1 /************************************************************
2
3 Copyright 1987, 1989, 1998 The Open Group
4
5 Permission to use, copy, modify, distribute, and sell this software and its
6 documentation for any purpose is hereby granted without fee, provided that
7 the above copyright notice appear in all copies and that both that
8 copyright notice and this permission notice appear in supporting
9 documentation.
10
11 The above copyright notice and this permission notice shall be included in
12 all copies or substantial portions of the Software.
13
14 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
20
21 Except as contained in this notice, the name of The Open Group shall not be
22 used in advertising or otherwise to promote the sale, use or other dealings
23 in this Software without prior written authorization from The Open Group.
24
25 Copyright 1987, 1989 by Digital Equipment Corporation, Maynard, Massachusetts.
26
27 All Rights Reserved
28
29 Permission to use, copy, modify, and distribute this software and its
30 documentation for any purpose and without fee is hereby granted,
31 provided that the above copyright notice appear in all copies and that
32 both that copyright notice and this permission notice appear in
33 supporting documentation, and that the name of Digital not be
34 used in advertising or publicity pertaining to distribution of the
35 software without specific, written prior permission.
36
37 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
38 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
39 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
40 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
41 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
42 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
43 SOFTWARE.
44
45 ********************************************************/
46
47 /* The panoramix components contained the following notice */
48 /*****************************************************************
49
50 Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
51
52 Permission is hereby granted, free of charge, to any person obtaining a copy
53 of this software and associated documentation files (the "Software"), to deal
54 in the Software without restriction, including without limitation the rights
55 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
56 copies of the Software.
57
58 The above copyright notice and this permission notice shall be included in
59 all copies or substantial portions of the Software.
60
61 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
62 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
63 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
64 DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
65 BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
66 WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
67 IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
68
69 Except as contained in this notice, the name of Digital Equipment Corporation
70 shall not be used in advertising or otherwise to promote the sale, use or other
71 dealings in this Software without prior written authorization from Digital
72 Equipment Corporation.
73
74 ******************************************************************/
75
76 /* XSERVER_DTRACE additions:
77 * Copyright (c) 2005-2006, Oracle and/or its affiliates. All rights reserved.
78 *
79 * Permission is hereby granted, free of charge, to any person obtaining a
80 * copy of this software and associated documentation files (the "Software"),
81 * to deal in the Software without restriction, including without limitation
82 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
83 * and/or sell copies of the Software, and to permit persons to whom the
84 * Software is furnished to do so, subject to the following conditions:
85 *
86 * The above copyright notice and this permission notice (including the next
87 * paragraph) shall be included in all copies or substantial portions of the
88 * Software.
89 *
90 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
91 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
92 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
93 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
94 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
95 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
96 * DEALINGS IN THE SOFTWARE.
97 */
98
99 #ifdef HAVE_DIX_CONFIG_H
100 #include <dix-config.h>
101 #include <version-config.h>
102 #endif
103
104 #ifdef PANORAMIX_DEBUG
105 #include <stdio.h>
106 int ProcInitialConnection();
107 #endif
108
109 #include "windowstr.h"
110 #include <X11/fonts/fontstruct.h>
111 #include <X11/fonts/libxfont2.h>
112 #include "dixfontstr.h"
113 #include "gcstruct.h"
114 #include "selection.h"
115 #include "colormapst.h"
116 #include "cursorstr.h"
117 #include "scrnintstr.h"
118 #include "opaque.h"
119 #include "input.h"
120 #include "servermd.h"
121 #include "extnsionst.h"
122 #include "dixfont.h"
123 #include "dispatch.h"
124 #include "swaprep.h"
125 #include "swapreq.h"
126 #include "privates.h"
127 #include "xace.h"
128 #include "inputstr.h"
129 #include "xkbsrv.h"
130 #include "site.h"
131 #include "client.h"
132
133 #ifdef XSERVER_DTRACE
134 #include "registry.h"
135 #include "probes.h"
136 #endif
137
138 #define mskcnt ((MAXCLIENTS + 31) / 32)
139 #define BITMASK(i) (1U << ((i) & 31))
140 #define MASKIDX(i) ((i) >> 5)
141 #define MASKWORD(buf, i) buf[MASKIDX(i)]
142 #define BITSET(buf, i) MASKWORD(buf, i) |= BITMASK(i)
143 #define BITCLEAR(buf, i) MASKWORD(buf, i) &= ~BITMASK(i)
144 #define GETBIT(buf, i) (MASKWORD(buf, i) & BITMASK(i))
145
146 xConnSetupPrefix connSetupPrefix;
147
148 PaddingInfo PixmapWidthPaddingInfo[33];
149
150 static ClientPtr grabClient;
151
152 #define GrabNone 0
153 #define GrabActive 1
154 static int grabState = GrabNone;
155 static long grabWaiters[mskcnt];
156 CallbackListPtr ServerGrabCallback = NULL;
157 HWEventQueuePtr checkForInput[2];
158 int connBlockScreenStart;
159
160 static void KillAllClients(void);
161
162 static int nextFreeClientID; /* always MIN free client ID */
163
164 static int nClients; /* number of authorized clients */
165
166 CallbackListPtr ClientStateCallback;
167
168 /* dispatchException & isItTimeToYield must be declared volatile since they
169 * are modified by signal handlers - otherwise optimizer may assume it doesn't
170 * need to actually check value in memory when used and may miss changes from
171 * signal handlers.
172 */
173 volatile char dispatchException = 0;
174 volatile char isItTimeToYield;
175
176 #define SAME_SCREENS(a, b) (\
177 (a.pScreen == b.pScreen))
178
179 void
SetInputCheck(HWEventQueuePtr c0,HWEventQueuePtr c1)180 SetInputCheck(HWEventQueuePtr c0, HWEventQueuePtr c1)
181 {
182 checkForInput[0] = c0;
183 checkForInput[1] = c1;
184 }
185
186 void
UpdateCurrentTime(void)187 UpdateCurrentTime(void)
188 {
189 TimeStamp systime;
190
191 /* To avoid time running backwards, we must call GetTimeInMillis before
192 * calling ProcessInputEvents.
193 */
194 systime.months = currentTime.months;
195 systime.milliseconds = GetTimeInMillis();
196 if (systime.milliseconds < currentTime.milliseconds)
197 systime.months++;
198 if (InputCheckPending())
199 ProcessInputEvents();
200 if (CompareTimeStamps(systime, currentTime) == LATER)
201 currentTime = systime;
202 }
203
204 /* Like UpdateCurrentTime, but can't call ProcessInputEvents */
205 void
UpdateCurrentTimeIf(void)206 UpdateCurrentTimeIf(void)
207 {
208 TimeStamp systime;
209
210 systime.months = currentTime.months;
211 systime.milliseconds = GetTimeInMillis();
212 if (systime.milliseconds < currentTime.milliseconds)
213 systime.months++;
214 if (CompareTimeStamps(systime, currentTime) == LATER)
215 currentTime = systime;
216 }
217
218 #undef SMART_DEBUG
219
220 /* in milliseconds */
221 #define SMART_SCHEDULE_DEFAULT_INTERVAL 5
222 #define SMART_SCHEDULE_MAX_SLICE 15
223
224 #ifdef HAVE_SETITIMER
225 Bool SmartScheduleSignalEnable = TRUE;
226 #endif
227
228 long SmartScheduleSlice = SMART_SCHEDULE_DEFAULT_INTERVAL;
229 long SmartScheduleInterval = SMART_SCHEDULE_DEFAULT_INTERVAL;
230 long SmartScheduleMaxSlice = SMART_SCHEDULE_MAX_SLICE;
231 long SmartScheduleTime;
232 int SmartScheduleLatencyLimited = 0;
233 static ClientPtr SmartLastClient;
234 static int SmartLastIndex[SMART_MAX_PRIORITY - SMART_MIN_PRIORITY + 1];
235
236 #ifdef SMART_DEBUG
237 long SmartLastPrint;
238 #endif
239
240 void Dispatch(void);
241
242 static struct xorg_list ready_clients;
243 static struct xorg_list saved_ready_clients;
244 struct xorg_list output_pending_clients;
245
246 static void
init_client_ready(void)247 init_client_ready(void)
248 {
249 xorg_list_init(&ready_clients);
250 xorg_list_init(&saved_ready_clients);
251 xorg_list_init(&output_pending_clients);
252 }
253
254 Bool
clients_are_ready(void)255 clients_are_ready(void)
256 {
257 return !xorg_list_is_empty(&ready_clients);
258 }
259
260 /* Client has requests queued or data on the network */
261 void
mark_client_ready(ClientPtr client)262 mark_client_ready(ClientPtr client)
263 {
264 if (xorg_list_is_empty(&client->ready))
265 xorg_list_append(&client->ready, &ready_clients);
266 }
267
268 /*
269 * Client has requests queued or data on the network, but awaits a
270 * server grab release
271 */
mark_client_saved_ready(ClientPtr client)272 void mark_client_saved_ready(ClientPtr client)
273 {
274 if (xorg_list_is_empty(&client->ready))
275 xorg_list_append(&client->ready, &saved_ready_clients);
276 }
277
278 /* Client has no requests queued and no data on network */
279 void
mark_client_not_ready(ClientPtr client)280 mark_client_not_ready(ClientPtr client)
281 {
282 xorg_list_del(&client->ready);
283 }
284
285 static void
mark_client_grab(ClientPtr grab)286 mark_client_grab(ClientPtr grab)
287 {
288 ClientPtr client, tmp;
289
290 xorg_list_for_each_entry_safe(client, tmp, &ready_clients, ready) {
291 if (client != grab) {
292 xorg_list_del(&client->ready);
293 xorg_list_append(&client->ready, &saved_ready_clients);
294 }
295 }
296 }
297
298 static void
mark_client_ungrab(void)299 mark_client_ungrab(void)
300 {
301 ClientPtr client, tmp;
302
303 xorg_list_for_each_entry_safe(client, tmp, &saved_ready_clients, ready) {
304 xorg_list_del(&client->ready);
305 xorg_list_append(&client->ready, &ready_clients);
306 }
307 }
308
309 static ClientPtr
SmartScheduleClient(void)310 SmartScheduleClient(void)
311 {
312 ClientPtr pClient, best = NULL;
313 int bestRobin, robin;
314 long now = SmartScheduleTime;
315 long idle;
316 int nready = 0;
317
318 bestRobin = 0;
319 idle = 2 * SmartScheduleSlice;
320
321 xorg_list_for_each_entry(pClient, &ready_clients, ready) {
322 nready++;
323
324 /* Praise clients which haven't run in a while */
325 if ((now - pClient->smart_stop_tick) >= idle) {
326 if (pClient->smart_priority < 0)
327 pClient->smart_priority++;
328 }
329
330 /* check priority to select best client */
331 robin =
332 (pClient->index -
333 SmartLastIndex[pClient->smart_priority -
334 SMART_MIN_PRIORITY]) & 0xff;
335
336 /* pick the best client */
337 if (!best ||
338 pClient->priority > best->priority ||
339 (pClient->priority == best->priority &&
340 (pClient->smart_priority > best->smart_priority ||
341 (pClient->smart_priority == best->smart_priority && robin > bestRobin))))
342 {
343 best = pClient;
344 bestRobin = robin;
345 }
346 #ifdef SMART_DEBUG
347 if ((now - SmartLastPrint) >= 5000)
348 fprintf(stderr, " %2d: %3d", pClient->index, pClient->smart_priority);
349 #endif
350 }
351 #ifdef SMART_DEBUG
352 if ((now - SmartLastPrint) >= 5000) {
353 fprintf(stderr, " use %2d\n", best->index);
354 SmartLastPrint = now;
355 }
356 #endif
357 SmartLastIndex[best->smart_priority - SMART_MIN_PRIORITY] = best->index;
358 /*
359 * Set current client pointer
360 */
361 if (SmartLastClient != best) {
362 best->smart_start_tick = now;
363 SmartLastClient = best;
364 }
365 /*
366 * Adjust slice
367 */
368 if (nready == 1 && SmartScheduleLatencyLimited == 0) {
369 /*
370 * If it's been a long time since another client
371 * has run, bump the slice up to get maximal
372 * performance from a single client
373 */
374 if ((now - best->smart_start_tick) > 1000 &&
375 SmartScheduleSlice < SmartScheduleMaxSlice) {
376 SmartScheduleSlice += SmartScheduleInterval;
377 }
378 }
379 else {
380 SmartScheduleSlice = SmartScheduleInterval;
381 }
382 return best;
383 }
384
385 void
EnableLimitedSchedulingLatency(void)386 EnableLimitedSchedulingLatency(void)
387 {
388 ++SmartScheduleLatencyLimited;
389 SmartScheduleSlice = SmartScheduleInterval;
390 }
391
392 void
DisableLimitedSchedulingLatency(void)393 DisableLimitedSchedulingLatency(void)
394 {
395 --SmartScheduleLatencyLimited;
396
397 /* protect against bugs */
398 if (SmartScheduleLatencyLimited < 0)
399 SmartScheduleLatencyLimited = 0;
400 }
401
402 void
Dispatch(void)403 Dispatch(void)
404 {
405 int result;
406 ClientPtr client;
407 long start_tick;
408
409 nextFreeClientID = 1;
410 nClients = 0;
411
412 SmartScheduleSlice = SmartScheduleInterval;
413 init_client_ready();
414
415 while (!dispatchException) {
416 if (InputCheckPending()) {
417 ProcessInputEvents();
418 FlushIfCriticalOutputPending();
419 }
420
421 if (!WaitForSomething(clients_are_ready()))
422 continue;
423
424 /*****************
425 * Handle events in round robin fashion, doing input between
426 * each round
427 *****************/
428
429 if (!dispatchException && clients_are_ready()) {
430 client = SmartScheduleClient();
431
432 isItTimeToYield = FALSE;
433
434 start_tick = SmartScheduleTime;
435 while (!isItTimeToYield) {
436 if (InputCheckPending())
437 ProcessInputEvents();
438
439 FlushIfCriticalOutputPending();
440 if ((SmartScheduleTime - start_tick) >= SmartScheduleSlice)
441 {
442 /* Penalize clients which consume ticks */
443 if (client->smart_priority > SMART_MIN_PRIORITY)
444 client->smart_priority--;
445 break;
446 }
447
448 /* now, finally, deal with client requests */
449 result = ReadRequestFromClient(client);
450 if (result <= 0) {
451 if (result < 0)
452 CloseDownClient(client);
453 break;
454 }
455
456 client->sequence++;
457 client->majorOp = ((xReq *) client->requestBuffer)->reqType;
458 client->minorOp = 0;
459 if (client->majorOp >= EXTENSION_BASE) {
460 ExtensionEntry *ext = GetExtensionEntry(client->majorOp);
461
462 if (ext)
463 client->minorOp = ext->MinorOpcode(client);
464 }
465 #ifdef XSERVER_DTRACE
466 if (XSERVER_REQUEST_START_ENABLED())
467 XSERVER_REQUEST_START(LookupMajorName(client->majorOp),
468 client->majorOp,
469 ((xReq *) client->requestBuffer)->length,
470 client->index,
471 client->requestBuffer);
472 #endif
473 if (result > (maxBigRequestSize << 2))
474 result = BadLength;
475 else {
476 result = XaceHookDispatch(client, client->majorOp);
477 if (result == Success)
478 result =
479 (*client->requestVector[client->majorOp]) (client);
480 }
481 if (!SmartScheduleSignalEnable)
482 SmartScheduleTime = GetTimeInMillis();
483
484 #ifdef XSERVER_DTRACE
485 if (XSERVER_REQUEST_DONE_ENABLED())
486 XSERVER_REQUEST_DONE(LookupMajorName(client->majorOp),
487 client->majorOp, client->sequence,
488 client->index, result);
489 #endif
490
491 if (client->noClientException != Success) {
492 CloseDownClient(client);
493 break;
494 }
495 else if (result != Success) {
496 SendErrorToClient(client, client->majorOp,
497 client->minorOp,
498 client->errorValue, result);
499 break;
500 }
501 }
502 FlushAllOutput();
503 if (client == SmartLastClient)
504 client->smart_stop_tick = SmartScheduleTime;
505 }
506 dispatchException &= ~DE_PRIORITYCHANGE;
507 }
508 #if defined(DDXBEFORERESET)
509 ddxBeforeReset();
510 #endif
511 KillAllClients();
512 dispatchException &= ~DE_RESET;
513 SmartScheduleLatencyLimited = 0;
514 ResetOsBuffers();
515 }
516
517 static int VendorRelease = VENDOR_RELEASE;
518 static const char *VendorString = VENDOR_NAME;
519
520 void
SetVendorRelease(int release)521 SetVendorRelease(int release)
522 {
523 VendorRelease = release;
524 }
525
526 void
SetVendorString(const char * vendor)527 SetVendorString(const char *vendor)
528 {
529 VendorString = vendor;
530 }
531
532 Bool
CreateConnectionBlock(void)533 CreateConnectionBlock(void)
534 {
535 xConnSetup setup;
536 xWindowRoot root;
537 xDepth depth;
538 xVisualType visual;
539 xPixmapFormat format;
540 unsigned long vid;
541 int i, j, k, lenofblock, sizesofar = 0;
542 char *pBuf;
543
544 memset(&setup, 0, sizeof(xConnSetup));
545 /* Leave off the ridBase and ridMask, these must be sent with
546 connection */
547
548 setup.release = VendorRelease;
549 /*
550 * per-server image and bitmap parameters are defined in Xmd.h
551 */
552 setup.imageByteOrder = screenInfo.imageByteOrder;
553
554 setup.bitmapScanlineUnit = screenInfo.bitmapScanlineUnit;
555 setup.bitmapScanlinePad = screenInfo.bitmapScanlinePad;
556
557 setup.bitmapBitOrder = screenInfo.bitmapBitOrder;
558 setup.motionBufferSize = NumMotionEvents();
559 setup.numRoots = screenInfo.numScreens;
560 setup.nbytesVendor = strlen(VendorString);
561 setup.numFormats = screenInfo.numPixmapFormats;
562 setup.maxRequestSize = MAX_REQUEST_SIZE;
563 QueryMinMaxKeyCodes(&setup.minKeyCode, &setup.maxKeyCode);
564
565 lenofblock = sizeof(xConnSetup) +
566 pad_to_int32(setup.nbytesVendor) +
567 (setup.numFormats * sizeof(xPixmapFormat)) +
568 (setup.numRoots * sizeof(xWindowRoot));
569 ConnectionInfo = malloc(lenofblock);
570 if (!ConnectionInfo)
571 return FALSE;
572
573 memmove(ConnectionInfo, (char *) &setup, sizeof(xConnSetup));
574 sizesofar = sizeof(xConnSetup);
575 pBuf = ConnectionInfo + sizeof(xConnSetup);
576
577 memmove(pBuf, VendorString, (int) setup.nbytesVendor);
578 sizesofar += setup.nbytesVendor;
579 pBuf += setup.nbytesVendor;
580 i = padding_for_int32(setup.nbytesVendor);
581 sizesofar += i;
582 while (--i >= 0)
583 *pBuf++ = 0;
584
585 memset(&format, 0, sizeof(xPixmapFormat));
586 for (i = 0; i < screenInfo.numPixmapFormats; i++) {
587 format.depth = screenInfo.formats[i].depth;
588 format.bitsPerPixel = screenInfo.formats[i].bitsPerPixel;
589 format.scanLinePad = screenInfo.formats[i].scanlinePad;
590 memmove(pBuf, (char *) &format, sizeof(xPixmapFormat));
591 pBuf += sizeof(xPixmapFormat);
592 sizesofar += sizeof(xPixmapFormat);
593 }
594
595 connBlockScreenStart = sizesofar;
596 memset(&depth, 0, sizeof(xDepth));
597 memset(&visual, 0, sizeof(xVisualType));
598 for (i = 0; i < screenInfo.numScreens; i++) {
599 ScreenPtr pScreen;
600 DepthPtr pDepth;
601 VisualPtr pVisual;
602
603 pScreen = screenInfo.screens[i];
604 root.windowId = pScreen->root->drawable.id;
605 root.defaultColormap = pScreen->defColormap;
606 root.whitePixel = pScreen->whitePixel;
607 root.blackPixel = pScreen->blackPixel;
608 root.currentInputMask = 0; /* filled in when sent */
609 root.pixWidth = pScreen->width;
610 root.pixHeight = pScreen->height;
611 root.mmWidth = pScreen->mmWidth;
612 root.mmHeight = pScreen->mmHeight;
613 root.minInstalledMaps = pScreen->minInstalledCmaps;
614 root.maxInstalledMaps = pScreen->maxInstalledCmaps;
615 root.rootVisualID = pScreen->rootVisual;
616 root.backingStore = pScreen->backingStoreSupport;
617 root.saveUnders = FALSE;
618 root.rootDepth = pScreen->rootDepth;
619 root.nDepths = pScreen->numDepths;
620 memmove(pBuf, (char *) &root, sizeof(xWindowRoot));
621 sizesofar += sizeof(xWindowRoot);
622 pBuf += sizeof(xWindowRoot);
623
624 pDepth = pScreen->allowedDepths;
625 for (j = 0; j < pScreen->numDepths; j++, pDepth++) {
626 lenofblock += sizeof(xDepth) +
627 (pDepth->numVids * sizeof(xVisualType));
628 pBuf = (char *) realloc(ConnectionInfo, lenofblock);
629 if (!pBuf) {
630 free(ConnectionInfo);
631 return FALSE;
632 }
633 ConnectionInfo = pBuf;
634 pBuf += sizesofar;
635 depth.depth = pDepth->depth;
636 depth.nVisuals = pDepth->numVids;
637 memmove(pBuf, (char *) &depth, sizeof(xDepth));
638 pBuf += sizeof(xDepth);
639 sizesofar += sizeof(xDepth);
640 for (k = 0; k < pDepth->numVids; k++) {
641 vid = pDepth->vids[k];
642 for (pVisual = pScreen->visuals;
643 pVisual->vid != vid; pVisual++);
644 visual.visualID = vid;
645 visual.class = pVisual->class;
646 visual.bitsPerRGB = pVisual->bitsPerRGBValue;
647 visual.colormapEntries = pVisual->ColormapEntries;
648 visual.redMask = pVisual->redMask;
649 visual.greenMask = pVisual->greenMask;
650 visual.blueMask = pVisual->blueMask;
651 memmove(pBuf, (char *) &visual, sizeof(xVisualType));
652 pBuf += sizeof(xVisualType);
653 sizesofar += sizeof(xVisualType);
654 }
655 }
656 }
657 connSetupPrefix.success = xTrue;
658 connSetupPrefix.length = lenofblock / 4;
659 connSetupPrefix.majorVersion = X_PROTOCOL;
660 connSetupPrefix.minorVersion = X_PROTOCOL_REVISION;
661 return TRUE;
662 }
663
664 int
ProcBadRequest(ClientPtr client)665 ProcBadRequest(ClientPtr client)
666 {
667 return BadRequest;
668 }
669
670 int
ProcCreateWindow(ClientPtr client)671 ProcCreateWindow(ClientPtr client)
672 {
673 WindowPtr pParent, pWin;
674
675 REQUEST(xCreateWindowReq);
676 int len, rc;
677
678 REQUEST_AT_LEAST_SIZE(xCreateWindowReq);
679
680 LEGAL_NEW_RESOURCE(stuff->wid, client);
681 rc = dixLookupWindow(&pParent, stuff->parent, client, DixAddAccess);
682 if (rc != Success)
683 return rc;
684 len = client->req_len - bytes_to_int32(sizeof(xCreateWindowReq));
685 if (Ones(stuff->mask) != len)
686 return BadLength;
687 if (!stuff->width || !stuff->height) {
688 client->errorValue = 0;
689 return BadValue;
690 }
691 pWin = CreateWindow(stuff->wid, pParent, stuff->x,
692 stuff->y, stuff->width, stuff->height,
693 stuff->borderWidth, stuff->class,
694 stuff->mask, (XID *) &stuff[1],
695 (int) stuff->depth, client, stuff->visual, &rc);
696 if (pWin) {
697 Mask mask = pWin->eventMask;
698
699 pWin->eventMask = 0; /* subterfuge in case AddResource fails */
700 if (!AddResource(stuff->wid, RT_WINDOW, (void *) pWin))
701 return BadAlloc;
702 pWin->eventMask = mask;
703 }
704 return rc;
705 }
706
707 int
ProcChangeWindowAttributes(ClientPtr client)708 ProcChangeWindowAttributes(ClientPtr client)
709 {
710 WindowPtr pWin;
711
712 REQUEST(xChangeWindowAttributesReq);
713 int len, rc;
714 Mask access_mode = 0;
715
716 REQUEST_AT_LEAST_SIZE(xChangeWindowAttributesReq);
717 access_mode |= (stuff->valueMask & CWEventMask) ? DixReceiveAccess : 0;
718 access_mode |= (stuff->valueMask & ~CWEventMask) ? DixSetAttrAccess : 0;
719 rc = dixLookupWindow(&pWin, stuff->window, client, access_mode);
720 if (rc != Success)
721 return rc;
722 len = client->req_len - bytes_to_int32(sizeof(xChangeWindowAttributesReq));
723 if (len != Ones(stuff->valueMask))
724 return BadLength;
725 return ChangeWindowAttributes(pWin,
726 stuff->valueMask, (XID *) &stuff[1], client);
727 }
728
729 int
ProcGetWindowAttributes(ClientPtr client)730 ProcGetWindowAttributes(ClientPtr client)
731 {
732 WindowPtr pWin;
733
734 REQUEST(xResourceReq);
735 xGetWindowAttributesReply wa;
736 int rc;
737
738 REQUEST_SIZE_MATCH(xResourceReq);
739 rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess);
740 if (rc != Success)
741 return rc;
742 memset(&wa, 0, sizeof(xGetWindowAttributesReply));
743 GetWindowAttributes(pWin, client, &wa);
744 WriteReplyToClient(client, sizeof(xGetWindowAttributesReply), &wa);
745 return Success;
746 }
747
748 int
ProcDestroyWindow(ClientPtr client)749 ProcDestroyWindow(ClientPtr client)
750 {
751 WindowPtr pWin;
752
753 REQUEST(xResourceReq);
754 int rc;
755
756 REQUEST_SIZE_MATCH(xResourceReq);
757 rc = dixLookupWindow(&pWin, stuff->id, client, DixDestroyAccess);
758 if (rc != Success)
759 return rc;
760 if (pWin->parent) {
761 rc = dixLookupWindow(&pWin, pWin->parent->drawable.id, client,
762 DixRemoveAccess);
763 if (rc != Success)
764 return rc;
765 FreeResource(stuff->id, RT_NONE);
766 }
767 return Success;
768 }
769
770 int
ProcDestroySubwindows(ClientPtr client)771 ProcDestroySubwindows(ClientPtr client)
772 {
773 WindowPtr pWin;
774
775 REQUEST(xResourceReq);
776 int rc;
777
778 REQUEST_SIZE_MATCH(xResourceReq);
779 rc = dixLookupWindow(&pWin, stuff->id, client, DixRemoveAccess);
780 if (rc != Success)
781 return rc;
782 DestroySubwindows(pWin, client);
783 return Success;
784 }
785
786 int
ProcChangeSaveSet(ClientPtr client)787 ProcChangeSaveSet(ClientPtr client)
788 {
789 WindowPtr pWin;
790
791 REQUEST(xChangeSaveSetReq);
792 int rc;
793
794 REQUEST_SIZE_MATCH(xChangeSaveSetReq);
795 rc = dixLookupWindow(&pWin, stuff->window, client, DixManageAccess);
796 if (rc != Success)
797 return rc;
798 if (client->clientAsMask == (CLIENT_BITS(pWin->drawable.id)))
799 return BadMatch;
800 if ((stuff->mode == SetModeInsert) || (stuff->mode == SetModeDelete))
801 return AlterSaveSetForClient(client, pWin, stuff->mode, FALSE, TRUE);
802 client->errorValue = stuff->mode;
803 return BadValue;
804 }
805
806 int
ProcReparentWindow(ClientPtr client)807 ProcReparentWindow(ClientPtr client)
808 {
809 WindowPtr pWin, pParent;
810
811 REQUEST(xReparentWindowReq);
812 int rc;
813
814 REQUEST_SIZE_MATCH(xReparentWindowReq);
815 rc = dixLookupWindow(&pWin, stuff->window, client, DixManageAccess);
816 if (rc != Success)
817 return rc;
818 rc = dixLookupWindow(&pParent, stuff->parent, client, DixAddAccess);
819 if (rc != Success)
820 return rc;
821 if (!SAME_SCREENS(pWin->drawable, pParent->drawable))
822 return BadMatch;
823 if ((pWin->backgroundState == ParentRelative) &&
824 (pParent->drawable.depth != pWin->drawable.depth))
825 return BadMatch;
826 if ((pWin->drawable.class != InputOnly) &&
827 (pParent->drawable.class == InputOnly))
828 return BadMatch;
829 return ReparentWindow(pWin, pParent,
830 (short) stuff->x, (short) stuff->y, client);
831 }
832
833 int
ProcMapWindow(ClientPtr client)834 ProcMapWindow(ClientPtr client)
835 {
836 WindowPtr pWin;
837
838 REQUEST(xResourceReq);
839 int rc;
840
841 REQUEST_SIZE_MATCH(xResourceReq);
842 rc = dixLookupWindow(&pWin, stuff->id, client, DixShowAccess);
843 if (rc != Success)
844 return rc;
845 MapWindow(pWin, client);
846 /* update cache to say it is mapped */
847 return Success;
848 }
849
850 int
ProcMapSubwindows(ClientPtr client)851 ProcMapSubwindows(ClientPtr client)
852 {
853 WindowPtr pWin;
854
855 REQUEST(xResourceReq);
856 int rc;
857
858 REQUEST_SIZE_MATCH(xResourceReq);
859 rc = dixLookupWindow(&pWin, stuff->id, client, DixListAccess);
860 if (rc != Success)
861 return rc;
862 MapSubwindows(pWin, client);
863 /* update cache to say it is mapped */
864 return Success;
865 }
866
867 int
ProcUnmapWindow(ClientPtr client)868 ProcUnmapWindow(ClientPtr client)
869 {
870 WindowPtr pWin;
871
872 REQUEST(xResourceReq);
873 int rc;
874
875 REQUEST_SIZE_MATCH(xResourceReq);
876 rc = dixLookupWindow(&pWin, stuff->id, client, DixHideAccess);
877 if (rc != Success)
878 return rc;
879 UnmapWindow(pWin, FALSE);
880 /* update cache to say it is mapped */
881 return Success;
882 }
883
884 int
ProcUnmapSubwindows(ClientPtr client)885 ProcUnmapSubwindows(ClientPtr client)
886 {
887 WindowPtr pWin;
888
889 REQUEST(xResourceReq);
890 int rc;
891
892 REQUEST_SIZE_MATCH(xResourceReq);
893 rc = dixLookupWindow(&pWin, stuff->id, client, DixListAccess);
894 if (rc != Success)
895 return rc;
896 UnmapSubwindows(pWin);
897 return Success;
898 }
899
900 int
ProcConfigureWindow(ClientPtr client)901 ProcConfigureWindow(ClientPtr client)
902 {
903 WindowPtr pWin;
904
905 REQUEST(xConfigureWindowReq);
906 int len, rc;
907
908 REQUEST_AT_LEAST_SIZE(xConfigureWindowReq);
909 rc = dixLookupWindow(&pWin, stuff->window, client,
910 DixManageAccess | DixSetAttrAccess);
911 if (rc != Success)
912 return rc;
913 len = client->req_len - bytes_to_int32(sizeof(xConfigureWindowReq));
914 if (Ones((Mask) stuff->mask) != len)
915 return BadLength;
916 return ConfigureWindow(pWin, (Mask) stuff->mask, (XID *) &stuff[1], client);
917 }
918
919 int
ProcCirculateWindow(ClientPtr client)920 ProcCirculateWindow(ClientPtr client)
921 {
922 WindowPtr pWin;
923
924 REQUEST(xCirculateWindowReq);
925 int rc;
926
927 REQUEST_SIZE_MATCH(xCirculateWindowReq);
928 if ((stuff->direction != RaiseLowest) && (stuff->direction != LowerHighest)) {
929 client->errorValue = stuff->direction;
930 return BadValue;
931 }
932 rc = dixLookupWindow(&pWin, stuff->window, client, DixManageAccess);
933 if (rc != Success)
934 return rc;
935 CirculateWindow(pWin, (int) stuff->direction, client);
936 return Success;
937 }
938
939 static int
GetGeometry(ClientPtr client,xGetGeometryReply * rep)940 GetGeometry(ClientPtr client, xGetGeometryReply * rep)
941 {
942 DrawablePtr pDraw;
943 int rc;
944
945 REQUEST(xResourceReq);
946 REQUEST_SIZE_MATCH(xResourceReq);
947
948 rc = dixLookupDrawable(&pDraw, stuff->id, client, M_ANY, DixGetAttrAccess);
949 if (rc != Success)
950 return rc;
951
952 rep->type = X_Reply;
953 rep->length = 0;
954 rep->sequenceNumber = client->sequence;
955 rep->root = pDraw->pScreen->root->drawable.id;
956 rep->depth = pDraw->depth;
957 rep->width = pDraw->width;
958 rep->height = pDraw->height;
959
960 if (WindowDrawable(pDraw->type)) {
961 WindowPtr pWin = (WindowPtr) pDraw;
962
963 rep->x = pWin->origin.x - wBorderWidth(pWin);
964 rep->y = pWin->origin.y - wBorderWidth(pWin);
965 rep->borderWidth = pWin->borderWidth;
966 }
967 else { /* DRAWABLE_PIXMAP */
968
969 rep->x = rep->y = rep->borderWidth = 0;
970 }
971
972 return Success;
973 }
974
975 int
ProcGetGeometry(ClientPtr client)976 ProcGetGeometry(ClientPtr client)
977 {
978 xGetGeometryReply rep = { .type = X_Reply };
979 int status;
980
981 if ((status = GetGeometry(client, &rep)) != Success)
982 return status;
983
984 WriteReplyToClient(client, sizeof(xGetGeometryReply), &rep);
985 return Success;
986 }
987
988 int
ProcQueryTree(ClientPtr client)989 ProcQueryTree(ClientPtr client)
990 {
991 xQueryTreeReply reply;
992 int rc, numChildren = 0;
993 WindowPtr pChild, pWin, pHead;
994 Window *childIDs = (Window *) NULL;
995
996 REQUEST(xResourceReq);
997
998 REQUEST_SIZE_MATCH(xResourceReq);
999 rc = dixLookupWindow(&pWin, stuff->id, client, DixListAccess);
1000 if (rc != Success)
1001 return rc;
1002
1003 reply = (xQueryTreeReply) {
1004 .type = X_Reply,
1005 .sequenceNumber = client->sequence,
1006 .root = pWin->drawable.pScreen->root->drawable.id,
1007 .parent = (pWin->parent) ? pWin->parent->drawable.id : (Window) None
1008 };
1009 pHead = RealChildHead(pWin);
1010 for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib)
1011 numChildren++;
1012 if (numChildren) {
1013 int curChild = 0;
1014
1015 childIDs = xallocarray(numChildren, sizeof(Window));
1016 if (!childIDs)
1017 return BadAlloc;
1018 for (pChild = pWin->lastChild; pChild != pHead;
1019 pChild = pChild->prevSib)
1020 childIDs[curChild++] = pChild->drawable.id;
1021 }
1022
1023 reply.nChildren = numChildren;
1024 reply.length = bytes_to_int32(numChildren * sizeof(Window));
1025
1026 WriteReplyToClient(client, sizeof(xQueryTreeReply), &reply);
1027 if (numChildren) {
1028 client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
1029 WriteSwappedDataToClient(client, numChildren * sizeof(Window),
1030 childIDs);
1031 free(childIDs);
1032 }
1033
1034 return Success;
1035 }
1036
1037 int
ProcInternAtom(ClientPtr client)1038 ProcInternAtom(ClientPtr client)
1039 {
1040 Atom atom;
1041 char *tchar;
1042
1043 REQUEST(xInternAtomReq);
1044
1045 REQUEST_FIXED_SIZE(xInternAtomReq, stuff->nbytes);
1046 if ((stuff->onlyIfExists != xTrue) && (stuff->onlyIfExists != xFalse)) {
1047 client->errorValue = stuff->onlyIfExists;
1048 return BadValue;
1049 }
1050 tchar = (char *) &stuff[1];
1051 atom = MakeAtom(tchar, stuff->nbytes, !stuff->onlyIfExists);
1052 if (atom != BAD_RESOURCE) {
1053 xInternAtomReply reply = {
1054 .type = X_Reply,
1055 .sequenceNumber = client->sequence,
1056 .length = 0,
1057 .atom = atom
1058 };
1059 WriteReplyToClient(client, sizeof(xInternAtomReply), &reply);
1060 return Success;
1061 }
1062 else
1063 return BadAlloc;
1064 }
1065
1066 int
ProcGetAtomName(ClientPtr client)1067 ProcGetAtomName(ClientPtr client)
1068 {
1069 const char *str;
1070
1071 REQUEST(xResourceReq);
1072
1073 REQUEST_SIZE_MATCH(xResourceReq);
1074 if ((str = NameForAtom(stuff->id))) {
1075 int len = strlen(str);
1076 xGetAtomNameReply reply = {
1077 .type = X_Reply,
1078 .sequenceNumber = client->sequence,
1079 .length = bytes_to_int32(len),
1080 .nameLength = len
1081 };
1082
1083 WriteReplyToClient(client, sizeof(xGetAtomNameReply), &reply);
1084 WriteToClient(client, len, str);
1085 return Success;
1086 }
1087 else {
1088 client->errorValue = stuff->id;
1089 return BadAtom;
1090 }
1091 }
1092
1093 int
ProcGrabServer(ClientPtr client)1094 ProcGrabServer(ClientPtr client)
1095 {
1096 int rc;
1097
1098 REQUEST_SIZE_MATCH(xReq);
1099 if (grabState != GrabNone && client != grabClient) {
1100 ResetCurrentRequest(client);
1101 client->sequence--;
1102 BITSET(grabWaiters, client->index);
1103 IgnoreClient(client);
1104 return Success;
1105 }
1106 rc = OnlyListenToOneClient(client);
1107 if (rc != Success)
1108 return rc;
1109 grabState = GrabActive;
1110 grabClient = client;
1111 mark_client_grab(client);
1112
1113 if (ServerGrabCallback) {
1114 ServerGrabInfoRec grabinfo;
1115
1116 grabinfo.client = client;
1117 grabinfo.grabstate = SERVER_GRABBED;
1118 CallCallbacks(&ServerGrabCallback, (void *) &grabinfo);
1119 }
1120
1121 return Success;
1122 }
1123
1124 static void
UngrabServer(ClientPtr client)1125 UngrabServer(ClientPtr client)
1126 {
1127 int i;
1128
1129 grabState = GrabNone;
1130 ListenToAllClients();
1131 mark_client_ungrab();
1132 for (i = mskcnt; --i >= 0 && !grabWaiters[i];);
1133 if (i >= 0) {
1134 i <<= 5;
1135 while (!GETBIT(grabWaiters, i))
1136 i++;
1137 BITCLEAR(grabWaiters, i);
1138 AttendClient(clients[i]);
1139 }
1140
1141 if (ServerGrabCallback) {
1142 ServerGrabInfoRec grabinfo;
1143
1144 grabinfo.client = client;
1145 grabinfo.grabstate = SERVER_UNGRABBED;
1146 CallCallbacks(&ServerGrabCallback, (void *) &grabinfo);
1147 }
1148 }
1149
1150 int
ProcUngrabServer(ClientPtr client)1151 ProcUngrabServer(ClientPtr client)
1152 {
1153 REQUEST_SIZE_MATCH(xReq);
1154 UngrabServer(client);
1155 return Success;
1156 }
1157
1158 int
ProcTranslateCoords(ClientPtr client)1159 ProcTranslateCoords(ClientPtr client)
1160 {
1161 REQUEST(xTranslateCoordsReq);
1162
1163 WindowPtr pWin, pDst;
1164 xTranslateCoordsReply rep;
1165 int rc;
1166
1167 REQUEST_SIZE_MATCH(xTranslateCoordsReq);
1168 rc = dixLookupWindow(&pWin, stuff->srcWid, client, DixGetAttrAccess);
1169 if (rc != Success)
1170 return rc;
1171 rc = dixLookupWindow(&pDst, stuff->dstWid, client, DixGetAttrAccess);
1172 if (rc != Success)
1173 return rc;
1174
1175 rep = (xTranslateCoordsReply) {
1176 .type = X_Reply,
1177 .sequenceNumber = client->sequence,
1178 .length = 0
1179 };
1180 if (!SAME_SCREENS(pWin->drawable, pDst->drawable)) {
1181 rep.sameScreen = xFalse;
1182 rep.child = None;
1183 rep.dstX = rep.dstY = 0;
1184 }
1185 else {
1186 INT16 x, y;
1187
1188 rep.sameScreen = xTrue;
1189 rep.child = None;
1190 /* computing absolute coordinates -- adjust to destination later */
1191 x = pWin->drawable.x + stuff->srcX;
1192 y = pWin->drawable.y + stuff->srcY;
1193 pWin = pDst->firstChild;
1194 while (pWin) {
1195 BoxRec box;
1196
1197 if ((pWin->mapped) &&
1198 (x >= pWin->drawable.x - wBorderWidth(pWin)) &&
1199 (x < pWin->drawable.x + (int) pWin->drawable.width +
1200 wBorderWidth(pWin)) &&
1201 (y >= pWin->drawable.y - wBorderWidth(pWin)) &&
1202 (y < pWin->drawable.y + (int) pWin->drawable.height +
1203 wBorderWidth(pWin))
1204 /* When a window is shaped, a further check
1205 * is made to see if the point is inside
1206 * borderSize
1207 */
1208 && (!wBoundingShape(pWin) ||
1209 RegionContainsPoint(&pWin->borderSize, x, y, &box))
1210
1211 && (!wInputShape(pWin) ||
1212 RegionContainsPoint(wInputShape(pWin),
1213 x - pWin->drawable.x,
1214 y - pWin->drawable.y, &box))
1215 ) {
1216 rep.child = pWin->drawable.id;
1217 pWin = (WindowPtr) NULL;
1218 }
1219 else
1220 pWin = pWin->nextSib;
1221 }
1222 /* adjust to destination coordinates */
1223 rep.dstX = x - pDst->drawable.x;
1224 rep.dstY = y - pDst->drawable.y;
1225 }
1226 WriteReplyToClient(client, sizeof(xTranslateCoordsReply), &rep);
1227 return Success;
1228 }
1229
1230 int
ProcOpenFont(ClientPtr client)1231 ProcOpenFont(ClientPtr client)
1232 {
1233 int err;
1234
1235 REQUEST(xOpenFontReq);
1236
1237 REQUEST_FIXED_SIZE(xOpenFontReq, stuff->nbytes);
1238 client->errorValue = stuff->fid;
1239 LEGAL_NEW_RESOURCE(stuff->fid, client);
1240 err = OpenFont(client, stuff->fid, (Mask) 0,
1241 stuff->nbytes, (char *) &stuff[1]);
1242 if (err == Success) {
1243 return Success;
1244 }
1245 else
1246 return err;
1247 }
1248
1249 int
ProcCloseFont(ClientPtr client)1250 ProcCloseFont(ClientPtr client)
1251 {
1252 FontPtr pFont;
1253 int rc;
1254
1255 REQUEST(xResourceReq);
1256
1257 REQUEST_SIZE_MATCH(xResourceReq);
1258 rc = dixLookupResourceByType((void **) &pFont, stuff->id, RT_FONT,
1259 client, DixDestroyAccess);
1260 if (rc == Success) {
1261 FreeResource(stuff->id, RT_NONE);
1262 return Success;
1263 }
1264 else {
1265 client->errorValue = stuff->id;
1266 return rc;
1267 }
1268 }
1269
1270 int
ProcQueryFont(ClientPtr client)1271 ProcQueryFont(ClientPtr client)
1272 {
1273 xQueryFontReply *reply;
1274 FontPtr pFont;
1275 int rc;
1276
1277 REQUEST(xResourceReq);
1278 REQUEST_SIZE_MATCH(xResourceReq);
1279
1280 rc = dixLookupFontable(&pFont, stuff->id, client, DixGetAttrAccess);
1281 if (rc != Success)
1282 return rc;
1283
1284 {
1285 xCharInfo *pmax = FONTINKMAX(pFont);
1286 xCharInfo *pmin = FONTINKMIN(pFont);
1287 int nprotoxcistructs;
1288 int rlength;
1289
1290 nprotoxcistructs = (pmax->rightSideBearing == pmin->rightSideBearing &&
1291 pmax->leftSideBearing == pmin->leftSideBearing &&
1292 pmax->descent == pmin->descent &&
1293 pmax->ascent == pmin->ascent &&
1294 pmax->characterWidth == pmin->characterWidth) ?
1295 0 : N2dChars(pFont);
1296
1297 rlength = sizeof(xQueryFontReply) +
1298 FONTINFONPROPS(FONTCHARSET(pFont)) * sizeof(xFontProp) +
1299 nprotoxcistructs * sizeof(xCharInfo);
1300 reply = calloc(1, rlength);
1301 if (!reply) {
1302 return BadAlloc;
1303 }
1304
1305 reply->type = X_Reply;
1306 reply->length = bytes_to_int32(rlength - sizeof(xGenericReply));
1307 reply->sequenceNumber = client->sequence;
1308 QueryFont(pFont, reply, nprotoxcistructs);
1309
1310 WriteReplyToClient(client, rlength, reply);
1311 free(reply);
1312 return Success;
1313 }
1314 }
1315
1316 int
ProcQueryTextExtents(ClientPtr client)1317 ProcQueryTextExtents(ClientPtr client)
1318 {
1319 xQueryTextExtentsReply reply;
1320 FontPtr pFont;
1321 ExtentInfoRec info;
1322 unsigned long length;
1323 int rc;
1324
1325 REQUEST(xQueryTextExtentsReq);
1326 REQUEST_AT_LEAST_SIZE(xQueryTextExtentsReq);
1327
1328 rc = dixLookupFontable(&pFont, stuff->fid, client, DixGetAttrAccess);
1329 if (rc != Success)
1330 return rc;
1331
1332 length = client->req_len - bytes_to_int32(sizeof(xQueryTextExtentsReq));
1333 length = length << 1;
1334 if (stuff->oddLength) {
1335 if (length == 0)
1336 return BadLength;
1337 length--;
1338 }
1339 if (!xfont2_query_text_extents(pFont, length, (unsigned char *) &stuff[1], &info))
1340 return BadAlloc;
1341 reply = (xQueryTextExtentsReply) {
1342 .type = X_Reply,
1343 .drawDirection = info.drawDirection,
1344 .sequenceNumber = client->sequence,
1345 .length = 0,
1346 .fontAscent = info.fontAscent,
1347 .fontDescent = info.fontDescent,
1348 .overallAscent = info.overallAscent,
1349 .overallDescent = info.overallDescent,
1350 .overallWidth = info.overallWidth,
1351 .overallLeft = info.overallLeft,
1352 .overallRight = info.overallRight
1353 };
1354 WriteReplyToClient(client, sizeof(xQueryTextExtentsReply), &reply);
1355 return Success;
1356 }
1357
1358 int
ProcListFonts(ClientPtr client)1359 ProcListFonts(ClientPtr client)
1360 {
1361 REQUEST(xListFontsReq);
1362
1363 REQUEST_FIXED_SIZE(xListFontsReq, stuff->nbytes);
1364
1365 return ListFonts(client, (unsigned char *) &stuff[1], stuff->nbytes,
1366 stuff->maxNames);
1367 }
1368
1369 int
ProcListFontsWithInfo(ClientPtr client)1370 ProcListFontsWithInfo(ClientPtr client)
1371 {
1372 REQUEST(xListFontsWithInfoReq);
1373
1374 REQUEST_FIXED_SIZE(xListFontsWithInfoReq, stuff->nbytes);
1375
1376 return StartListFontsWithInfo(client, stuff->nbytes,
1377 (unsigned char *) &stuff[1], stuff->maxNames);
1378 }
1379
1380 /**
1381 *
1382 * \param value must conform to DeleteType
1383 */
1384 int
dixDestroyPixmap(void * value,XID pid)1385 dixDestroyPixmap(void *value, XID pid)
1386 {
1387 PixmapPtr pPixmap = (PixmapPtr) value;
1388
1389 return (*pPixmap->drawable.pScreen->DestroyPixmap) (pPixmap);
1390 }
1391
1392 int
ProcCreatePixmap(ClientPtr client)1393 ProcCreatePixmap(ClientPtr client)
1394 {
1395 PixmapPtr pMap;
1396 DrawablePtr pDraw;
1397
1398 REQUEST(xCreatePixmapReq);
1399 DepthPtr pDepth;
1400 int i, rc;
1401
1402 REQUEST_SIZE_MATCH(xCreatePixmapReq);
1403 client->errorValue = stuff->pid;
1404 LEGAL_NEW_RESOURCE(stuff->pid, client);
1405
1406 rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY,
1407 DixGetAttrAccess);
1408 if (rc != Success)
1409 return rc;
1410
1411 if (!stuff->width || !stuff->height) {
1412 client->errorValue = 0;
1413 return BadValue;
1414 }
1415 if (stuff->width > 32767 || stuff->height > 32767) {
1416 /* It is allowed to try and allocate a pixmap which is larger than
1417 * 32767 in either dimension. However, all of the framebuffer code
1418 * is buggy and does not reliably draw to such big pixmaps, basically
1419 * because the Region data structure operates with signed shorts
1420 * for the rectangles in it.
1421 *
1422 * Furthermore, several places in the X server computes the
1423 * size in bytes of the pixmap and tries to store it in an
1424 * integer. This integer can overflow and cause the allocated size
1425 * to be much smaller.
1426 *
1427 * So, such big pixmaps are rejected here with a BadAlloc
1428 */
1429 return BadAlloc;
1430 }
1431 if (stuff->depth != 1) {
1432 pDepth = pDraw->pScreen->allowedDepths;
1433 for (i = 0; i < pDraw->pScreen->numDepths; i++, pDepth++)
1434 if (pDepth->depth == stuff->depth)
1435 goto CreatePmap;
1436 client->errorValue = stuff->depth;
1437 return BadValue;
1438 }
1439 CreatePmap:
1440 pMap = (PixmapPtr) (*pDraw->pScreen->CreatePixmap)
1441 (pDraw->pScreen, stuff->width, stuff->height, stuff->depth, 0);
1442 if (pMap) {
1443 pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
1444 pMap->drawable.id = stuff->pid;
1445 /* security creation/labeling check */
1446 rc = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pid, RT_PIXMAP,
1447 pMap, RT_NONE, NULL, DixCreateAccess);
1448 if (rc != Success) {
1449 (*pDraw->pScreen->DestroyPixmap) (pMap);
1450 return rc;
1451 }
1452 if (AddResource(stuff->pid, RT_PIXMAP, (void *) pMap))
1453 return Success;
1454 }
1455 return BadAlloc;
1456 }
1457
1458 int
ProcFreePixmap(ClientPtr client)1459 ProcFreePixmap(ClientPtr client)
1460 {
1461 PixmapPtr pMap;
1462 int rc;
1463
1464 REQUEST(xResourceReq);
1465 REQUEST_SIZE_MATCH(xResourceReq);
1466
1467 rc = dixLookupResourceByType((void **) &pMap, stuff->id, RT_PIXMAP,
1468 client, DixDestroyAccess);
1469 if (rc == Success) {
1470 FreeResource(stuff->id, RT_NONE);
1471 return Success;
1472 }
1473 else {
1474 client->errorValue = stuff->id;
1475 return rc;
1476 }
1477 }
1478
1479 int
ProcCreateGC(ClientPtr client)1480 ProcCreateGC(ClientPtr client)
1481 {
1482 int error, rc;
1483 GC *pGC;
1484 DrawablePtr pDraw;
1485 unsigned len;
1486
1487 REQUEST(xCreateGCReq);
1488
1489 REQUEST_AT_LEAST_SIZE(xCreateGCReq);
1490 client->errorValue = stuff->gc;
1491 LEGAL_NEW_RESOURCE(stuff->gc, client);
1492 rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0,
1493 DixGetAttrAccess);
1494 if (rc != Success)
1495 return rc;
1496
1497 len = client->req_len - bytes_to_int32(sizeof(xCreateGCReq));
1498 if (len != Ones(stuff->mask))
1499 return BadLength;
1500 pGC = (GC *) CreateGC(pDraw, stuff->mask, (XID *) &stuff[1], &error,
1501 stuff->gc, client);
1502 if (error != Success)
1503 return error;
1504 if (!AddResource(stuff->gc, RT_GC, (void *) pGC))
1505 return BadAlloc;
1506 return Success;
1507 }
1508
1509 int
ProcChangeGC(ClientPtr client)1510 ProcChangeGC(ClientPtr client)
1511 {
1512 GC *pGC;
1513 int result;
1514 unsigned len;
1515
1516 REQUEST(xChangeGCReq);
1517 REQUEST_AT_LEAST_SIZE(xChangeGCReq);
1518
1519 result = dixLookupGC(&pGC, stuff->gc, client, DixSetAttrAccess);
1520 if (result != Success)
1521 return result;
1522
1523 len = client->req_len - bytes_to_int32(sizeof(xChangeGCReq));
1524 if (len != Ones(stuff->mask))
1525 return BadLength;
1526
1527 return ChangeGCXIDs(client, pGC, stuff->mask, (CARD32 *) &stuff[1]);
1528 }
1529
1530 int
ProcCopyGC(ClientPtr client)1531 ProcCopyGC(ClientPtr client)
1532 {
1533 GC *dstGC;
1534 GC *pGC;
1535 int result;
1536
1537 REQUEST(xCopyGCReq);
1538 REQUEST_SIZE_MATCH(xCopyGCReq);
1539
1540 result = dixLookupGC(&pGC, stuff->srcGC, client, DixGetAttrAccess);
1541 if (result != Success)
1542 return result;
1543 result = dixLookupGC(&dstGC, stuff->dstGC, client, DixSetAttrAccess);
1544 if (result != Success)
1545 return result;
1546 if ((dstGC->pScreen != pGC->pScreen) || (dstGC->depth != pGC->depth))
1547 return BadMatch;
1548 if (stuff->mask & ~GCAllBits) {
1549 client->errorValue = stuff->mask;
1550 return BadValue;
1551 }
1552 return CopyGC(pGC, dstGC, stuff->mask);
1553 }
1554
1555 int
ProcSetDashes(ClientPtr client)1556 ProcSetDashes(ClientPtr client)
1557 {
1558 GC *pGC;
1559 int result;
1560
1561 REQUEST(xSetDashesReq);
1562
1563 REQUEST_FIXED_SIZE(xSetDashesReq, stuff->nDashes);
1564 if (stuff->nDashes == 0) {
1565 client->errorValue = 0;
1566 return BadValue;
1567 }
1568
1569 result = dixLookupGC(&pGC, stuff->gc, client, DixSetAttrAccess);
1570 if (result != Success)
1571 return result;
1572
1573 /* If there's an error, either there's no sensible errorValue,
1574 * or there was a dash segment of 0. */
1575 client->errorValue = 0;
1576 return SetDashes(pGC, stuff->dashOffset, stuff->nDashes,
1577 (unsigned char *) &stuff[1]);
1578 }
1579
1580 int
ProcSetClipRectangles(ClientPtr client)1581 ProcSetClipRectangles(ClientPtr client)
1582 {
1583 int nr, result;
1584 GC *pGC;
1585
1586 REQUEST(xSetClipRectanglesReq);
1587
1588 REQUEST_AT_LEAST_SIZE(xSetClipRectanglesReq);
1589 if ((stuff->ordering != Unsorted) && (stuff->ordering != YSorted) &&
1590 (stuff->ordering != YXSorted) && (stuff->ordering != YXBanded)) {
1591 client->errorValue = stuff->ordering;
1592 return BadValue;
1593 }
1594 result = dixLookupGC(&pGC, stuff->gc, client, DixSetAttrAccess);
1595 if (result != Success)
1596 return result;
1597
1598 nr = (client->req_len << 2) - sizeof(xSetClipRectanglesReq);
1599 if (nr & 4)
1600 return BadLength;
1601 nr >>= 3;
1602 return SetClipRects(pGC, stuff->xOrigin, stuff->yOrigin,
1603 nr, (xRectangle *) &stuff[1], (int) stuff->ordering);
1604 }
1605
1606 int
ProcFreeGC(ClientPtr client)1607 ProcFreeGC(ClientPtr client)
1608 {
1609 GC *pGC;
1610 int rc;
1611
1612 REQUEST(xResourceReq);
1613 REQUEST_SIZE_MATCH(xResourceReq);
1614
1615 rc = dixLookupGC(&pGC, stuff->id, client, DixDestroyAccess);
1616 if (rc != Success)
1617 return rc;
1618
1619 FreeResource(stuff->id, RT_NONE);
1620 return Success;
1621 }
1622
1623 int
ProcClearToBackground(ClientPtr client)1624 ProcClearToBackground(ClientPtr client)
1625 {
1626 REQUEST(xClearAreaReq);
1627 WindowPtr pWin;
1628 int rc;
1629
1630 REQUEST_SIZE_MATCH(xClearAreaReq);
1631 rc = dixLookupWindow(&pWin, stuff->window, client, DixWriteAccess);
1632 if (rc != Success)
1633 return rc;
1634 if (pWin->drawable.class == InputOnly) {
1635 client->errorValue = stuff->window;
1636 return BadMatch;
1637 }
1638 if ((stuff->exposures != xTrue) && (stuff->exposures != xFalse)) {
1639 client->errorValue = stuff->exposures;
1640 return BadValue;
1641 }
1642 (*pWin->drawable.pScreen->ClearToBackground) (pWin, stuff->x, stuff->y,
1643 stuff->width, stuff->height,
1644 (Bool) stuff->exposures);
1645 return Success;
1646 }
1647
1648 /* send GraphicsExpose events, or a NoExpose event, based on the region */
1649 void
SendGraphicsExpose(ClientPtr client,RegionPtr pRgn,XID drawable,int major,int minor)1650 SendGraphicsExpose(ClientPtr client, RegionPtr pRgn, XID drawable,
1651 int major, int minor)
1652 {
1653 if (pRgn && !RegionNil(pRgn)) {
1654 xEvent *pEvent;
1655 xEvent *pe;
1656 BoxPtr pBox;
1657 int i;
1658 int numRects;
1659
1660 numRects = RegionNumRects(pRgn);
1661 pBox = RegionRects(pRgn);
1662 if (!(pEvent = calloc(numRects, sizeof(xEvent))))
1663 return;
1664 pe = pEvent;
1665
1666 for (i = 1; i <= numRects; i++, pe++, pBox++) {
1667 pe->u.u.type = GraphicsExpose;
1668 pe->u.graphicsExposure.drawable = drawable;
1669 pe->u.graphicsExposure.x = pBox->x1;
1670 pe->u.graphicsExposure.y = pBox->y1;
1671 pe->u.graphicsExposure.width = pBox->x2 - pBox->x1;
1672 pe->u.graphicsExposure.height = pBox->y2 - pBox->y1;
1673 pe->u.graphicsExposure.count = numRects - i;
1674 pe->u.graphicsExposure.majorEvent = major;
1675 pe->u.graphicsExposure.minorEvent = minor;
1676 }
1677 /* GraphicsExpose is a "critical event", which TryClientEvents
1678 * handles specially. */
1679 TryClientEvents(client, NULL, pEvent, numRects,
1680 (Mask) 0, NoEventMask, NullGrab);
1681 free(pEvent);
1682 }
1683 else {
1684 xEvent event = {
1685 .u.noExposure.drawable = drawable,
1686 .u.noExposure.majorEvent = major,
1687 .u.noExposure.minorEvent = minor
1688 };
1689 event.u.u.type = NoExpose;
1690 WriteEventsToClient(client, 1, &event);
1691 }
1692 }
1693
1694 int
ProcCopyArea(ClientPtr client)1695 ProcCopyArea(ClientPtr client)
1696 {
1697 DrawablePtr pDst;
1698 DrawablePtr pSrc;
1699 GC *pGC;
1700
1701 REQUEST(xCopyAreaReq);
1702 RegionPtr pRgn;
1703 int rc;
1704
1705 REQUEST_SIZE_MATCH(xCopyAreaReq);
1706
1707 VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pDst, DixWriteAccess);
1708 if (stuff->dstDrawable != stuff->srcDrawable) {
1709 rc = dixLookupDrawable(&pSrc, stuff->srcDrawable, client, 0,
1710 DixReadAccess);
1711 if (rc != Success)
1712 return rc;
1713 if ((pDst->pScreen != pSrc->pScreen) || (pDst->depth != pSrc->depth)) {
1714 client->errorValue = stuff->dstDrawable;
1715 return BadMatch;
1716 }
1717 }
1718 else
1719 pSrc = pDst;
1720
1721 pRgn = (*pGC->ops->CopyArea) (pSrc, pDst, pGC, stuff->srcX, stuff->srcY,
1722 stuff->width, stuff->height,
1723 stuff->dstX, stuff->dstY);
1724 if (pGC->graphicsExposures) {
1725 SendGraphicsExpose(client, pRgn, stuff->dstDrawable, X_CopyArea, 0);
1726 if (pRgn)
1727 RegionDestroy(pRgn);
1728 }
1729
1730 return Success;
1731 }
1732
1733 int
ProcCopyPlane(ClientPtr client)1734 ProcCopyPlane(ClientPtr client)
1735 {
1736 DrawablePtr psrcDraw, pdstDraw;
1737 GC *pGC;
1738
1739 REQUEST(xCopyPlaneReq);
1740 RegionPtr pRgn;
1741 int rc;
1742
1743 REQUEST_SIZE_MATCH(xCopyPlaneReq);
1744
1745 VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pdstDraw, DixWriteAccess);
1746 if (stuff->dstDrawable != stuff->srcDrawable) {
1747 rc = dixLookupDrawable(&psrcDraw, stuff->srcDrawable, client, 0,
1748 DixReadAccess);
1749 if (rc != Success)
1750 return rc;
1751
1752 if (pdstDraw->pScreen != psrcDraw->pScreen) {
1753 client->errorValue = stuff->dstDrawable;
1754 return BadMatch;
1755 }
1756 }
1757 else
1758 psrcDraw = pdstDraw;
1759
1760 /* Check to see if stuff->bitPlane has exactly ONE good bit set */
1761 if (stuff->bitPlane == 0 || (stuff->bitPlane & (stuff->bitPlane - 1)) ||
1762 (stuff->bitPlane > (1L << (psrcDraw->depth - 1)))) {
1763 client->errorValue = stuff->bitPlane;
1764 return BadValue;
1765 }
1766
1767 pRgn =
1768 (*pGC->ops->CopyPlane) (psrcDraw, pdstDraw, pGC, stuff->srcX,
1769 stuff->srcY, stuff->width, stuff->height,
1770 stuff->dstX, stuff->dstY, stuff->bitPlane);
1771 if (pGC->graphicsExposures) {
1772 SendGraphicsExpose(client, pRgn, stuff->dstDrawable, X_CopyPlane, 0);
1773 if (pRgn)
1774 RegionDestroy(pRgn);
1775 }
1776 return Success;
1777 }
1778
1779 int
ProcPolyPoint(ClientPtr client)1780 ProcPolyPoint(ClientPtr client)
1781 {
1782 int npoint;
1783 GC *pGC;
1784 DrawablePtr pDraw;
1785
1786 REQUEST(xPolyPointReq);
1787
1788 REQUEST_AT_LEAST_SIZE(xPolyPointReq);
1789 if ((stuff->coordMode != CoordModeOrigin) &&
1790 (stuff->coordMode != CoordModePrevious)) {
1791 client->errorValue = stuff->coordMode;
1792 return BadValue;
1793 }
1794 VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
1795 npoint = bytes_to_int32((client->req_len << 2) - sizeof(xPolyPointReq));
1796 if (npoint)
1797 (*pGC->ops->PolyPoint) (pDraw, pGC, stuff->coordMode, npoint,
1798 (xPoint *) &stuff[1]);
1799 return Success;
1800 }
1801
1802 int
ProcPolyLine(ClientPtr client)1803 ProcPolyLine(ClientPtr client)
1804 {
1805 int npoint;
1806 GC *pGC;
1807 DrawablePtr pDraw;
1808
1809 REQUEST(xPolyLineReq);
1810
1811 REQUEST_AT_LEAST_SIZE(xPolyLineReq);
1812 if ((stuff->coordMode != CoordModeOrigin) &&
1813 (stuff->coordMode != CoordModePrevious)) {
1814 client->errorValue = stuff->coordMode;
1815 return BadValue;
1816 }
1817 VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
1818 npoint = bytes_to_int32((client->req_len << 2) - sizeof(xPolyLineReq));
1819 if (npoint > 1)
1820 (*pGC->ops->Polylines) (pDraw, pGC, stuff->coordMode, npoint,
1821 (DDXPointPtr) &stuff[1]);
1822 return Success;
1823 }
1824
1825 int
ProcPolySegment(ClientPtr client)1826 ProcPolySegment(ClientPtr client)
1827 {
1828 int nsegs;
1829 GC *pGC;
1830 DrawablePtr pDraw;
1831
1832 REQUEST(xPolySegmentReq);
1833
1834 REQUEST_AT_LEAST_SIZE(xPolySegmentReq);
1835 VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
1836 nsegs = (client->req_len << 2) - sizeof(xPolySegmentReq);
1837 if (nsegs & 4)
1838 return BadLength;
1839 nsegs >>= 3;
1840 if (nsegs)
1841 (*pGC->ops->PolySegment) (pDraw, pGC, nsegs, (xSegment *) &stuff[1]);
1842 return Success;
1843 }
1844
1845 int
ProcPolyRectangle(ClientPtr client)1846 ProcPolyRectangle(ClientPtr client)
1847 {
1848 int nrects;
1849 GC *pGC;
1850 DrawablePtr pDraw;
1851
1852 REQUEST(xPolyRectangleReq);
1853
1854 REQUEST_AT_LEAST_SIZE(xPolyRectangleReq);
1855 VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
1856 nrects = (client->req_len << 2) - sizeof(xPolyRectangleReq);
1857 if (nrects & 4)
1858 return BadLength;
1859 nrects >>= 3;
1860 if (nrects)
1861 (*pGC->ops->PolyRectangle) (pDraw, pGC,
1862 nrects, (xRectangle *) &stuff[1]);
1863 return Success;
1864 }
1865
1866 int
ProcPolyArc(ClientPtr client)1867 ProcPolyArc(ClientPtr client)
1868 {
1869 int narcs;
1870 GC *pGC;
1871 DrawablePtr pDraw;
1872
1873 REQUEST(xPolyArcReq);
1874
1875 REQUEST_AT_LEAST_SIZE(xPolyArcReq);
1876 VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
1877 narcs = (client->req_len << 2) - sizeof(xPolyArcReq);
1878 if (narcs % sizeof(xArc))
1879 return BadLength;
1880 narcs /= sizeof(xArc);
1881 if (narcs)
1882 (*pGC->ops->PolyArc) (pDraw, pGC, narcs, (xArc *) &stuff[1]);
1883 return Success;
1884 }
1885
1886 int
ProcFillPoly(ClientPtr client)1887 ProcFillPoly(ClientPtr client)
1888 {
1889 int things;
1890 GC *pGC;
1891 DrawablePtr pDraw;
1892
1893 REQUEST(xFillPolyReq);
1894
1895 REQUEST_AT_LEAST_SIZE(xFillPolyReq);
1896 if ((stuff->shape != Complex) && (stuff->shape != Nonconvex) &&
1897 (stuff->shape != Convex)) {
1898 client->errorValue = stuff->shape;
1899 return BadValue;
1900 }
1901 if ((stuff->coordMode != CoordModeOrigin) &&
1902 (stuff->coordMode != CoordModePrevious)) {
1903 client->errorValue = stuff->coordMode;
1904 return BadValue;
1905 }
1906
1907 VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
1908 things = bytes_to_int32((client->req_len << 2) - sizeof(xFillPolyReq));
1909 if (things)
1910 (*pGC->ops->FillPolygon) (pDraw, pGC, stuff->shape,
1911 stuff->coordMode, things,
1912 (DDXPointPtr) &stuff[1]);
1913 return Success;
1914 }
1915
1916 int
ProcPolyFillRectangle(ClientPtr client)1917 ProcPolyFillRectangle(ClientPtr client)
1918 {
1919 int things;
1920 GC *pGC;
1921 DrawablePtr pDraw;
1922
1923 REQUEST(xPolyFillRectangleReq);
1924
1925 REQUEST_AT_LEAST_SIZE(xPolyFillRectangleReq);
1926 VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
1927 things = (client->req_len << 2) - sizeof(xPolyFillRectangleReq);
1928 if (things & 4)
1929 return BadLength;
1930 things >>= 3;
1931
1932 if (things)
1933 (*pGC->ops->PolyFillRect) (pDraw, pGC, things,
1934 (xRectangle *) &stuff[1]);
1935 return Success;
1936 }
1937
1938 int
ProcPolyFillArc(ClientPtr client)1939 ProcPolyFillArc(ClientPtr client)
1940 {
1941 int narcs;
1942 GC *pGC;
1943 DrawablePtr pDraw;
1944
1945 REQUEST(xPolyFillArcReq);
1946
1947 REQUEST_AT_LEAST_SIZE(xPolyFillArcReq);
1948 VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
1949 narcs = (client->req_len << 2) - sizeof(xPolyFillArcReq);
1950 if (narcs % sizeof(xArc))
1951 return BadLength;
1952 narcs /= sizeof(xArc);
1953 if (narcs)
1954 (*pGC->ops->PolyFillArc) (pDraw, pGC, narcs, (xArc *) &stuff[1]);
1955 return Success;
1956 }
1957
1958 #ifdef MATCH_CLIENT_ENDIAN
1959
1960 int
ServerOrder(void)1961 ServerOrder(void)
1962 {
1963 int whichbyte = 1;
1964
1965 if (*((char *) &whichbyte))
1966 return LSBFirst;
1967 return MSBFirst;
1968 }
1969
1970 #define ClientOrder(client) ((client)->swapped ? !ServerOrder() : ServerOrder())
1971
1972 void
ReformatImage(char * base,int nbytes,int bpp,int order)1973 ReformatImage(char *base, int nbytes, int bpp, int order)
1974 {
1975 switch (bpp) {
1976 case 1: /* yuck */
1977 if (BITMAP_BIT_ORDER != order)
1978 BitOrderInvert((unsigned char *) base, nbytes);
1979 #if IMAGE_BYTE_ORDER != BITMAP_BIT_ORDER && BITMAP_SCANLINE_UNIT != 8
1980 ReformatImage(base, nbytes, BITMAP_SCANLINE_UNIT, order);
1981 #endif
1982 break;
1983 case 4:
1984 break; /* yuck */
1985 case 8:
1986 break;
1987 case 16:
1988 if (IMAGE_BYTE_ORDER != order)
1989 TwoByteSwap((unsigned char *) base, nbytes);
1990 break;
1991 case 32:
1992 if (IMAGE_BYTE_ORDER != order)
1993 FourByteSwap((unsigned char *) base, nbytes);
1994 break;
1995 }
1996 }
1997 #else
1998 #define ReformatImage(b,n,bpp,o)
1999 #endif
2000
2001 /* 64-bit server notes: the protocol restricts padding of images to
2002 * 8-, 16-, or 32-bits. We would like to have 64-bits for the server
2003 * to use internally. Removes need for internal alignment checking.
2004 * All of the PutImage functions could be changed individually, but
2005 * as currently written, they call other routines which require things
2006 * to be 64-bit padded on scanlines, so we changed things here.
2007 * If an image would be padded differently for 64- versus 32-, then
2008 * copy each scanline to a 64-bit padded scanline.
2009 * Also, we need to make sure that the image is aligned on a 64-bit
2010 * boundary, even if the scanlines are padded to our satisfaction.
2011 */
2012 int
ProcPutImage(ClientPtr client)2013 ProcPutImage(ClientPtr client)
2014 {
2015 GC *pGC;
2016 DrawablePtr pDraw;
2017 long length; /* length of scanline server padded */
2018 long lengthProto; /* length of scanline protocol padded */
2019 char *tmpImage;
2020
2021 REQUEST(xPutImageReq);
2022
2023 REQUEST_AT_LEAST_SIZE(xPutImageReq);
2024 VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
2025 if (stuff->format == XYBitmap) {
2026 if ((stuff->depth != 1) ||
2027 (stuff->leftPad >= (unsigned int) screenInfo.bitmapScanlinePad))
2028 return BadMatch;
2029 length = BitmapBytePad(stuff->width + stuff->leftPad);
2030 }
2031 else if (stuff->format == XYPixmap) {
2032 if ((pDraw->depth != stuff->depth) ||
2033 (stuff->leftPad >= (unsigned int) screenInfo.bitmapScanlinePad))
2034 return BadMatch;
2035 length = BitmapBytePad(stuff->width + stuff->leftPad);
2036 length *= stuff->depth;
2037 }
2038 else if (stuff->format == ZPixmap) {
2039 if ((pDraw->depth != stuff->depth) || (stuff->leftPad != 0))
2040 return BadMatch;
2041 length = PixmapBytePad(stuff->width, stuff->depth);
2042 }
2043 else {
2044 client->errorValue = stuff->format;
2045 return BadValue;
2046 }
2047
2048 tmpImage = (char *) &stuff[1];
2049 lengthProto = length;
2050
2051 if (stuff->height != 0 && lengthProto >= (INT32_MAX / stuff->height))
2052 return BadLength;
2053
2054 if ((bytes_to_int32(lengthProto * stuff->height) +
2055 bytes_to_int32(sizeof(xPutImageReq))) != client->req_len)
2056 return BadLength;
2057
2058 ReformatImage(tmpImage, lengthProto * stuff->height,
2059 stuff->format == ZPixmap ? BitsPerPixel(stuff->depth) : 1,
2060 ClientOrder(client));
2061
2062 (*pGC->ops->PutImage) (pDraw, pGC, stuff->depth, stuff->dstX, stuff->dstY,
2063 stuff->width, stuff->height,
2064 stuff->leftPad, stuff->format, tmpImage);
2065
2066 return Success;
2067 }
2068
2069 static int
DoGetImage(ClientPtr client,int format,Drawable drawable,int x,int y,int width,int height,Mask planemask)2070 DoGetImage(ClientPtr client, int format, Drawable drawable,
2071 int x, int y, int width, int height,
2072 Mask planemask)
2073 {
2074 DrawablePtr pDraw, pBoundingDraw;
2075 int nlines, linesPerBuf, rc;
2076 int linesDone;
2077
2078 /* coordinates relative to the bounding drawable */
2079 int relx, rely;
2080 long widthBytesLine, length;
2081 Mask plane = 0;
2082 char *pBuf;
2083 xGetImageReply xgi;
2084 RegionPtr pVisibleRegion = NULL;
2085
2086 if ((format != XYPixmap) && (format != ZPixmap)) {
2087 client->errorValue = format;
2088 return BadValue;
2089 }
2090 rc = dixLookupDrawable(&pDraw, drawable, client, 0, DixReadAccess);
2091 if (rc != Success)
2092 return rc;
2093
2094 memset(&xgi, 0, sizeof(xGetImageReply));
2095
2096 relx = x;
2097 rely = y;
2098
2099 if (pDraw->type == DRAWABLE_WINDOW) {
2100 WindowPtr pWin = (WindowPtr) pDraw;
2101
2102 /* "If the drawable is a window, the window must be viewable ... or a
2103 * BadMatch error results" */
2104 if (!pWin->viewable)
2105 return BadMatch;
2106
2107 /* If the drawable is a window, the rectangle must be contained within
2108 * its bounds (including the border). */
2109 if (x < -wBorderWidth(pWin) ||
2110 x + width > wBorderWidth(pWin) + (int) pDraw->width ||
2111 y < -wBorderWidth(pWin) ||
2112 y + height > wBorderWidth(pWin) + (int) pDraw->height)
2113 return BadMatch;
2114
2115 relx += pDraw->x;
2116 rely += pDraw->y;
2117
2118 if (pDraw->pScreen->GetWindowPixmap) {
2119 PixmapPtr pPix = (*pDraw->pScreen->GetWindowPixmap) (pWin);
2120
2121 pBoundingDraw = &pPix->drawable;
2122 #ifdef COMPOSITE
2123 relx -= pPix->screen_x;
2124 rely -= pPix->screen_y;
2125 #endif
2126 }
2127 else {
2128 pBoundingDraw = (DrawablePtr) pDraw->pScreen->root;
2129 }
2130
2131 xgi.visual = wVisual(pWin);
2132 }
2133 else {
2134 pBoundingDraw = pDraw;
2135 xgi.visual = None;
2136 }
2137
2138 /* "If the drawable is a pixmap, the given rectangle must be wholly
2139 * contained within the pixmap, or a BadMatch error results. If the
2140 * drawable is a window [...] it must be the case that if there were no
2141 * inferiors or overlapping windows, the specified rectangle of the window
2142 * would be fully visible on the screen and wholly contained within the
2143 * outside edges of the window, or a BadMatch error results."
2144 *
2145 * We relax the window case slightly to mean that the rectangle must exist
2146 * within the bounds of the window's backing pixmap. In particular, this
2147 * means that a GetImage request may succeed or fail with BadMatch depending
2148 * on whether any of its ancestor windows are redirected. */
2149 if (relx < 0 || relx + width > (int) pBoundingDraw->width ||
2150 rely < 0 || rely + height > (int) pBoundingDraw->height)
2151 return BadMatch;
2152
2153 xgi.type = X_Reply;
2154 xgi.sequenceNumber = client->sequence;
2155 xgi.depth = pDraw->depth;
2156 if (format == ZPixmap) {
2157 widthBytesLine = PixmapBytePad(width, pDraw->depth);
2158 length = widthBytesLine * height;
2159
2160 }
2161 else {
2162 widthBytesLine = BitmapBytePad(width);
2163 plane = ((Mask) 1) << (pDraw->depth - 1);
2164 /* only planes asked for */
2165 length = widthBytesLine * height *
2166 Ones(planemask & (plane | (plane - 1)));
2167
2168 }
2169
2170 xgi.length = length;
2171
2172 xgi.length = bytes_to_int32(xgi.length);
2173 if (widthBytesLine == 0 || height == 0)
2174 linesPerBuf = 0;
2175 else if (widthBytesLine >= IMAGE_BUFSIZE)
2176 linesPerBuf = 1;
2177 else {
2178 linesPerBuf = IMAGE_BUFSIZE / widthBytesLine;
2179 if (linesPerBuf > height)
2180 linesPerBuf = height;
2181 }
2182 length = linesPerBuf * widthBytesLine;
2183 if (linesPerBuf < height) {
2184 /* we have to make sure intermediate buffers don't need padding */
2185 while ((linesPerBuf > 1) &&
2186 (length & ((1L << LOG2_BYTES_PER_SCANLINE_PAD) - 1))) {
2187 linesPerBuf--;
2188 length -= widthBytesLine;
2189 }
2190 while (length & ((1L << LOG2_BYTES_PER_SCANLINE_PAD) - 1)) {
2191 linesPerBuf++;
2192 length += widthBytesLine;
2193 }
2194 }
2195 if (!(pBuf = calloc(1, length)))
2196 return BadAlloc;
2197 WriteReplyToClient(client, sizeof(xGetImageReply), &xgi);
2198
2199 if (pDraw->type == DRAWABLE_WINDOW) {
2200 pVisibleRegion = &((WindowPtr) pDraw)->borderClip;
2201 pDraw->pScreen->SourceValidate(pDraw, x, y, width, height,
2202 IncludeInferiors);
2203 }
2204
2205 if (linesPerBuf == 0) {
2206 /* nothing to do */
2207 }
2208 else if (format == ZPixmap) {
2209 linesDone = 0;
2210 while (height - linesDone > 0) {
2211 nlines = min(linesPerBuf, height - linesDone);
2212 (*pDraw->pScreen->GetImage) (pDraw,
2213 x,
2214 y + linesDone,
2215 width,
2216 nlines,
2217 format, planemask, (void *) pBuf);
2218 if (pVisibleRegion)
2219 XaceCensorImage(client, pVisibleRegion, widthBytesLine,
2220 pDraw, x, y + linesDone, width,
2221 nlines, format, pBuf);
2222
2223 /* Note that this is NOT a call to WriteSwappedDataToClient,
2224 as we do NOT byte swap */
2225 ReformatImage(pBuf, (int) (nlines * widthBytesLine),
2226 BitsPerPixel(pDraw->depth), ClientOrder(client));
2227
2228 WriteToClient(client, (int) (nlines * widthBytesLine), pBuf);
2229 linesDone += nlines;
2230 }
2231 }
2232 else { /* XYPixmap */
2233
2234 for (; plane; plane >>= 1) {
2235 if (planemask & plane) {
2236 linesDone = 0;
2237 while (height - linesDone > 0) {
2238 nlines = min(linesPerBuf, height - linesDone);
2239 (*pDraw->pScreen->GetImage) (pDraw,
2240 x,
2241 y + linesDone,
2242 width,
2243 nlines,
2244 format, plane, (void *) pBuf);
2245 if (pVisibleRegion)
2246 XaceCensorImage(client, pVisibleRegion,
2247 widthBytesLine,
2248 pDraw, x, y + linesDone, width,
2249 nlines, format, pBuf);
2250
2251 /* Note: NOT a call to WriteSwappedDataToClient,
2252 as we do NOT byte swap */
2253 ReformatImage(pBuf, (int) (nlines * widthBytesLine),
2254 1, ClientOrder(client));
2255
2256 WriteToClient(client, (int)(nlines * widthBytesLine), pBuf);
2257 linesDone += nlines;
2258 }
2259 }
2260 }
2261 }
2262 free(pBuf);
2263 return Success;
2264 }
2265
2266 int
ProcGetImage(ClientPtr client)2267 ProcGetImage(ClientPtr client)
2268 {
2269 REQUEST(xGetImageReq);
2270
2271 REQUEST_SIZE_MATCH(xGetImageReq);
2272
2273 return DoGetImage(client, stuff->format, stuff->drawable,
2274 stuff->x, stuff->y,
2275 (int) stuff->width, (int) stuff->height,
2276 stuff->planeMask);
2277 }
2278
2279 int
ProcPolyText(ClientPtr client)2280 ProcPolyText(ClientPtr client)
2281 {
2282 int err;
2283
2284 REQUEST(xPolyTextReq);
2285 DrawablePtr pDraw;
2286 GC *pGC;
2287
2288 REQUEST_AT_LEAST_SIZE(xPolyTextReq);
2289 VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
2290
2291 err = PolyText(client,
2292 pDraw,
2293 pGC,
2294 (unsigned char *) &stuff[1],
2295 ((unsigned char *) stuff) + (client->req_len << 2),
2296 stuff->x, stuff->y, stuff->reqType, stuff->drawable);
2297
2298 if (err == Success) {
2299 return Success;
2300 }
2301 else
2302 return err;
2303 }
2304
2305 int
ProcImageText8(ClientPtr client)2306 ProcImageText8(ClientPtr client)
2307 {
2308 int err;
2309 DrawablePtr pDraw;
2310 GC *pGC;
2311
2312 REQUEST(xImageTextReq);
2313
2314 REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars);
2315 VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
2316
2317 err = ImageText(client,
2318 pDraw,
2319 pGC,
2320 stuff->nChars,
2321 (unsigned char *) &stuff[1],
2322 stuff->x, stuff->y, stuff->reqType, stuff->drawable);
2323
2324 if (err == Success) {
2325 return Success;
2326 }
2327 else
2328 return err;
2329 }
2330
2331 int
ProcImageText16(ClientPtr client)2332 ProcImageText16(ClientPtr client)
2333 {
2334 int err;
2335 DrawablePtr pDraw;
2336 GC *pGC;
2337
2338 REQUEST(xImageTextReq);
2339
2340 REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars << 1);
2341 VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
2342
2343 err = ImageText(client,
2344 pDraw,
2345 pGC,
2346 stuff->nChars,
2347 (unsigned char *) &stuff[1],
2348 stuff->x, stuff->y, stuff->reqType, stuff->drawable);
2349
2350 if (err == Success) {
2351 return Success;
2352 }
2353 else
2354 return err;
2355 }
2356
2357 int
ProcCreateColormap(ClientPtr client)2358 ProcCreateColormap(ClientPtr client)
2359 {
2360 VisualPtr pVisual;
2361 ColormapPtr pmap;
2362 Colormap mid;
2363 WindowPtr pWin;
2364 ScreenPtr pScreen;
2365
2366 REQUEST(xCreateColormapReq);
2367 int i, result;
2368
2369 REQUEST_SIZE_MATCH(xCreateColormapReq);
2370
2371 if ((stuff->alloc != AllocNone) && (stuff->alloc != AllocAll)) {
2372 client->errorValue = stuff->alloc;
2373 return BadValue;
2374 }
2375 mid = stuff->mid;
2376 LEGAL_NEW_RESOURCE(mid, client);
2377 result = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
2378 if (result != Success)
2379 return result;
2380
2381 pScreen = pWin->drawable.pScreen;
2382 for (i = 0, pVisual = pScreen->visuals;
2383 i < pScreen->numVisuals; i++, pVisual++) {
2384 if (pVisual->vid != stuff->visual)
2385 continue;
2386 return CreateColormap(mid, pScreen, pVisual, &pmap,
2387 (int) stuff->alloc, client->index);
2388 }
2389 client->errorValue = stuff->visual;
2390 return BadMatch;
2391 }
2392
2393 int
ProcFreeColormap(ClientPtr client)2394 ProcFreeColormap(ClientPtr client)
2395 {
2396 ColormapPtr pmap;
2397 int rc;
2398
2399 REQUEST(xResourceReq);
2400
2401 REQUEST_SIZE_MATCH(xResourceReq);
2402 rc = dixLookupResourceByType((void **) &pmap, stuff->id, RT_COLORMAP,
2403 client, DixDestroyAccess);
2404 if (rc == Success) {
2405 /* Freeing a default colormap is a no-op */
2406 if (!(pmap->flags & IsDefault))
2407 FreeResource(stuff->id, RT_NONE);
2408 return Success;
2409 }
2410 else {
2411 client->errorValue = stuff->id;
2412 return rc;
2413 }
2414 }
2415
2416 int
ProcCopyColormapAndFree(ClientPtr client)2417 ProcCopyColormapAndFree(ClientPtr client)
2418 {
2419 Colormap mid;
2420 ColormapPtr pSrcMap;
2421
2422 REQUEST(xCopyColormapAndFreeReq);
2423 int rc;
2424
2425 REQUEST_SIZE_MATCH(xCopyColormapAndFreeReq);
2426 mid = stuff->mid;
2427 LEGAL_NEW_RESOURCE(mid, client);
2428 rc = dixLookupResourceByType((void **) &pSrcMap, stuff->srcCmap,
2429 RT_COLORMAP, client,
2430 DixReadAccess | DixRemoveAccess);
2431 if (rc == Success)
2432 return CopyColormapAndFree(mid, pSrcMap, client->index);
2433 client->errorValue = stuff->srcCmap;
2434 return rc;
2435 }
2436
2437 int
ProcInstallColormap(ClientPtr client)2438 ProcInstallColormap(ClientPtr client)
2439 {
2440 ColormapPtr pcmp;
2441 int rc;
2442
2443 REQUEST(xResourceReq);
2444 REQUEST_SIZE_MATCH(xResourceReq);
2445
2446 rc = dixLookupResourceByType((void **) &pcmp, stuff->id, RT_COLORMAP,
2447 client, DixInstallAccess);
2448 if (rc != Success)
2449 goto out;
2450
2451 rc = XaceHook(XACE_SCREEN_ACCESS, client, pcmp->pScreen, DixSetAttrAccess);
2452 if (rc != Success) {
2453 if (rc == BadValue)
2454 rc = BadColor;
2455 goto out;
2456 }
2457
2458 (*(pcmp->pScreen->InstallColormap)) (pcmp);
2459 return Success;
2460
2461 out:
2462 client->errorValue = stuff->id;
2463 return rc;
2464 }
2465
2466 int
ProcUninstallColormap(ClientPtr client)2467 ProcUninstallColormap(ClientPtr client)
2468 {
2469 ColormapPtr pcmp;
2470 int rc;
2471
2472 REQUEST(xResourceReq);
2473 REQUEST_SIZE_MATCH(xResourceReq);
2474
2475 rc = dixLookupResourceByType((void **) &pcmp, stuff->id, RT_COLORMAP,
2476 client, DixUninstallAccess);
2477 if (rc != Success)
2478 goto out;
2479
2480 rc = XaceHook(XACE_SCREEN_ACCESS, client, pcmp->pScreen, DixSetAttrAccess);
2481 if (rc != Success) {
2482 if (rc == BadValue)
2483 rc = BadColor;
2484 goto out;
2485 }
2486
2487 if (pcmp->mid != pcmp->pScreen->defColormap)
2488 (*(pcmp->pScreen->UninstallColormap)) (pcmp);
2489 return Success;
2490
2491 out:
2492 client->errorValue = stuff->id;
2493 return rc;
2494 }
2495
2496 int
ProcListInstalledColormaps(ClientPtr client)2497 ProcListInstalledColormaps(ClientPtr client)
2498 {
2499 xListInstalledColormapsReply *preply;
2500 int nummaps, rc;
2501 WindowPtr pWin;
2502
2503 REQUEST(xResourceReq);
2504 REQUEST_SIZE_MATCH(xResourceReq);
2505
2506 rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess);
2507 if (rc != Success)
2508 return rc;
2509
2510 rc = XaceHook(XACE_SCREEN_ACCESS, client, pWin->drawable.pScreen,
2511 DixGetAttrAccess);
2512 if (rc != Success)
2513 return rc;
2514
2515 preply = malloc(sizeof(xListInstalledColormapsReply) +
2516 pWin->drawable.pScreen->maxInstalledCmaps *
2517 sizeof(Colormap));
2518 if (!preply)
2519 return BadAlloc;
2520
2521 preply->type = X_Reply;
2522 preply->sequenceNumber = client->sequence;
2523 nummaps = (*pWin->drawable.pScreen->ListInstalledColormaps)
2524 (pWin->drawable.pScreen, (Colormap *) &preply[1]);
2525 preply->nColormaps = nummaps;
2526 preply->length = nummaps;
2527 WriteReplyToClient(client, sizeof(xListInstalledColormapsReply), preply);
2528 client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
2529 WriteSwappedDataToClient(client, nummaps * sizeof(Colormap), &preply[1]);
2530 free(preply);
2531 return Success;
2532 }
2533
2534 int
ProcAllocColor(ClientPtr client)2535 ProcAllocColor(ClientPtr client)
2536 {
2537 ColormapPtr pmap;
2538 int rc;
2539
2540 REQUEST(xAllocColorReq);
2541
2542 REQUEST_SIZE_MATCH(xAllocColorReq);
2543 rc = dixLookupResourceByType((void **) &pmap, stuff->cmap, RT_COLORMAP,
2544 client, DixAddAccess);
2545 if (rc == Success) {
2546 xAllocColorReply acr = {
2547 .type = X_Reply,
2548 .sequenceNumber = client->sequence,
2549 .length = 0,
2550 .red = stuff->red,
2551 .green = stuff->green,
2552 .blue = stuff->blue,
2553 .pixel = 0
2554 };
2555 if ((rc = AllocColor(pmap, &acr.red, &acr.green, &acr.blue,
2556 &acr.pixel, client->index)))
2557 return rc;
2558 #ifdef PANORAMIX
2559 if (noPanoramiXExtension || !pmap->pScreen->myNum)
2560 #endif
2561 WriteReplyToClient(client, sizeof(xAllocColorReply), &acr);
2562 return Success;
2563
2564 }
2565 else {
2566 client->errorValue = stuff->cmap;
2567 return rc;
2568 }
2569 }
2570
2571 int
ProcAllocNamedColor(ClientPtr client)2572 ProcAllocNamedColor(ClientPtr client)
2573 {
2574 ColormapPtr pcmp;
2575 int rc;
2576
2577 REQUEST(xAllocNamedColorReq);
2578
2579 REQUEST_FIXED_SIZE(xAllocNamedColorReq, stuff->nbytes);
2580 rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP,
2581 client, DixAddAccess);
2582 if (rc == Success) {
2583 xAllocNamedColorReply ancr = {
2584 .type = X_Reply,
2585 .sequenceNumber = client->sequence,
2586 .length = 0
2587 };
2588 if (OsLookupColor
2589 (pcmp->pScreen->myNum, (char *) &stuff[1], stuff->nbytes,
2590 &ancr.exactRed, &ancr.exactGreen, &ancr.exactBlue)) {
2591 ancr.screenRed = ancr.exactRed;
2592 ancr.screenGreen = ancr.exactGreen;
2593 ancr.screenBlue = ancr.exactBlue;
2594 ancr.pixel = 0;
2595 if ((rc = AllocColor(pcmp,
2596 &ancr.screenRed, &ancr.screenGreen,
2597 &ancr.screenBlue, &ancr.pixel, client->index)))
2598 return rc;
2599 #ifdef PANORAMIX
2600 if (noPanoramiXExtension || !pcmp->pScreen->myNum)
2601 #endif
2602 WriteReplyToClient(client, sizeof(xAllocNamedColorReply),
2603 &ancr);
2604 return Success;
2605 }
2606 else
2607 return BadName;
2608
2609 }
2610 else {
2611 client->errorValue = stuff->cmap;
2612 return rc;
2613 }
2614 }
2615
2616 int
ProcAllocColorCells(ClientPtr client)2617 ProcAllocColorCells(ClientPtr client)
2618 {
2619 ColormapPtr pcmp;
2620 int rc;
2621
2622 REQUEST(xAllocColorCellsReq);
2623
2624 REQUEST_SIZE_MATCH(xAllocColorCellsReq);
2625 rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP,
2626 client, DixAddAccess);
2627 if (rc == Success) {
2628 int npixels, nmasks;
2629 long length;
2630 Pixel *ppixels, *pmasks;
2631
2632 npixels = stuff->colors;
2633 if (!npixels) {
2634 client->errorValue = npixels;
2635 return BadValue;
2636 }
2637 if (stuff->contiguous != xTrue && stuff->contiguous != xFalse) {
2638 client->errorValue = stuff->contiguous;
2639 return BadValue;
2640 }
2641 nmasks = stuff->planes;
2642 length = ((long) npixels + (long) nmasks) * sizeof(Pixel);
2643 ppixels = malloc(length);
2644 if (!ppixels)
2645 return BadAlloc;
2646 pmasks = ppixels + npixels;
2647
2648 if ((rc = AllocColorCells(client->index, pcmp, npixels, nmasks,
2649 (Bool) stuff->contiguous, ppixels, pmasks))) {
2650 free(ppixels);
2651 return rc;
2652 }
2653 #ifdef PANORAMIX
2654 if (noPanoramiXExtension || !pcmp->pScreen->myNum)
2655 #endif
2656 {
2657 xAllocColorCellsReply accr = {
2658 .type = X_Reply,
2659 .sequenceNumber = client->sequence,
2660 .length = bytes_to_int32(length),
2661 .nPixels = npixels,
2662 .nMasks = nmasks
2663 };
2664 WriteReplyToClient(client, sizeof(xAllocColorCellsReply), &accr);
2665 client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
2666 WriteSwappedDataToClient(client, length, ppixels);
2667 }
2668 free(ppixels);
2669 return Success;
2670 }
2671 else {
2672 client->errorValue = stuff->cmap;
2673 return rc;
2674 }
2675 }
2676
2677 int
ProcAllocColorPlanes(ClientPtr client)2678 ProcAllocColorPlanes(ClientPtr client)
2679 {
2680 ColormapPtr pcmp;
2681 int rc;
2682
2683 REQUEST(xAllocColorPlanesReq);
2684
2685 REQUEST_SIZE_MATCH(xAllocColorPlanesReq);
2686 rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP,
2687 client, DixAddAccess);
2688 if (rc == Success) {
2689 xAllocColorPlanesReply acpr;
2690 int npixels;
2691 long length;
2692 Pixel *ppixels;
2693
2694 npixels = stuff->colors;
2695 if (!npixels) {
2696 client->errorValue = npixels;
2697 return BadValue;
2698 }
2699 if (stuff->contiguous != xTrue && stuff->contiguous != xFalse) {
2700 client->errorValue = stuff->contiguous;
2701 return BadValue;
2702 }
2703 acpr = (xAllocColorPlanesReply) {
2704 .type = X_Reply,
2705 .sequenceNumber = client->sequence,
2706 .nPixels = npixels
2707 };
2708 length = (long) npixels *sizeof(Pixel);
2709
2710 ppixels = malloc(length);
2711 if (!ppixels)
2712 return BadAlloc;
2713 if ((rc = AllocColorPlanes(client->index, pcmp, npixels,
2714 (int) stuff->red, (int) stuff->green,
2715 (int) stuff->blue, (Bool) stuff->contiguous,
2716 ppixels, &acpr.redMask, &acpr.greenMask,
2717 &acpr.blueMask))) {
2718 free(ppixels);
2719 return rc;
2720 }
2721 acpr.length = bytes_to_int32(length);
2722 #ifdef PANORAMIX
2723 if (noPanoramiXExtension || !pcmp->pScreen->myNum)
2724 #endif
2725 {
2726 WriteReplyToClient(client, sizeof(xAllocColorPlanesReply), &acpr);
2727 client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
2728 WriteSwappedDataToClient(client, length, ppixels);
2729 }
2730 free(ppixels);
2731 return Success;
2732 }
2733 else {
2734 client->errorValue = stuff->cmap;
2735 return rc;
2736 }
2737 }
2738
2739 int
ProcFreeColors(ClientPtr client)2740 ProcFreeColors(ClientPtr client)
2741 {
2742 ColormapPtr pcmp;
2743 int rc;
2744
2745 REQUEST(xFreeColorsReq);
2746
2747 REQUEST_AT_LEAST_SIZE(xFreeColorsReq);
2748 rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP,
2749 client, DixRemoveAccess);
2750 if (rc == Success) {
2751 int count;
2752
2753 if (pcmp->flags & AllAllocated)
2754 return BadAccess;
2755 count = bytes_to_int32((client->req_len << 2) - sizeof(xFreeColorsReq));
2756 return FreeColors(pcmp, client->index, count,
2757 (Pixel *) &stuff[1], (Pixel) stuff->planeMask);
2758 }
2759 else {
2760 client->errorValue = stuff->cmap;
2761 return rc;
2762 }
2763 }
2764
2765 int
ProcStoreColors(ClientPtr client)2766 ProcStoreColors(ClientPtr client)
2767 {
2768 ColormapPtr pcmp;
2769 int rc;
2770
2771 REQUEST(xStoreColorsReq);
2772
2773 REQUEST_AT_LEAST_SIZE(xStoreColorsReq);
2774 rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP,
2775 client, DixWriteAccess);
2776 if (rc == Success) {
2777 int count;
2778
2779 count = (client->req_len << 2) - sizeof(xStoreColorsReq);
2780 if (count % sizeof(xColorItem))
2781 return BadLength;
2782 count /= sizeof(xColorItem);
2783 return StoreColors(pcmp, count, (xColorItem *) &stuff[1], client);
2784 }
2785 else {
2786 client->errorValue = stuff->cmap;
2787 return rc;
2788 }
2789 }
2790
2791 int
ProcStoreNamedColor(ClientPtr client)2792 ProcStoreNamedColor(ClientPtr client)
2793 {
2794 ColormapPtr pcmp;
2795 int rc;
2796
2797 REQUEST(xStoreNamedColorReq);
2798
2799 REQUEST_FIXED_SIZE(xStoreNamedColorReq, stuff->nbytes);
2800 rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP,
2801 client, DixWriteAccess);
2802 if (rc == Success) {
2803 xColorItem def;
2804
2805 if (OsLookupColor(pcmp->pScreen->myNum, (char *) &stuff[1],
2806 stuff->nbytes, &def.red, &def.green, &def.blue)) {
2807 def.flags = stuff->flags;
2808 def.pixel = stuff->pixel;
2809 return StoreColors(pcmp, 1, &def, client);
2810 }
2811 return BadName;
2812 }
2813 else {
2814 client->errorValue = stuff->cmap;
2815 return rc;
2816 }
2817 }
2818
2819 int
ProcQueryColors(ClientPtr client)2820 ProcQueryColors(ClientPtr client)
2821 {
2822 ColormapPtr pcmp;
2823 int rc;
2824
2825 REQUEST(xQueryColorsReq);
2826
2827 REQUEST_AT_LEAST_SIZE(xQueryColorsReq);
2828 rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP,
2829 client, DixReadAccess);
2830 if (rc == Success) {
2831 int count;
2832 xrgb *prgbs;
2833 xQueryColorsReply qcr;
2834
2835 count =
2836 bytes_to_int32((client->req_len << 2) - sizeof(xQueryColorsReq));
2837 prgbs = calloc(count, sizeof(xrgb));
2838 if (!prgbs && count)
2839 return BadAlloc;
2840 if ((rc =
2841 QueryColors(pcmp, count, (Pixel *) &stuff[1], prgbs, client))) {
2842 free(prgbs);
2843 return rc;
2844 }
2845 qcr = (xQueryColorsReply) {
2846 .type = X_Reply,
2847 .sequenceNumber = client->sequence,
2848 .length = bytes_to_int32(count * sizeof(xrgb)),
2849 .nColors = count
2850 };
2851 WriteReplyToClient(client, sizeof(xQueryColorsReply), &qcr);
2852 if (count) {
2853 client->pSwapReplyFunc = (ReplySwapPtr) SQColorsExtend;
2854 WriteSwappedDataToClient(client, count * sizeof(xrgb), prgbs);
2855 }
2856 free(prgbs);
2857 return Success;
2858
2859 }
2860 else {
2861 client->errorValue = stuff->cmap;
2862 return rc;
2863 }
2864 }
2865
2866 int
ProcLookupColor(ClientPtr client)2867 ProcLookupColor(ClientPtr client)
2868 {
2869 ColormapPtr pcmp;
2870 int rc;
2871
2872 REQUEST(xLookupColorReq);
2873
2874 REQUEST_FIXED_SIZE(xLookupColorReq, stuff->nbytes);
2875 rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP,
2876 client, DixReadAccess);
2877 if (rc == Success) {
2878 CARD16 exactRed, exactGreen, exactBlue;
2879
2880 if (OsLookupColor
2881 (pcmp->pScreen->myNum, (char *) &stuff[1], stuff->nbytes,
2882 &exactRed, &exactGreen, &exactBlue)) {
2883 xLookupColorReply lcr = {
2884 .type = X_Reply,
2885 .sequenceNumber = client->sequence,
2886 .length = 0,
2887 .exactRed = exactRed,
2888 .exactGreen = exactGreen,
2889 .exactBlue = exactBlue,
2890 .screenRed = exactRed,
2891 .screenGreen = exactGreen,
2892 .screenBlue = exactBlue
2893 };
2894 (*pcmp->pScreen->ResolveColor) (&lcr.screenRed,
2895 &lcr.screenGreen,
2896 &lcr.screenBlue, pcmp->pVisual);
2897 WriteReplyToClient(client, sizeof(xLookupColorReply), &lcr);
2898 return Success;
2899 }
2900 return BadName;
2901 }
2902 else {
2903 client->errorValue = stuff->cmap;
2904 return rc;
2905 }
2906 }
2907
2908 int
ProcCreateCursor(ClientPtr client)2909 ProcCreateCursor(ClientPtr client)
2910 {
2911 CursorPtr pCursor;
2912 PixmapPtr src;
2913 PixmapPtr msk;
2914 unsigned char *srcbits;
2915 unsigned char *mskbits;
2916 unsigned short width, height;
2917 long n;
2918 CursorMetricRec cm;
2919 int rc;
2920
2921 REQUEST(xCreateCursorReq);
2922
2923 REQUEST_SIZE_MATCH(xCreateCursorReq);
2924 LEGAL_NEW_RESOURCE(stuff->cid, client);
2925
2926 rc = dixLookupResourceByType((void **) &src, stuff->source, RT_PIXMAP,
2927 client, DixReadAccess);
2928 if (rc != Success) {
2929 client->errorValue = stuff->source;
2930 return rc;
2931 }
2932
2933 if (src->drawable.depth != 1)
2934 return (BadMatch);
2935
2936 /* Find and validate cursor mask pixmap, if one is provided */
2937 if (stuff->mask != None) {
2938 rc = dixLookupResourceByType((void **) &msk, stuff->mask, RT_PIXMAP,
2939 client, DixReadAccess);
2940 if (rc != Success) {
2941 client->errorValue = stuff->mask;
2942 return rc;
2943 }
2944
2945 if (src->drawable.width != msk->drawable.width
2946 || src->drawable.height != msk->drawable.height
2947 || src->drawable.depth != 1 || msk->drawable.depth != 1)
2948 return BadMatch;
2949 }
2950 else
2951 msk = NULL;
2952
2953 width = src->drawable.width;
2954 height = src->drawable.height;
2955
2956 if (stuff->x > width || stuff->y > height)
2957 return BadMatch;
2958
2959 srcbits = calloc(BitmapBytePad(width), height);
2960 if (!srcbits)
2961 return BadAlloc;
2962 n = BitmapBytePad(width) * height;
2963 mskbits = malloc(n);
2964 if (!mskbits) {
2965 free(srcbits);
2966 return BadAlloc;
2967 }
2968
2969 (*src->drawable.pScreen->GetImage) ((DrawablePtr) src, 0, 0, width, height,
2970 XYPixmap, 1, (void *) srcbits);
2971 if (msk == (PixmapPtr) NULL) {
2972 unsigned char *bits = mskbits;
2973
2974 while (--n >= 0)
2975 *bits++ = ~0;
2976 }
2977 else {
2978 /* zeroing the (pad) bits helps some ddx cursor handling */
2979 memset((char *) mskbits, 0, n);
2980 (*msk->drawable.pScreen->GetImage) ((DrawablePtr) msk, 0, 0, width,
2981 height, XYPixmap, 1,
2982 (void *) mskbits);
2983 }
2984 cm.width = width;
2985 cm.height = height;
2986 cm.xhot = stuff->x;
2987 cm.yhot = stuff->y;
2988 rc = AllocARGBCursor(srcbits, mskbits, NULL, &cm,
2989 stuff->foreRed, stuff->foreGreen, stuff->foreBlue,
2990 stuff->backRed, stuff->backGreen, stuff->backBlue,
2991 &pCursor, client, stuff->cid);
2992
2993 if (rc != Success)
2994 goto bail;
2995 if (!AddResource(stuff->cid, RT_CURSOR, (void *) pCursor)) {
2996 rc = BadAlloc;
2997 goto bail;
2998 }
2999
3000 return Success;
3001 bail:
3002 free(srcbits);
3003 free(mskbits);
3004 return rc;
3005 }
3006
3007 int
ProcCreateGlyphCursor(ClientPtr client)3008 ProcCreateGlyphCursor(ClientPtr client)
3009 {
3010 CursorPtr pCursor;
3011 int res;
3012
3013 REQUEST(xCreateGlyphCursorReq);
3014
3015 REQUEST_SIZE_MATCH(xCreateGlyphCursorReq);
3016 LEGAL_NEW_RESOURCE(stuff->cid, client);
3017
3018 res = AllocGlyphCursor(stuff->source, stuff->sourceChar,
3019 stuff->mask, stuff->maskChar,
3020 stuff->foreRed, stuff->foreGreen, stuff->foreBlue,
3021 stuff->backRed, stuff->backGreen, stuff->backBlue,
3022 &pCursor, client, stuff->cid);
3023 if (res != Success)
3024 return res;
3025 if (AddResource(stuff->cid, RT_CURSOR, (void *) pCursor))
3026 return Success;
3027 return BadAlloc;
3028 }
3029
3030 int
ProcFreeCursor(ClientPtr client)3031 ProcFreeCursor(ClientPtr client)
3032 {
3033 CursorPtr pCursor;
3034 int rc;
3035
3036 REQUEST(xResourceReq);
3037
3038 REQUEST_SIZE_MATCH(xResourceReq);
3039 rc = dixLookupResourceByType((void **) &pCursor, stuff->id, RT_CURSOR,
3040 client, DixDestroyAccess);
3041 if (rc == Success) {
3042 FreeResource(stuff->id, RT_NONE);
3043 return Success;
3044 }
3045 else {
3046 client->errorValue = stuff->id;
3047 return rc;
3048 }
3049 }
3050
3051 int
ProcQueryBestSize(ClientPtr client)3052 ProcQueryBestSize(ClientPtr client)
3053 {
3054 xQueryBestSizeReply reply;
3055 DrawablePtr pDraw;
3056 ScreenPtr pScreen;
3057 int rc;
3058
3059 REQUEST(xQueryBestSizeReq);
3060 REQUEST_SIZE_MATCH(xQueryBestSizeReq);
3061
3062 if ((stuff->class != CursorShape) &&
3063 (stuff->class != TileShape) && (stuff->class != StippleShape)) {
3064 client->errorValue = stuff->class;
3065 return BadValue;
3066 }
3067
3068 rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY,
3069 DixGetAttrAccess);
3070 if (rc != Success)
3071 return rc;
3072 if (stuff->class != CursorShape && pDraw->type == UNDRAWABLE_WINDOW)
3073 return BadMatch;
3074 pScreen = pDraw->pScreen;
3075 rc = XaceHook(XACE_SCREEN_ACCESS, client, pScreen, DixGetAttrAccess);
3076 if (rc != Success)
3077 return rc;
3078 (*pScreen->QueryBestSize) (stuff->class, &stuff->width,
3079 &stuff->height, pScreen);
3080 reply = (xQueryBestSizeReply) {
3081 .type = X_Reply,
3082 .sequenceNumber = client->sequence,
3083 .length = 0,
3084 .width = stuff->width,
3085 .height = stuff->height
3086 };
3087 WriteReplyToClient(client, sizeof(xQueryBestSizeReply), &reply);
3088 return Success;
3089 }
3090
3091 int
ProcSetScreenSaver(ClientPtr client)3092 ProcSetScreenSaver(ClientPtr client)
3093 {
3094 int rc, i, blankingOption, exposureOption;
3095
3096 REQUEST(xSetScreenSaverReq);
3097 REQUEST_SIZE_MATCH(xSetScreenSaverReq);
3098
3099 for (i = 0; i < screenInfo.numScreens; i++) {
3100 rc = XaceHook(XACE_SCREENSAVER_ACCESS, client, screenInfo.screens[i],
3101 DixSetAttrAccess);
3102 if (rc != Success)
3103 return rc;
3104 }
3105
3106 blankingOption = stuff->preferBlank;
3107 if ((blankingOption != DontPreferBlanking) &&
3108 (blankingOption != PreferBlanking) &&
3109 (blankingOption != DefaultBlanking)) {
3110 client->errorValue = blankingOption;
3111 return BadValue;
3112 }
3113 exposureOption = stuff->allowExpose;
3114 if ((exposureOption != DontAllowExposures) &&
3115 (exposureOption != AllowExposures) &&
3116 (exposureOption != DefaultExposures)) {
3117 client->errorValue = exposureOption;
3118 return BadValue;
3119 }
3120 if (stuff->timeout < -1) {
3121 client->errorValue = stuff->timeout;
3122 return BadValue;
3123 }
3124 if (stuff->interval < -1) {
3125 client->errorValue = stuff->interval;
3126 return BadValue;
3127 }
3128
3129 if (blankingOption == DefaultBlanking)
3130 ScreenSaverBlanking = defaultScreenSaverBlanking;
3131 else
3132 ScreenSaverBlanking = blankingOption;
3133 if (exposureOption == DefaultExposures)
3134 ScreenSaverAllowExposures = defaultScreenSaverAllowExposures;
3135 else
3136 ScreenSaverAllowExposures = exposureOption;
3137
3138 if (stuff->timeout >= 0)
3139 ScreenSaverTime = stuff->timeout * MILLI_PER_SECOND;
3140 else
3141 ScreenSaverTime = defaultScreenSaverTime;
3142 if (stuff->interval >= 0)
3143 ScreenSaverInterval = stuff->interval * MILLI_PER_SECOND;
3144 else
3145 ScreenSaverInterval = defaultScreenSaverInterval;
3146
3147 SetScreenSaverTimer();
3148 return Success;
3149 }
3150
3151 int
ProcGetScreenSaver(ClientPtr client)3152 ProcGetScreenSaver(ClientPtr client)
3153 {
3154 xGetScreenSaverReply rep;
3155 int rc, i;
3156
3157 REQUEST_SIZE_MATCH(xReq);
3158
3159 for (i = 0; i < screenInfo.numScreens; i++) {
3160 rc = XaceHook(XACE_SCREENSAVER_ACCESS, client, screenInfo.screens[i],
3161 DixGetAttrAccess);
3162 if (rc != Success)
3163 return rc;
3164 }
3165
3166 rep = (xGetScreenSaverReply) {
3167 .type = X_Reply,
3168 .sequenceNumber = client->sequence,
3169 .length = 0,
3170 .timeout = ScreenSaverTime / MILLI_PER_SECOND,
3171 .interval = ScreenSaverInterval / MILLI_PER_SECOND,
3172 .preferBlanking = ScreenSaverBlanking,
3173 .allowExposures = ScreenSaverAllowExposures
3174 };
3175 WriteReplyToClient(client, sizeof(xGetScreenSaverReply), &rep);
3176 return Success;
3177 }
3178
3179 int
ProcChangeHosts(ClientPtr client)3180 ProcChangeHosts(ClientPtr client)
3181 {
3182 REQUEST(xChangeHostsReq);
3183
3184 REQUEST_FIXED_SIZE(xChangeHostsReq, stuff->hostLength);
3185
3186 if (stuff->mode == HostInsert)
3187 return AddHost(client, (int) stuff->hostFamily,
3188 stuff->hostLength, (void *) &stuff[1]);
3189 if (stuff->mode == HostDelete)
3190 return RemoveHost(client, (int) stuff->hostFamily,
3191 stuff->hostLength, (void *) &stuff[1]);
3192 client->errorValue = stuff->mode;
3193 return BadValue;
3194 }
3195
3196 int
ProcListHosts(ClientPtr client)3197 ProcListHosts(ClientPtr client)
3198 {
3199 xListHostsReply reply;
3200 int len, nHosts, result;
3201 BOOL enabled;
3202 void *pdata;
3203
3204 /* REQUEST(xListHostsReq); */
3205
3206 REQUEST_SIZE_MATCH(xListHostsReq);
3207
3208 /* untrusted clients can't list hosts */
3209 result = XaceHook(XACE_SERVER_ACCESS, client, DixReadAccess);
3210 if (result != Success)
3211 return result;
3212
3213 result = GetHosts(&pdata, &nHosts, &len, &enabled);
3214 if (result != Success)
3215 return result;
3216
3217 reply = (xListHostsReply) {
3218 .type = X_Reply,
3219 .enabled = enabled,
3220 .sequenceNumber = client->sequence,
3221 .length = bytes_to_int32(len),
3222 .nHosts = nHosts
3223 };
3224 WriteReplyToClient(client, sizeof(xListHostsReply), &reply);
3225 if (nHosts) {
3226 client->pSwapReplyFunc = (ReplySwapPtr) SLHostsExtend;
3227 WriteSwappedDataToClient(client, len, pdata);
3228 }
3229 free(pdata);
3230 return Success;
3231 }
3232
3233 int
ProcChangeAccessControl(ClientPtr client)3234 ProcChangeAccessControl(ClientPtr client)
3235 {
3236 REQUEST(xSetAccessControlReq);
3237
3238 REQUEST_SIZE_MATCH(xSetAccessControlReq);
3239 if ((stuff->mode != EnableAccess) && (stuff->mode != DisableAccess)) {
3240 client->errorValue = stuff->mode;
3241 return BadValue;
3242 }
3243 return ChangeAccessControl(client, stuff->mode == EnableAccess);
3244 }
3245
3246 /*********************
3247 * CloseDownRetainedResources
3248 *
3249 * Find all clients that are gone and have terminated in RetainTemporary
3250 * and destroy their resources.
3251 *********************/
3252
3253 static void
CloseDownRetainedResources(void)3254 CloseDownRetainedResources(void)
3255 {
3256 int i;
3257 ClientPtr client;
3258
3259 for (i = 1; i < currentMaxClients; i++) {
3260 client = clients[i];
3261 if (client && (client->closeDownMode == RetainTemporary)
3262 && (client->clientGone))
3263 CloseDownClient(client);
3264 }
3265 }
3266
3267 int
ProcKillClient(ClientPtr client)3268 ProcKillClient(ClientPtr client)
3269 {
3270 REQUEST(xResourceReq);
3271 ClientPtr killclient;
3272 int rc;
3273
3274 REQUEST_SIZE_MATCH(xResourceReq);
3275 if (stuff->id == AllTemporary) {
3276 CloseDownRetainedResources();
3277 return Success;
3278 }
3279
3280 rc = dixLookupClient(&killclient, stuff->id, client, DixDestroyAccess);
3281 if (rc == Success) {
3282 CloseDownClient(killclient);
3283 if (client == killclient) {
3284 /* force yield and return Success, so that Dispatch()
3285 * doesn't try to touch client
3286 */
3287 isItTimeToYield = TRUE;
3288 }
3289 return Success;
3290 }
3291 else
3292 return rc;
3293 }
3294
3295 int
ProcSetFontPath(ClientPtr client)3296 ProcSetFontPath(ClientPtr client)
3297 {
3298 unsigned char *ptr;
3299 unsigned long nbytes, total;
3300 long nfonts;
3301 int n;
3302
3303 REQUEST(xSetFontPathReq);
3304
3305 REQUEST_AT_LEAST_SIZE(xSetFontPathReq);
3306
3307 nbytes = (client->req_len << 2) - sizeof(xSetFontPathReq);
3308 total = nbytes;
3309 ptr = (unsigned char *) &stuff[1];
3310 nfonts = stuff->nFonts;
3311 while (--nfonts >= 0) {
3312 if ((total == 0) || (total < (n = (*ptr + 1))))
3313 return BadLength;
3314 total -= n;
3315 ptr += n;
3316 }
3317 if (total >= 4)
3318 return BadLength;
3319 return SetFontPath(client, stuff->nFonts, (unsigned char *) &stuff[1]);
3320 }
3321
3322 int
ProcGetFontPath(ClientPtr client)3323 ProcGetFontPath(ClientPtr client)
3324 {
3325 xGetFontPathReply reply;
3326 int rc, stringLens, numpaths;
3327 unsigned char *bufferStart;
3328
3329 /* REQUEST (xReq); */
3330
3331 REQUEST_SIZE_MATCH(xReq);
3332 rc = GetFontPath(client, &numpaths, &stringLens, &bufferStart);
3333 if (rc != Success)
3334 return rc;
3335
3336 reply = (xGetFontPathReply) {
3337 .type = X_Reply,
3338 .sequenceNumber = client->sequence,
3339 .length = bytes_to_int32(stringLens + numpaths),
3340 .nPaths = numpaths
3341 };
3342
3343 WriteReplyToClient(client, sizeof(xGetFontPathReply), &reply);
3344 if (stringLens || numpaths)
3345 WriteToClient(client, stringLens + numpaths, bufferStart);
3346 return Success;
3347 }
3348
3349 int
ProcChangeCloseDownMode(ClientPtr client)3350 ProcChangeCloseDownMode(ClientPtr client)
3351 {
3352 int rc;
3353
3354 REQUEST(xSetCloseDownModeReq);
3355 REQUEST_SIZE_MATCH(xSetCloseDownModeReq);
3356
3357 rc = XaceHook(XACE_CLIENT_ACCESS, client, client, DixManageAccess);
3358 if (rc != Success)
3359 return rc;
3360
3361 if ((stuff->mode == AllTemporary) ||
3362 (stuff->mode == RetainPermanent) || (stuff->mode == RetainTemporary)) {
3363 client->closeDownMode = stuff->mode;
3364 return Success;
3365 }
3366 else {
3367 client->errorValue = stuff->mode;
3368 return BadValue;
3369 }
3370 }
3371
3372 int
ProcForceScreenSaver(ClientPtr client)3373 ProcForceScreenSaver(ClientPtr client)
3374 {
3375 int rc;
3376
3377 REQUEST(xForceScreenSaverReq);
3378
3379 REQUEST_SIZE_MATCH(xForceScreenSaverReq);
3380
3381 if ((stuff->mode != ScreenSaverReset) && (stuff->mode != ScreenSaverActive)) {
3382 client->errorValue = stuff->mode;
3383 return BadValue;
3384 }
3385 rc = dixSaveScreens(client, SCREEN_SAVER_FORCER, (int) stuff->mode);
3386 if (rc != Success)
3387 return rc;
3388 return Success;
3389 }
3390
3391 int
ProcNoOperation(ClientPtr client)3392 ProcNoOperation(ClientPtr client)
3393 {
3394 REQUEST_AT_LEAST_SIZE(xReq);
3395
3396 /* noop -- don't do anything */
3397 return Success;
3398 }
3399
3400 /**********************
3401 * CloseDownClient
3402 *
3403 * Client can either mark his resources destroy or retain. If retained and
3404 * then killed again, the client is really destroyed.
3405 *********************/
3406
3407 char dispatchExceptionAtReset = DE_RESET;
3408
3409 void
CloseDownClient(ClientPtr client)3410 CloseDownClient(ClientPtr client)
3411 {
3412 Bool really_close_down = client->clientGone ||
3413 client->closeDownMode == DestroyAll;
3414
3415 if (!client->clientGone) {
3416 /* ungrab server if grabbing client dies */
3417 if (grabState != GrabNone && grabClient == client) {
3418 UngrabServer(client);
3419 }
3420 BITCLEAR(grabWaiters, client->index);
3421 DeleteClientFromAnySelections(client);
3422 ReleaseActiveGrabs(client);
3423 DeleteClientFontStuff(client);
3424 if (!really_close_down) {
3425 /* This frees resources that should never be retained
3426 * no matter what the close down mode is. Actually we
3427 * could do this unconditionally, but it's probably
3428 * better not to traverse all the client's resources
3429 * twice (once here, once a few lines down in
3430 * FreeClientResources) in the common case of
3431 * really_close_down == TRUE.
3432 */
3433 FreeClientNeverRetainResources(client);
3434 client->clientState = ClientStateRetained;
3435 if (ClientStateCallback) {
3436 NewClientInfoRec clientinfo;
3437
3438 clientinfo.client = client;
3439 clientinfo.prefix = (xConnSetupPrefix *) NULL;
3440 clientinfo.setup = (xConnSetup *) NULL;
3441 CallCallbacks((&ClientStateCallback), (void *) &clientinfo);
3442 }
3443 }
3444 client->clientGone = TRUE; /* so events aren't sent to client */
3445 if (ClientIsAsleep(client))
3446 ClientSignal(client);
3447 ProcessWorkQueueZombies();
3448 CloseDownConnection(client);
3449 output_pending_clear(client);
3450 mark_client_not_ready(client);
3451
3452 /* If the client made it to the Running stage, nClients has
3453 * been incremented on its behalf, so we need to decrement it
3454 * now. If it hasn't gotten to Running, nClients has *not*
3455 * been incremented, so *don't* decrement it.
3456 */
3457 if (client->clientState != ClientStateInitial) {
3458 --nClients;
3459 }
3460 }
3461
3462 if (really_close_down) {
3463 if (client->clientState == ClientStateRunning && nClients == 0)
3464 dispatchException |= dispatchExceptionAtReset;
3465
3466 client->clientState = ClientStateGone;
3467 if (ClientStateCallback) {
3468 NewClientInfoRec clientinfo;
3469
3470 clientinfo.client = client;
3471 clientinfo.prefix = (xConnSetupPrefix *) NULL;
3472 clientinfo.setup = (xConnSetup *) NULL;
3473 CallCallbacks((&ClientStateCallback), (void *) &clientinfo);
3474 }
3475 TouchListenerGone(client->clientAsMask);
3476 FreeClientResources(client);
3477 /* Disable client ID tracking. This must be done after
3478 * ClientStateCallback. */
3479 ReleaseClientIds(client);
3480 #ifdef XSERVER_DTRACE
3481 XSERVER_CLIENT_DISCONNECT(client->index);
3482 #endif
3483 if (client->index < nextFreeClientID)
3484 nextFreeClientID = client->index;
3485 clients[client->index] = NullClient;
3486 SmartLastClient = NullClient;
3487 dixFreeObjectWithPrivates(client, PRIVATE_CLIENT);
3488
3489 while (!clients[currentMaxClients - 1])
3490 currentMaxClients--;
3491 }
3492 }
3493
3494 static void
KillAllClients(void)3495 KillAllClients(void)
3496 {
3497 int i;
3498
3499 for (i = 1; i < currentMaxClients; i++)
3500 if (clients[i]) {
3501 /* Make sure Retained clients are released. */
3502 clients[i]->closeDownMode = DestroyAll;
3503 CloseDownClient(clients[i]);
3504 }
3505 }
3506
3507 void
InitClient(ClientPtr client,int i,void * ospriv)3508 InitClient(ClientPtr client, int i, void *ospriv)
3509 {
3510 client->index = i;
3511 xorg_list_init(&client->ready);
3512 xorg_list_init(&client->output_pending);
3513 client->clientAsMask = ((Mask) i) << CLIENTOFFSET;
3514 client->closeDownMode = i ? DestroyAll : RetainPermanent;
3515 client->requestVector = InitialVector;
3516 client->osPrivate = ospriv;
3517 QueryMinMaxKeyCodes(&client->minKC, &client->maxKC);
3518 client->smart_start_tick = SmartScheduleTime;
3519 client->smart_stop_tick = SmartScheduleTime;
3520 client->clientIds = NULL;
3521 }
3522
3523 /************************
3524 * int NextAvailableClient(ospriv)
3525 *
3526 * OS dependent portion can't assign client id's because of CloseDownModes.
3527 * Returns NULL if there are no free clients.
3528 *************************/
3529
3530 ClientPtr
NextAvailableClient(void * ospriv)3531 NextAvailableClient(void *ospriv)
3532 {
3533 int i;
3534 ClientPtr client;
3535 xReq data;
3536
3537 i = nextFreeClientID;
3538 if (i == LimitClients)
3539 return (ClientPtr) NULL;
3540 clients[i] = client =
3541 dixAllocateObjectWithPrivates(ClientRec, PRIVATE_CLIENT);
3542 if (!client)
3543 return (ClientPtr) NULL;
3544 InitClient(client, i, ospriv);
3545 if (!InitClientResources(client)) {
3546 dixFreeObjectWithPrivates(client, PRIVATE_CLIENT);
3547 return (ClientPtr) NULL;
3548 }
3549 data.reqType = 1;
3550 data.length = bytes_to_int32(sz_xReq + sz_xConnClientPrefix);
3551 if (!InsertFakeRequest(client, (char *) &data, sz_xReq)) {
3552 FreeClientResources(client);
3553 dixFreeObjectWithPrivates(client, PRIVATE_CLIENT);
3554 return (ClientPtr) NULL;
3555 }
3556 if (i == currentMaxClients)
3557 currentMaxClients++;
3558 while ((nextFreeClientID < LimitClients) && clients[nextFreeClientID])
3559 nextFreeClientID++;
3560
3561 /* Enable client ID tracking. This must be done before
3562 * ClientStateCallback. */
3563 ReserveClientIds(client);
3564
3565 if (ClientStateCallback) {
3566 NewClientInfoRec clientinfo;
3567
3568 clientinfo.client = client;
3569 clientinfo.prefix = (xConnSetupPrefix *) NULL;
3570 clientinfo.setup = (xConnSetup *) NULL;
3571 CallCallbacks((&ClientStateCallback), (void *) &clientinfo);
3572 }
3573 return client;
3574 }
3575
3576 int
ProcInitialConnection(ClientPtr client)3577 ProcInitialConnection(ClientPtr client)
3578 {
3579 REQUEST(xReq);
3580 xConnClientPrefix *prefix;
3581 int whichbyte = 1;
3582 char order;
3583
3584 prefix = (xConnClientPrefix *) ((char *)stuff + sz_xReq);
3585 order = prefix->byteOrder;
3586 if (order != 'l' && order != 'B' && order != 'r' && order != 'R')
3587 return client->noClientException = -1;
3588 if (((*(char *) &whichbyte) && (order == 'B' || order == 'R')) ||
3589 (!(*(char *) &whichbyte) && (order == 'l' || order == 'r'))) {
3590 client->swapped = TRUE;
3591 SwapConnClientPrefix(prefix);
3592 }
3593 stuff->reqType = 2;
3594 stuff->length += bytes_to_int32(prefix->nbytesAuthProto) +
3595 bytes_to_int32(prefix->nbytesAuthString);
3596 if (client->swapped) {
3597 swaps(&stuff->length);
3598 }
3599 if (order == 'r' || order == 'R') {
3600 client->local = FALSE;
3601 }
3602 ResetCurrentRequest(client);
3603 return Success;
3604 }
3605
3606 static int
SendConnSetup(ClientPtr client,const char * reason)3607 SendConnSetup(ClientPtr client, const char *reason)
3608 {
3609 xWindowRoot *root;
3610 int i;
3611 int numScreens;
3612 char *lConnectionInfo;
3613 xConnSetupPrefix *lconnSetupPrefix;
3614
3615 if (reason) {
3616 xConnSetupPrefix csp;
3617
3618 csp.success = xFalse;
3619 csp.lengthReason = strlen(reason);
3620 csp.length = bytes_to_int32(csp.lengthReason);
3621 csp.majorVersion = X_PROTOCOL;
3622 csp.minorVersion = X_PROTOCOL_REVISION;
3623 if (client->swapped)
3624 WriteSConnSetupPrefix(client, &csp);
3625 else
3626 WriteToClient(client, sz_xConnSetupPrefix, &csp);
3627 WriteToClient(client, (int) csp.lengthReason, reason);
3628 return client->noClientException = -1;
3629 }
3630
3631 numScreens = screenInfo.numScreens;
3632 lConnectionInfo = ConnectionInfo;
3633 lconnSetupPrefix = &connSetupPrefix;
3634
3635 /* We're about to start speaking X protocol back to the client by
3636 * sending the connection setup info. This means the authorization
3637 * step is complete, and we can count the client as an
3638 * authorized one.
3639 */
3640 nClients++;
3641
3642 client->requestVector = client->swapped ? SwappedProcVector : ProcVector;
3643 client->sequence = 0;
3644 ((xConnSetup *) lConnectionInfo)->ridBase = client->clientAsMask;
3645 ((xConnSetup *) lConnectionInfo)->ridMask = RESOURCE_ID_MASK;
3646 #ifdef MATCH_CLIENT_ENDIAN
3647 ((xConnSetup *) lConnectionInfo)->imageByteOrder = ClientOrder(client);
3648 ((xConnSetup *) lConnectionInfo)->bitmapBitOrder = ClientOrder(client);
3649 #endif
3650 /* fill in the "currentInputMask" */
3651 root = (xWindowRoot *) (lConnectionInfo + connBlockScreenStart);
3652 #ifdef PANORAMIX
3653 if (noPanoramiXExtension)
3654 numScreens = screenInfo.numScreens;
3655 else
3656 numScreens = ((xConnSetup *) ConnectionInfo)->numRoots;
3657 #endif
3658
3659 for (i = 0; i < numScreens; i++) {
3660 unsigned int j;
3661 xDepth *pDepth;
3662 WindowPtr pRoot = screenInfo.screens[i]->root;
3663
3664 root->currentInputMask = pRoot->eventMask | wOtherEventMasks(pRoot);
3665 pDepth = (xDepth *) (root + 1);
3666 for (j = 0; j < root->nDepths; j++) {
3667 pDepth = (xDepth *) (((char *) (pDepth + 1)) +
3668 pDepth->nVisuals * sizeof(xVisualType));
3669 }
3670 root = (xWindowRoot *) pDepth;
3671 }
3672
3673 if (client->swapped) {
3674 WriteSConnSetupPrefix(client, lconnSetupPrefix);
3675 WriteSConnectionInfo(client,
3676 (unsigned long) (lconnSetupPrefix->length << 2),
3677 lConnectionInfo);
3678 }
3679 else {
3680 WriteToClient(client, sizeof(xConnSetupPrefix), lconnSetupPrefix);
3681 WriteToClient(client, (int) (lconnSetupPrefix->length << 2),
3682 lConnectionInfo);
3683 }
3684 client->clientState = ClientStateRunning;
3685 if (ClientStateCallback) {
3686 NewClientInfoRec clientinfo;
3687
3688 clientinfo.client = client;
3689 clientinfo.prefix = lconnSetupPrefix;
3690 clientinfo.setup = (xConnSetup *) lConnectionInfo;
3691 CallCallbacks((&ClientStateCallback), (void *) &clientinfo);
3692 }
3693 return Success;
3694 }
3695
3696 int
ProcEstablishConnection(ClientPtr client)3697 ProcEstablishConnection(ClientPtr client)
3698 {
3699 const char *reason;
3700 char *auth_proto, *auth_string;
3701 xConnClientPrefix *prefix;
3702
3703 REQUEST(xReq);
3704
3705 prefix = (xConnClientPrefix *) ((char *) stuff + sz_xReq);
3706 auth_proto = (char *) prefix + sz_xConnClientPrefix;
3707 auth_string = auth_proto + pad_to_int32(prefix->nbytesAuthProto);
3708
3709 if ((client->req_len << 2) != sz_xReq + sz_xConnClientPrefix +
3710 pad_to_int32(prefix->nbytesAuthProto) +
3711 pad_to_int32(prefix->nbytesAuthString))
3712 reason = "Bad length";
3713 else if ((prefix->majorVersion != X_PROTOCOL) ||
3714 (prefix->minorVersion != X_PROTOCOL_REVISION))
3715 reason = "Protocol version mismatch";
3716 else
3717 reason = ClientAuthorized(client,
3718 (unsigned short) prefix->nbytesAuthProto,
3719 auth_proto,
3720 (unsigned short) prefix->nbytesAuthString,
3721 auth_string);
3722
3723 return (SendConnSetup(client, reason));
3724 }
3725
3726 void
SendErrorToClient(ClientPtr client,unsigned majorCode,unsigned minorCode,XID resId,int errorCode)3727 SendErrorToClient(ClientPtr client, unsigned majorCode, unsigned minorCode,
3728 XID resId, int errorCode)
3729 {
3730 xError rep = {
3731 .type = X_Error,
3732 .errorCode = errorCode,
3733 .resourceID = resId,
3734 .minorCode = minorCode,
3735 .majorCode = majorCode
3736 };
3737
3738 WriteEventsToClient(client, 1, (xEvent *) &rep);
3739 }
3740
3741 void
MarkClientException(ClientPtr client)3742 MarkClientException(ClientPtr client)
3743 {
3744 client->noClientException = -1;
3745 }
3746
3747 /*
3748 * This array encodes the answer to the question "what is the log base 2
3749 * of the number of pixels that fit in a scanline pad unit?"
3750 * Note that ~0 is an invalid entry (mostly for the benefit of the reader).
3751 */
3752 static int answer[6][4] = {
3753 /* pad pad pad pad */
3754 /* 8 16 32 64 */
3755
3756 {3, 4, 5, 6}, /* 1 bit per pixel */
3757 {1, 2, 3, 4}, /* 4 bits per pixel */
3758 {0, 1, 2, 3}, /* 8 bits per pixel */
3759 {~0, 0, 1, 2}, /* 16 bits per pixel */
3760 {~0, ~0, 0, 1}, /* 24 bits per pixel */
3761 {~0, ~0, 0, 1} /* 32 bits per pixel */
3762 };
3763
3764 /*
3765 * This array gives the answer to the question "what is the first index for
3766 * the answer array above given the number of bits per pixel?"
3767 * Note that ~0 is an invalid entry (mostly for the benefit of the reader).
3768 */
3769 static int indexForBitsPerPixel[33] = {
3770 ~0, 0, ~0, ~0, /* 1 bit per pixel */
3771 1, ~0, ~0, ~0, /* 4 bits per pixel */
3772 2, ~0, ~0, ~0, /* 8 bits per pixel */
3773 ~0, ~0, ~0, ~0,
3774 3, ~0, ~0, ~0, /* 16 bits per pixel */
3775 ~0, ~0, ~0, ~0,
3776 4, ~0, ~0, ~0, /* 24 bits per pixel */
3777 ~0, ~0, ~0, ~0,
3778 5 /* 32 bits per pixel */
3779 };
3780
3781 /*
3782 * This array gives the bytesperPixel value for cases where the number
3783 * of bits per pixel is a multiple of 8 but not a power of 2.
3784 */
3785 static int answerBytesPerPixel[33] = {
3786 ~0, 0, ~0, ~0, /* 1 bit per pixel */
3787 0, ~0, ~0, ~0, /* 4 bits per pixel */
3788 0, ~0, ~0, ~0, /* 8 bits per pixel */
3789 ~0, ~0, ~0, ~0,
3790 0, ~0, ~0, ~0, /* 16 bits per pixel */
3791 ~0, ~0, ~0, ~0,
3792 3, ~0, ~0, ~0, /* 24 bits per pixel */
3793 ~0, ~0, ~0, ~0,
3794 0 /* 32 bits per pixel */
3795 };
3796
3797 /*
3798 * This array gives the answer to the question "what is the second index for
3799 * the answer array above given the number of bits per scanline pad unit?"
3800 * Note that ~0 is an invalid entry (mostly for the benefit of the reader).
3801 */
3802 static int indexForScanlinePad[65] = {
3803 ~0, ~0, ~0, ~0,
3804 ~0, ~0, ~0, ~0,
3805 0, ~0, ~0, ~0, /* 8 bits per scanline pad unit */
3806 ~0, ~0, ~0, ~0,
3807 1, ~0, ~0, ~0, /* 16 bits per scanline pad unit */
3808 ~0, ~0, ~0, ~0,
3809 ~0, ~0, ~0, ~0,
3810 ~0, ~0, ~0, ~0,
3811 2, ~0, ~0, ~0, /* 32 bits per scanline pad unit */
3812 ~0, ~0, ~0, ~0,
3813 ~0, ~0, ~0, ~0,
3814 ~0, ~0, ~0, ~0,
3815 ~0, ~0, ~0, ~0,
3816 ~0, ~0, ~0, ~0,
3817 ~0, ~0, ~0, ~0,
3818 ~0, ~0, ~0, ~0,
3819 3 /* 64 bits per scanline pad unit */
3820 };
3821
3822 /*
3823 grow the array of screenRecs if necessary.
3824 call the device-supplied initialization procedure
3825 with its screen number, a pointer to its ScreenRec, argc, and argv.
3826 return the number of successfully installed screens.
3827
3828 */
3829
init_screen(ScreenPtr pScreen,int i,Bool gpu)3830 static int init_screen(ScreenPtr pScreen, int i, Bool gpu)
3831 {
3832 int scanlinepad, format, depth, bitsPerPixel, j, k;
3833
3834 dixInitScreenSpecificPrivates(pScreen);
3835
3836 if (!dixAllocatePrivates(&pScreen->devPrivates, PRIVATE_SCREEN)) {
3837 return -1;
3838 }
3839 pScreen->myNum = i;
3840 if (gpu) {
3841 pScreen->myNum += GPU_SCREEN_OFFSET;
3842 pScreen->isGPU = TRUE;
3843 }
3844 pScreen->totalPixmapSize = 0; /* computed in CreateScratchPixmapForScreen */
3845 pScreen->ClipNotify = 0; /* for R4 ddx compatibility */
3846 pScreen->CreateScreenResources = 0;
3847
3848 xorg_list_init(&pScreen->pixmap_dirty_list);
3849 xorg_list_init(&pScreen->slave_list);
3850
3851 /*
3852 * This loop gets run once for every Screen that gets added,
3853 * but thats ok. If the ddx layer initializes the formats
3854 * one at a time calling AddScreen() after each, then each
3855 * iteration will make it a little more accurate. Worst case
3856 * we do this loop N * numPixmapFormats where N is # of screens.
3857 * Anyway, this must be called after InitOutput and before the
3858 * screen init routine is called.
3859 */
3860 for (format = 0; format < screenInfo.numPixmapFormats; format++) {
3861 depth = screenInfo.formats[format].depth;
3862 bitsPerPixel = screenInfo.formats[format].bitsPerPixel;
3863 scanlinepad = screenInfo.formats[format].scanlinePad;
3864 j = indexForBitsPerPixel[bitsPerPixel];
3865 k = indexForScanlinePad[scanlinepad];
3866 PixmapWidthPaddingInfo[depth].padPixelsLog2 = answer[j][k];
3867 PixmapWidthPaddingInfo[depth].padRoundUp =
3868 (scanlinepad / bitsPerPixel) - 1;
3869 j = indexForBitsPerPixel[8]; /* bits per byte */
3870 PixmapWidthPaddingInfo[depth].padBytesLog2 = answer[j][k];
3871 PixmapWidthPaddingInfo[depth].bitsPerPixel = bitsPerPixel;
3872 if (answerBytesPerPixel[bitsPerPixel]) {
3873 PixmapWidthPaddingInfo[depth].notPower2 = 1;
3874 PixmapWidthPaddingInfo[depth].bytesPerPixel =
3875 answerBytesPerPixel[bitsPerPixel];
3876 }
3877 else {
3878 PixmapWidthPaddingInfo[depth].notPower2 = 0;
3879 }
3880 }
3881 return 0;
3882 }
3883
3884 int
AddScreen(Bool (* pfnInit)(ScreenPtr,int,char **),int argc,char ** argv)3885 AddScreen(Bool (*pfnInit) (ScreenPtr /*pScreen */ ,
3886 int /*argc */ ,
3887 char ** /*argv */
3888 ), int argc, char **argv)
3889 {
3890
3891 int i;
3892 ScreenPtr pScreen;
3893 Bool ret;
3894
3895 i = screenInfo.numScreens;
3896 if (i == MAXSCREENS)
3897 return -1;
3898
3899 pScreen = (ScreenPtr) calloc(1, sizeof(ScreenRec));
3900 if (!pScreen)
3901 return -1;
3902
3903 ret = init_screen(pScreen, i, FALSE);
3904 if (ret != 0) {
3905 free(pScreen);
3906 return ret;
3907 }
3908 /* This is where screen specific stuff gets initialized. Load the
3909 screen structure, call the hardware, whatever.
3910 This is also where the default colormap should be allocated and
3911 also pixel values for blackPixel, whitePixel, and the cursor
3912 Note that InitScreen is NOT allowed to modify argc, argv, or
3913 any of the strings pointed to by argv. They may be passed to
3914 multiple screens.
3915 */
3916 screenInfo.screens[i] = pScreen;
3917 screenInfo.numScreens++;
3918 if (!(*pfnInit) (pScreen, argc, argv)) {
3919 dixFreeScreenSpecificPrivates(pScreen);
3920 dixFreePrivates(pScreen->devPrivates, PRIVATE_SCREEN);
3921 free(pScreen);
3922 screenInfo.numScreens--;
3923 return -1;
3924 }
3925
3926 update_desktop_dimensions();
3927
3928 dixRegisterScreenPrivateKey(&cursorScreenDevPriv, pScreen, PRIVATE_CURSOR,
3929 0);
3930
3931 return i;
3932 }
3933
3934 int
AddGPUScreen(Bool (* pfnInit)(ScreenPtr,int,char **),int argc,char ** argv)3935 AddGPUScreen(Bool (*pfnInit) (ScreenPtr /*pScreen */ ,
3936 int /*argc */ ,
3937 char ** /*argv */
3938 ),
3939 int argc, char **argv)
3940 {
3941 int i;
3942 ScreenPtr pScreen;
3943 Bool ret;
3944
3945 i = screenInfo.numGPUScreens;
3946 if (i == MAXGPUSCREENS)
3947 return -1;
3948
3949 pScreen = (ScreenPtr) calloc(1, sizeof(ScreenRec));
3950 if (!pScreen)
3951 return -1;
3952
3953 ret = init_screen(pScreen, i, TRUE);
3954 if (ret != 0) {
3955 free(pScreen);
3956 return ret;
3957 }
3958
3959 /* This is where screen specific stuff gets initialized. Load the
3960 screen structure, call the hardware, whatever.
3961 This is also where the default colormap should be allocated and
3962 also pixel values for blackPixel, whitePixel, and the cursor
3963 Note that InitScreen is NOT allowed to modify argc, argv, or
3964 any of the strings pointed to by argv. They may be passed to
3965 multiple screens.
3966 */
3967 screenInfo.gpuscreens[i] = pScreen;
3968 screenInfo.numGPUScreens++;
3969 if (!(*pfnInit) (pScreen, argc, argv)) {
3970 dixFreePrivates(pScreen->devPrivates, PRIVATE_SCREEN);
3971 free(pScreen);
3972 screenInfo.numGPUScreens--;
3973 return -1;
3974 }
3975
3976 update_desktop_dimensions();
3977
3978 /*
3979 * We cannot register the Screen PRIVATE_CURSOR key if cursors are already
3980 * created, because dix/privates.c does not have relocation code for
3981 * PRIVATE_CURSOR. Once this is fixed the if() can be removed and we can
3982 * register the Screen PRIVATE_CURSOR key unconditionally.
3983 */
3984 if (!dixPrivatesCreated(PRIVATE_CURSOR))
3985 dixRegisterScreenPrivateKey(&cursorScreenDevPriv, pScreen,
3986 PRIVATE_CURSOR, 0);
3987
3988 return i;
3989 }
3990
3991 void
RemoveGPUScreen(ScreenPtr pScreen)3992 RemoveGPUScreen(ScreenPtr pScreen)
3993 {
3994 int idx, j;
3995 if (!pScreen->isGPU)
3996 return;
3997
3998 idx = pScreen->myNum - GPU_SCREEN_OFFSET;
3999 for (j = idx; j < screenInfo.numGPUScreens - 1; j++) {
4000 screenInfo.gpuscreens[j] = screenInfo.gpuscreens[j + 1];
4001 screenInfo.gpuscreens[j]->myNum = j + GPU_SCREEN_OFFSET;
4002 }
4003 screenInfo.numGPUScreens--;
4004
4005 /* this gets freed later in the resource list, but without
4006 * the screen existing it causes crashes - so remove it here */
4007 if (pScreen->defColormap)
4008 FreeResource(pScreen->defColormap, RT_COLORMAP);
4009 free(pScreen);
4010
4011 }
4012
4013 void
AttachUnboundGPU(ScreenPtr pScreen,ScreenPtr new)4014 AttachUnboundGPU(ScreenPtr pScreen, ScreenPtr new)
4015 {
4016 assert(new->isGPU);
4017 assert(!new->current_master);
4018 xorg_list_add(&new->slave_head, &pScreen->slave_list);
4019 new->current_master = pScreen;
4020 }
4021
4022 void
DetachUnboundGPU(ScreenPtr slave)4023 DetachUnboundGPU(ScreenPtr slave)
4024 {
4025 assert(slave->isGPU);
4026 assert(!slave->is_output_slave);
4027 assert(!slave->is_offload_slave);
4028 xorg_list_del(&slave->slave_head);
4029 slave->current_master = NULL;
4030 }
4031
4032 void
AttachOutputGPU(ScreenPtr pScreen,ScreenPtr new)4033 AttachOutputGPU(ScreenPtr pScreen, ScreenPtr new)
4034 {
4035 assert(new->isGPU);
4036 assert(!new->is_output_slave);
4037 assert(new->current_master == pScreen);
4038 new->is_output_slave = TRUE;
4039 new->current_master->output_slaves++;
4040 }
4041
4042 void
DetachOutputGPU(ScreenPtr slave)4043 DetachOutputGPU(ScreenPtr slave)
4044 {
4045 assert(slave->isGPU);
4046 assert(slave->is_output_slave);
4047 slave->current_master->output_slaves--;
4048 slave->is_output_slave = FALSE;
4049 }
4050
4051 void
AttachOffloadGPU(ScreenPtr pScreen,ScreenPtr new)4052 AttachOffloadGPU(ScreenPtr pScreen, ScreenPtr new)
4053 {
4054 assert(new->isGPU);
4055 assert(!new->is_offload_slave);
4056 assert(new->current_master == pScreen);
4057 new->is_offload_slave = TRUE;
4058 }
4059
4060 void
DetachOffloadGPU(ScreenPtr slave)4061 DetachOffloadGPU(ScreenPtr slave)
4062 {
4063 assert(slave->isGPU);
4064 assert(slave->is_offload_slave);
4065 slave->is_offload_slave = FALSE;
4066 }
4067
4068