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