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