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