xserver

xserver with xephyr scale patch
git clone https://git.neptards.moe/u3shit/xserver.git
Log | Files | Refs | README | LICENSE

dispatch.c (121636B)


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