~n-muench/ubuntu/oneiric/open-vm-tools/open-vm-tools.fix-836277

« back to all changes in this revision

Viewing changes to lib/resolution/resolution.c

  • Committer: Bazaar Package Importer
  • Author(s): Devid Antonio Filoni
  • Date: 2008-08-15 21:21:40 UTC
  • mfrom: (1.1.1 upstream)
  • Revision ID: james.westby@ubuntu.com-20080815212140-05fhxj8wroosysmj
Tags: 2008.08.08-109361-1ubuntu1
* Merge from Debian unstable (LP: #258393), remaining Ubuntu change:
  - add ubuntu_toolchain_FTBFS.dpatch patch, fix FTBFS
* Update ubuntu_toolchain_FTBFS.dpatch patch for the new version.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*********************************************************
 
2
 * Copyright (C) 2005 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
 * resolution.c --
 
21
 *
 
22
 *     Set of functions to handle guest screen resizing for
 
23
 *     vmware-{user,guestd}.
 
24
 */
 
25
 
 
26
#include <stdio.h>
 
27
#include <stdlib.h>
 
28
#include <string.h>
 
29
 
 
30
#include "vmware.h"
 
31
#include "vm_app.h"
 
32
#include "debug.h"
 
33
#include "rpcout.h"
 
34
#include "str.h"
 
35
#include "strutil.h"
 
36
 
 
37
#include "resolutionInt.h"
 
38
#include "resolution.h"
 
39
 
 
40
 
 
41
/*
 
42
 * Internal global variables
 
43
 */
 
44
 
 
45
 
 
46
/*
 
47
 * Describes current state of the library.
 
48
 */
 
49
ResolutionInfoType resolutionInfo = { .initialized = FALSE };
 
50
 
 
51
 
 
52
/*
 
53
 * Local function prototypes
 
54
 */
 
55
 
 
56
static Bool ResolutionResolutionSetCB(RpcInData *data);
 
57
static Bool ResolutionDisplayTopologySetCB(RpcInData *data);
 
58
 
 
59
 
 
60
/*
 
61
 * Global function definitions
 
62
 */
 
63
 
 
64
 
 
65
/*
 
66
 *-----------------------------------------------------------------------------
 
67
 *
 
68
 * Resolution_Init --
 
69
 *
 
70
 *      Initialize the guest resolution library.
 
71
 *
 
72
 * Results:
 
73
 *      TRUE on success, FALSE on failure (bad arguments?).
 
74
 *
 
75
 * Side effects:
 
76
 *      None.
 
77
 *
 
78
 *-----------------------------------------------------------------------------
 
79
 */
 
80
 
 
81
Bool
 
82
Resolution_Init(const char *tcloChannel,
 
83
                        // IN: TCLO channel name; used during capability registration
 
84
                        //     to tell the VMX whether Resolution_Set is being handled
 
85
                        //     by VMwareService/guestd or VMwareUser/vmware-user.
 
86
                InitHandle handle)
 
87
                        // IN: Back-end specific handle, if needed.  E.g., in the X11
 
88
                        //     case, this refers to the X11 display handle.
 
89
{
 
90
   // Shorter-named convenience alias.  I expect this to be optimized out.
 
91
   ResolutionInfoType *resInfo = &resolutionInfo;
 
92
 
 
93
   ASSERT(resInfo->initialized == FALSE);
 
94
   ASSERT((strcmp(tcloChannel, TOOLS_DAEMON_NAME) == 0) ||
 
95
          (strcmp(tcloChannel, TOOLS_DND_NAME)) == 0);
 
96
 
 
97
   /*
 
98
    * Blank out the resolutionInfo field, then copy user's arguments.
 
99
    */
 
100
   memset(resInfo, 0, sizeof *resInfo);
 
101
 
 
102
   strncpy(resInfo->tcloChannel, tcloChannel, sizeof resInfo->tcloChannel);
 
103
   resInfo->tcloChannel[sizeof resInfo->tcloChannel - 1] = '\0';
 
104
 
 
105
   if (!ResolutionBackendInit(handle)) {
 
106
      return FALSE;
 
107
   }
 
108
 
 
109
   resInfo->initialized = TRUE;
 
110
 
 
111
   return TRUE;
 
112
}
 
113
 
 
114
 
 
115
/*
 
116
 *-----------------------------------------------------------------------------
 
117
 *
 
118
 * Resolution_Cleanup --
 
119
 *
 
120
 *      Shutdown the library, free resources, etc.
 
121
 *
 
122
 * Results:
 
123
 *      None.
 
124
 *
 
125
 * Side effects:
 
126
 *      Resolution_* calls will fail until user next calls Resolution_Init().
 
127
 *
 
128
 *-----------------------------------------------------------------------------
 
129
 */
 
130
 
 
131
void
 
132
Resolution_Cleanup(void)
 
133
{
 
134
   // Shorter-named convenience alias.  I expect this to be optimized out.
 
135
   ResolutionInfoType *resInfo = &resolutionInfo;
 
136
 
 
137
   if (!resInfo->initialized) {
 
138
      return;
 
139
   }
 
140
 
 
141
   Resolution_UnregisterCaps();
 
142
   Resolution_CleanupBackdoor();
 
143
   ResolutionBackendCleanup();
 
144
 
 
145
   ASSERT(!resInfo->cbResolutionRegistered);
 
146
   ASSERT(!resInfo->cbTopologyRegistered);
 
147
   ASSERT(!resInfo->rpcIn);
 
148
}
 
149
 
 
150
 
 
151
/*-----------------------------------------------------------------------------
 
152
 *
 
153
 * Resolution_InitBackdoor --
 
154
 *
 
155
 *      Register RpcIn callbacks for supported/available RpcIn commands.
 
156
 *
 
157
 * Results:
 
158
 *      None.
 
159
 *
 
160
 * Side effects:
 
161
 *      Resolution_Set & DisplayTopology_Set callbacks may be registered.
 
162
 *
 
163
 *-----------------------------------------------------------------------------
 
164
 */
 
165
 
 
166
void
 
167
Resolution_InitBackdoor(RpcIn *rpcIn)
 
168
{
 
169
   // Shorter-named convenience alias.  I expect this to be optimized out.
 
170
   ResolutionInfoType *resInfo = &resolutionInfo;
 
171
 
 
172
   ASSERT(resInfo->initialized);
 
173
   ASSERT(rpcIn);
 
174
 
 
175
   resInfo->rpcIn = rpcIn;
 
176
 
 
177
   if (resInfo->canSetResolution) {
 
178
      RpcIn_RegisterCallbackEx(resInfo->rpcIn, "Resolution_Set",
 
179
                               ResolutionResolutionSetCB, NULL);
 
180
      resInfo->cbResolutionRegistered = TRUE;
 
181
   }
 
182
 
 
183
   if (resInfo->canSetTopology) {
 
184
      RpcIn_RegisterCallbackEx(resInfo->rpcIn, "DisplayTopology_Set",
 
185
                               ResolutionDisplayTopologySetCB, NULL);
 
186
      resInfo->cbTopologyRegistered = TRUE;
 
187
   }
 
188
}
 
189
 
 
190
 
 
191
/*
 
192
 *-----------------------------------------------------------------------------
 
193
 *
 
194
 * Resolution_CleanupBackdoor --
 
195
 *
 
196
 *      Unregisters RpcIn callbacks.
 
197
 *
 
198
 * Results:
 
199
 *      None.
 
200
 *
 
201
 * Side effects:
 
202
 *      Resolution callbacks are removed.
 
203
 *
 
204
 *-----------------------------------------------------------------------------
 
205
 */
 
206
 
 
207
void
 
208
Resolution_CleanupBackdoor(void)
 
209
{
 
210
   // Shorter-named convenience alias.  I expect this to be optimized out.
 
211
   ResolutionInfoType *resInfo = &resolutionInfo;
 
212
 
 
213
   if (!resInfo->initialized || !resInfo->rpcIn) {
 
214
      return;
 
215
   }
 
216
 
 
217
   if (resInfo->cbResolutionRegistered) {
 
218
      RpcIn_UnregisterCallback(resInfo->rpcIn, "Resolution_Set");
 
219
      resInfo->cbResolutionRegistered = FALSE;
 
220
   }
 
221
 
 
222
   if (resInfo->cbTopologyRegistered) {
 
223
      RpcIn_UnregisterCallback(resInfo->rpcIn, "DisplayTopology_Set");
 
224
      resInfo->cbTopologyRegistered = FALSE;
 
225
   }
 
226
 
 
227
   resInfo->rpcIn = FALSE;
 
228
}
 
229
 
 
230
 
 
231
/*
 
232
 *-----------------------------------------------------------------------------
 
233
 *
 
234
 * Resolution_RegisterCaps --
 
235
 *
 
236
 *      Register the "Resolution_Set" capability. Sometimes this needs to
 
237
 *      be done separately from the TCLO callback registration, so we
 
238
 *      provide it separately here.
 
239
 *
 
240
 * Results:
 
241
 *      TRUE on success
 
242
 *      FALSE on failure
 
243
 *
 
244
 * Side effects:
 
245
 *      None
 
246
 *
 
247
 *-----------------------------------------------------------------------------
 
248
 */
 
249
 
 
250
Bool
 
251
Resolution_RegisterCaps(void)
 
252
{
 
253
   // Shorter-named convenience alias.  I expect this to be optimized out.
 
254
   ResolutionInfoType *resInfo = &resolutionInfo;
 
255
 
 
256
   if (!resInfo->initialized) {
 
257
      return FALSE;
 
258
   }
 
259
 
 
260
   if (resInfo->canSetResolution) {
 
261
      if (!RpcOut_sendOne(NULL, NULL, "tools.capability.resolution_set 1")) {
 
262
         Debug("%s: Unable to register resolution set capability\n",
 
263
               __FUNCTION__);
 
264
         return FALSE;
 
265
      }
 
266
 
 
267
      if (!RpcOut_sendOne(NULL, NULL, "tools.capability.resolution_server %s 1",
 
268
                          resInfo->tcloChannel)) {
 
269
         Debug("%s: Unable to register resolution server capability\n",
 
270
               __FUNCTION__);
 
271
 
 
272
         /*
 
273
          * Note that we do not return false so that we stay backwards
 
274
          * compatible with old vmx code (Workstation 6/ESX 3.5) that doesn't
 
275
          * handle resolution_server.
 
276
          */
 
277
      }
 
278
   }
 
279
 
 
280
   if (resInfo->canSetTopology) {
 
281
      if (!RpcOut_sendOne(NULL, NULL, "tools.capability.display_topology_set 2")) {
 
282
         Debug("%s: Unable to register topology set capability\n",
 
283
               __FUNCTION__);
 
284
      }
 
285
 
 
286
      if (!RpcOut_sendOne(NULL, NULL, "tools.capability.display_global_offset 1")) {
 
287
         Debug("%s: Unable to register topology global offset capability\n",
 
288
               __FUNCTION__);
 
289
         /*
 
290
          * Ignore failures - host may not support these RPCs.
 
291
          */
 
292
      }
 
293
   }
 
294
 
 
295
   return TRUE;
 
296
}
 
297
 
 
298
 
 
299
 
 
300
 
 
301
/*
 
302
 *-----------------------------------------------------------------------------
 
303
 *
 
304
 * Resolution_UnregisterCaps --
 
305
 *
 
306
 *      Unregister the "Resolution_Set" and "DisplayTopology_Set" capabilities.
 
307
 *
 
308
 * Results:
 
309
 *      TRUE on success
 
310
 *      FALSE on failure
 
311
 *
 
312
 * Side effects:
 
313
 *      None
 
314
 *
 
315
 *-----------------------------------------------------------------------------
 
316
 */
 
317
 
 
318
Bool
 
319
Resolution_UnregisterCaps(void)
 
320
{
 
321
   // Shorter-named convenience alias.  I expect this to be optimized out.
 
322
   ResolutionInfoType *resInfo = &resolutionInfo;
 
323
 
 
324
   /*
 
325
    * RpcIn doesn't have an unregister facility, so all we need to do
 
326
    * here is unregister the capability.
 
327
    */
 
328
 
 
329
   if (!RpcOut_sendOne(NULL, NULL, "tools.capability.resolution_set 0")) {
 
330
      Debug("%s: Unable to unregister ResolutionSet capability\n",
 
331
            __FUNCTION__);
 
332
      return FALSE;
 
333
   }
 
334
 
 
335
   if (!RpcOut_sendOne(NULL, NULL, "tools.capability.resolution_server %s 0",
 
336
                       resInfo->tcloChannel)) {
 
337
      Debug("%s: Unable to unregister resolution server capability\n",
 
338
            __FUNCTION__);
 
339
 
 
340
      /*
 
341
       * Don't return false here so that an older vmx (Workstation 6/ESX 3.5)
 
342
       * that that supports resolution_set and not resolution_server will
 
343
       * still work.
 
344
       */
 
345
   }
 
346
 
 
347
   if (!RpcOut_sendOne(NULL, NULL, "tools.capability.display_topology_set 0") ||
 
348
       !RpcOut_sendOne(NULL, NULL, "tools.capability.display_global_offset 0")) {
 
349
      Debug("%s: Unable to unregister TopologySet capability\n",
 
350
            __FUNCTION__);
 
351
      /*
 
352
       * Ignore failures - host may not support these RPCs.
 
353
       */
 
354
   }
 
355
 
 
356
   return TRUE;
 
357
}
 
358
 
 
359
 
 
360
/*
 
361
 * Local function definitions
 
362
 */
 
363
 
 
364
 
 
365
/*
 
366
 *-----------------------------------------------------------------------------
 
367
 *
 
368
 * ResolutionResolutionSetCB  --
 
369
 *
 
370
 *      Handler for TCLO 'Resolution_Set'.
 
371
 *
 
372
 * Results:
 
373
 *      TRUE if we can reply, FALSE otherwise.
 
374
 *
 
375
 * Side effects:
 
376
 *      None.
 
377
 *
 
378
 *-----------------------------------------------------------------------------
 
379
 */
 
380
 
 
381
static Bool
 
382
ResolutionResolutionSetCB(RpcInData *data)      // IN/OUT:
 
383
{
 
384
   uint32 width = 0 ;
 
385
   uint32 height = 0;
 
386
   unsigned int index = 0;
 
387
   Bool retval = FALSE;
 
388
 
 
389
   /* parse the width and height */
 
390
   if (!StrUtil_GetNextUintToken(&width, &index, data->args, " ")) {
 
391
      goto invalid_arguments;
 
392
   }
 
393
   if (!StrUtil_GetNextUintToken(&height, &index, data->args, "")) {
 
394
      goto invalid_arguments;
 
395
   }
 
396
 
 
397
   retval = ResolutionSetResolution(width, height);
 
398
 
 
399
invalid_arguments:
 
400
   return RPCIN_SETRETVALS(data, retval ? "" : "Invalid arguments", retval);
 
401
}
 
402
 
 
403
 
 
404
/*
 
405
 *-----------------------------------------------------------------------------
 
406
 *
 
407
 * ResolutionDisplayTopologySetCB  --
 
408
 *
 
409
 *      Handler for TCLO 'DisplayTopology_Set'.
 
410
 *
 
411
 *      Routine unmarshals RPC arguments and passes over to back-end
 
412
 *      TopologySet().
 
413
 *
 
414
 * Results:
 
415
 *      TRUE if we can reply, FALSE otherwise.
 
416
 *
 
417
 * Side effects:
 
418
 *      None.
 
419
 *
 
420
 *-----------------------------------------------------------------------------
 
421
 */
 
422
 
 
423
static Bool
 
424
ResolutionDisplayTopologySetCB(RpcInData *data) // IN/OUT:
 
425
{
 
426
   DisplayTopologyInfo *displays = NULL;
 
427
   unsigned int count, i;
 
428
   Bool success = FALSE;
 
429
   const char *p;
 
430
 
 
431
   /*
 
432
    * The argument string will look something like:
 
433
    *   <count> [ , <x> <y> <w> <h> ] * count.
 
434
    *
 
435
    * e.g.
 
436
    *    3 , 0 0 640 480 , 640 0 800 600 , 0 480 640 480
 
437
    */
 
438
 
 
439
   if (sscanf(data->args, "%u", &count) != 1) {
 
440
      return RPCIN_SETRETVALS(data,
 
441
                              "Invalid arguments. Expected \"count\"",
 
442
                              FALSE);
 
443
   }
 
444
 
 
445
 
 
446
 
 
447
   displays = malloc(sizeof *displays * count);
 
448
   if (!displays) {
 
449
      RPCIN_SETRETVALS(data,
 
450
                       "Failed to alloc buffer for display info",
 
451
                       FALSE);
 
452
      goto out;
 
453
   }
 
454
 
 
455
   for (p = data->args, i = 0; i < count; i++) {
 
456
      p = strchr(p, ',');
 
457
      if (!p) {
 
458
         RPCIN_SETRETVALS(data,
 
459
                          "Expected comma separated display list",
 
460
                          FALSE);
 
461
         goto out;
 
462
      }
 
463
      p++; /* Skip past the , */
 
464
 
 
465
      if (sscanf(p, " %d %d %d %d ", &displays[i].x,
 
466
                 &displays[i].y, &displays[i].width, &displays[i].height) != 4) {
 
467
         RPCIN_SETRETVALS(data,
 
468
                          "Expected x, y, w, h in display entry",
 
469
                          FALSE);
 
470
         goto out;
 
471
      }
 
472
   }
 
473
 
 
474
   success = ResolutionSetTopology(count, displays);
 
475
 
 
476
   RPCIN_SETRETVALS(data, success ? "" : "ResolutionSetTopology failed", success);
 
477
 
 
478
out:
 
479
   free(displays);
 
480
   return success;
 
481
}