diff options
Diffstat (limited to 'xorg-server/dix/dispatch.c')
-rwxr-xr-x[-rw-r--r--] | xorg-server/dix/dispatch.c | 8034 |
1 files changed, 4038 insertions, 3996 deletions
diff --git a/xorg-server/dix/dispatch.c b/xorg-server/dix/dispatch.c index 74abecd67..36f9418ca 100644..100755 --- a/xorg-server/dix/dispatch.c +++ b/xorg-server/dix/dispatch.c @@ -1,3996 +1,4038 @@ -/************************************************************ - -Copyright 1987, 1989, 1998 The Open Group - -Permission to use, copy, modify, distribute, and sell this software and its -documentation for any purpose is hereby granted without fee, provided that -the above copyright notice appear in all copies and that both that -copyright notice and this permission notice appear in supporting -documentation. - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN -AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN -CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of The Open Group shall not be -used in advertising or otherwise to promote the sale, use or other dealings -in this Software without prior written authorization from The Open Group. - -Copyright 1987, 1989 by Digital Equipment Corporation, Maynard, Massachusetts. - - All Rights Reserved - -Permission to use, copy, modify, and distribute this software and its -documentation for any purpose and without fee is hereby granted, -provided that the above copyright notice appear in all copies and that -both that copyright notice and this permission notice appear in -supporting documentation, and that the name of Digital not be -used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. - -DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING -ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL -DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR -ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, -WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, -ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS -SOFTWARE. - -********************************************************/ - -/* The panoramix components contained the following notice */ -/***************************************************************** - -Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts. - -Permission is hereby granted, free of charge, to any person obtaining a copy -of this software and associated documentation files (the "Software"), to deal -in the Software without restriction, including without limitation the rights -to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -copies of the Software. - -The above copyright notice and this permission notice shall be included in -all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL -DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING, -BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY, -WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR -IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - -Except as contained in this notice, the name of Digital Equipment Corporation -shall not be used in advertising or otherwise to promote the sale, use or other -dealings in this Software without prior written authorization from Digital -Equipment Corporation. - -******************************************************************/ - -/* XSERVER_DTRACE additions: - * Copyright (c) 2005-2006, Oracle and/or its affiliates. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice (including the next - * paragraph) shall be included in all copies or substantial portions of the - * Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#ifdef HAVE_DIX_CONFIG_H -#include <dix-config.h> -#include <version-config.h> -#endif - -#ifdef PANORAMIX_DEBUG -#include <stdio.h> -int ProcInitialConnection(); -#endif - -#include "windowstr.h" -#include <X11/fonts/fontstruct.h> -#include "dixfontstr.h" -#include "gcstruct.h" -#include "selection.h" -#include "colormapst.h" -#include "cursorstr.h" -#include "scrnintstr.h" -#include "opaque.h" -#include "input.h" -#include "servermd.h" -#include "extnsionst.h" -#include "dixfont.h" -#include "dispatch.h" -#include "swaprep.h" -#include "swapreq.h" -#include "privates.h" -#include "xace.h" -#include "inputstr.h" -#include "xkbsrv.h" -#include "site.h" -#include "client.h" - -#ifdef XSERVER_DTRACE -#include "registry.h" -#include <sys/types.h> -typedef const char *string; - -#include "Xserver-dtrace.h" -#endif - -#define mskcnt ((MAXCLIENTS + 31) / 32) -#define BITMASK(i) (1U << ((i) & 31)) -#define MASKIDX(i) ((i) >> 5) -#define MASKWORD(buf, i) buf[MASKIDX(i)] -#define BITSET(buf, i) MASKWORD(buf, i) |= BITMASK(i) -#define BITCLEAR(buf, i) MASKWORD(buf, i) &= ~BITMASK(i) -#define GETBIT(buf, i) (MASKWORD(buf, i) & BITMASK(i)) - -xConnSetupPrefix connSetupPrefix; - -PaddingInfo PixmapWidthPaddingInfo[33]; - -static ClientPtr grabClient; - -#define GrabNone 0 -#define GrabActive 1 -#define GrabKickout 2 -static int grabState = GrabNone; -static long grabWaiters[mskcnt]; -CallbackListPtr ServerGrabCallback = NULL; -HWEventQueuePtr checkForInput[2]; -int connBlockScreenStart; - -static void KillAllClients(void); - -static int nextFreeClientID; /* always MIN free client ID */ - -static int nClients; /* number of authorized clients */ - -CallbackListPtr ClientStateCallback; - -/* dispatchException & isItTimeToYield must be declared volatile since they - * are modified by signal handlers - otherwise optimizer may assume it doesn't - * need to actually check value in memory when used and may miss changes from - * signal handlers. - */ -volatile char dispatchException = 0; -volatile char isItTimeToYield; - -#define SAME_SCREENS(a, b) (\ - (a.pScreen == b.pScreen)) - -void -SetInputCheck(HWEventQueuePtr c0, HWEventQueuePtr c1) -{ - checkForInput[0] = c0; - checkForInput[1] = c1; -} - -void -UpdateCurrentTime(void) -{ - TimeStamp systime; - - /* To avoid time running backwards, we must call GetTimeInMillis before - * calling ProcessInputEvents. - */ - systime.months = currentTime.months; - systime.milliseconds = GetTimeInMillis(); - if (systime.milliseconds < currentTime.milliseconds) - systime.months++; - if (*checkForInput[0] != *checkForInput[1]) - ProcessInputEvents(); - if (CompareTimeStamps(systime, currentTime) == LATER) - currentTime = systime; -} - -/* Like UpdateCurrentTime, but can't call ProcessInputEvents */ -void -UpdateCurrentTimeIf(void) -{ - TimeStamp systime; - - systime.months = currentTime.months; - systime.milliseconds = GetTimeInMillis(); - if (systime.milliseconds < currentTime.milliseconds) - systime.months++; - if (CompareTimeStamps(systime, currentTime) == LATER) - currentTime = systime; -} - -#undef SMART_DEBUG - -/* in milliseconds */ -#define SMART_SCHEDULE_DEFAULT_INTERVAL 5 -#define SMART_SCHEDULE_MAX_SLICE 15 - -#if defined(WIN32) && !defined(__CYGWIN__) -Bool SmartScheduleDisable = TRUE; -#else -Bool SmartScheduleDisable = FALSE; -#endif -long SmartScheduleSlice = SMART_SCHEDULE_DEFAULT_INTERVAL; -long SmartScheduleInterval = SMART_SCHEDULE_DEFAULT_INTERVAL; -long SmartScheduleMaxSlice = SMART_SCHEDULE_MAX_SLICE; -long SmartScheduleTime; -int SmartScheduleLatencyLimited = 0; -static ClientPtr SmartLastClient; -static int SmartLastIndex[SMART_MAX_PRIORITY - SMART_MIN_PRIORITY + 1]; - -#ifdef SMART_DEBUG -long SmartLastPrint; -#endif - -void Dispatch(void); - -static int -SmartScheduleClient(int *clientReady, int nready) -{ - ClientPtr pClient; - int i; - int client; - int bestPrio, best = 0; - int bestRobin, robin; - long now = SmartScheduleTime; - long idle; - - bestPrio = -0x7fffffff; - bestRobin = 0; - idle = 2 * SmartScheduleSlice; - for (i = 0; i < nready; i++) { - client = clientReady[i]; - pClient = clients[client]; - /* Praise clients which haven't run in a while */ - if ((now - pClient->smart_stop_tick) >= idle) { - if (pClient->smart_priority < 0) - pClient->smart_priority++; - } - - /* check priority to select best client */ - robin = - (pClient->index - - SmartLastIndex[pClient->smart_priority - - SMART_MIN_PRIORITY]) & 0xff; - if (pClient->smart_priority > bestPrio || - (pClient->smart_priority == bestPrio && robin > bestRobin)) { - bestPrio = pClient->smart_priority; - bestRobin = robin; - best = client; - } -#ifdef SMART_DEBUG - if ((now - SmartLastPrint) >= 5000) - fprintf(stderr, " %2d: %3d", client, pClient->smart_priority); -#endif - } -#ifdef SMART_DEBUG - if ((now - SmartLastPrint) >= 5000) { - fprintf(stderr, " use %2d\n", best); - SmartLastPrint = now; - } -#endif - pClient = clients[best]; - SmartLastIndex[bestPrio - SMART_MIN_PRIORITY] = pClient->index; - /* - * Set current client pointer - */ - if (SmartLastClient != pClient) { - pClient->smart_start_tick = now; - SmartLastClient = pClient; - } - /* - * Adjust slice - */ - if (nready == 1 && SmartScheduleLatencyLimited == 0) { - /* - * If it's been a long time since another client - * has run, bump the slice up to get maximal - * performance from a single client - */ - if ((now - pClient->smart_start_tick) > 1000 && - SmartScheduleSlice < SmartScheduleMaxSlice) { - SmartScheduleSlice += SmartScheduleInterval; - } - } - else { - SmartScheduleSlice = SmartScheduleInterval; - } - return best; -} - -void -EnableLimitedSchedulingLatency(void) -{ - ++SmartScheduleLatencyLimited; - SmartScheduleSlice = SmartScheduleInterval; -} - -void -DisableLimitedSchedulingLatency(void) -{ - --SmartScheduleLatencyLimited; - - /* protect against bugs */ - if (SmartScheduleLatencyLimited < 0) - SmartScheduleLatencyLimited = 0; -} - -void -Dispatch(void) -{ - int *clientReady; /* array of request ready clients */ - int result; - ClientPtr client; - int nready; - HWEventQueuePtr *icheck = checkForInput; - long start_tick; - - nextFreeClientID = 1; - nClients = 0; - - clientReady = malloc(sizeof(int) * MaxClients); - if (!clientReady) - return; - - SmartScheduleSlice = SmartScheduleInterval; - while (!dispatchException) { - if (*icheck[0] != *icheck[1]) { - ProcessInputEvents(); - FlushIfCriticalOutputPending(); - } - - nready = WaitForSomething(clientReady); - - if (nready && !SmartScheduleDisable) { - clientReady[0] = SmartScheduleClient(clientReady, nready); - nready = 1; - } - /***************** - * Handle events in round robin fashion, doing input between - * each round - *****************/ - - while (!dispatchException && (--nready >= 0)) { - client = clients[clientReady[nready]]; - if (!client) { - /* KillClient can cause this to happen */ - continue; - } - /* GrabServer activation can cause this to be true */ - if (grabState == GrabKickout) { - grabState = GrabActive; - break; - } - isItTimeToYield = FALSE; - - start_tick = SmartScheduleTime; - while (!isItTimeToYield) { - if (*icheck[0] != *icheck[1]) - ProcessInputEvents(); - - FlushIfCriticalOutputPending(); - if (!SmartScheduleDisable && - (SmartScheduleTime - start_tick) >= SmartScheduleSlice) { - /* Penalize clients which consume ticks */ - if (client->smart_priority > SMART_MIN_PRIORITY) - client->smart_priority--; - break; - } - /* now, finally, deal with client requests */ - - /* Update currentTime so request time checks, such as for input - * device grabs, are calculated correctly */ - UpdateCurrentTimeIf(); - result = ReadRequestFromClient(client); - if (result <= 0) { - if (result < 0) - CloseDownClient(client); - break; - } - - client->sequence++; - client->majorOp = ((xReq *) client->requestBuffer)->reqType; - client->minorOp = 0; - if (client->majorOp >= EXTENSION_BASE) { - ExtensionEntry *ext = GetExtensionEntry(client->majorOp); - - if (ext) - client->minorOp = ext->MinorOpcode(client); - } -#ifdef XSERVER_DTRACE - if (XSERVER_REQUEST_START_ENABLED()) - XSERVER_REQUEST_START(LookupMajorName(client->majorOp), - client->majorOp, - ((xReq *) client->requestBuffer)->length, - client->index, - client->requestBuffer); -#endif - if (result > (maxBigRequestSize << 2)) - result = BadLength; - else { - result = XaceHookDispatch(client, client->majorOp); - if (result == Success) - result = - (*client->requestVector[client->majorOp]) (client); - XaceHookAuditEnd(client, result); - } -#ifdef XSERVER_DTRACE - if (XSERVER_REQUEST_DONE_ENABLED()) - XSERVER_REQUEST_DONE(LookupMajorName(client->majorOp), - client->majorOp, client->sequence, - client->index, result); -#endif - - if (client->noClientException != Success) { - CloseDownClient(client); - break; - } - else if (result != Success) { - SendErrorToClient(client, client->majorOp, - client->minorOp, - client->errorValue, result); - break; - } - } - FlushAllOutput(); - client = clients[clientReady[nready]]; - if (client) - client->smart_stop_tick = SmartScheduleTime; - } - dispatchException &= ~DE_PRIORITYCHANGE; - } -#if defined(DDXBEFORERESET) - ddxBeforeReset(); -#endif - KillAllClients(); - free(clientReady); - dispatchException &= ~DE_RESET; - SmartScheduleLatencyLimited = 0; - ResetOsBuffers(); -} - -static int VendorRelease = VENDOR_RELEASE; -static const char *VendorString = VENDOR_NAME; - -void -SetVendorRelease(int release) -{ - VendorRelease = release; -} - -void -SetVendorString(const char *vendor) -{ - VendorString = vendor; -} - -Bool -CreateConnectionBlock(void) -{ - xConnSetup setup; - xWindowRoot root; - xDepth depth; - xVisualType visual; - xPixmapFormat format; - unsigned long vid; - int i, j, k, lenofblock, sizesofar = 0; - char *pBuf; - - memset(&setup, 0, sizeof(xConnSetup)); - /* Leave off the ridBase and ridMask, these must be sent with - connection */ - - setup.release = VendorRelease; - /* - * per-server image and bitmap parameters are defined in Xmd.h - */ - setup.imageByteOrder = screenInfo.imageByteOrder; - - setup.bitmapScanlineUnit = screenInfo.bitmapScanlineUnit; - setup.bitmapScanlinePad = screenInfo.bitmapScanlinePad; - - setup.bitmapBitOrder = screenInfo.bitmapBitOrder; - setup.motionBufferSize = NumMotionEvents(); - setup.numRoots = screenInfo.numScreens; - setup.nbytesVendor = strlen(VendorString); - setup.numFormats = screenInfo.numPixmapFormats; - setup.maxRequestSize = MAX_REQUEST_SIZE; - QueryMinMaxKeyCodes(&setup.minKeyCode, &setup.maxKeyCode); - - lenofblock = sizeof(xConnSetup) + - pad_to_int32(setup.nbytesVendor) + - (setup.numFormats * sizeof(xPixmapFormat)) + - (setup.numRoots * sizeof(xWindowRoot)); - ConnectionInfo = malloc(lenofblock); - if (!ConnectionInfo) - return FALSE; - - memmove(ConnectionInfo, (char *) &setup, sizeof(xConnSetup)); - sizesofar = sizeof(xConnSetup); - pBuf = ConnectionInfo + sizeof(xConnSetup); - - memmove(pBuf, VendorString, (int) setup.nbytesVendor); - sizesofar += setup.nbytesVendor; - pBuf += setup.nbytesVendor; - i = padding_for_int32(setup.nbytesVendor); - sizesofar += i; - while (--i >= 0) - *pBuf++ = 0; - - memset(&format, 0, sizeof(xPixmapFormat)); - for (i = 0; i < screenInfo.numPixmapFormats; i++) { - format.depth = screenInfo.formats[i].depth; - format.bitsPerPixel = screenInfo.formats[i].bitsPerPixel; - format.scanLinePad = screenInfo.formats[i].scanlinePad; - memmove(pBuf, (char *) &format, sizeof(xPixmapFormat)); - pBuf += sizeof(xPixmapFormat); - sizesofar += sizeof(xPixmapFormat); - } - - connBlockScreenStart = sizesofar; - memset(&depth, 0, sizeof(xDepth)); - memset(&visual, 0, sizeof(xVisualType)); - for (i = 0; i < screenInfo.numScreens; i++) { - ScreenPtr pScreen; - DepthPtr pDepth; - VisualPtr pVisual; - - pScreen = screenInfo.screens[i]; - root.windowId = pScreen->root->drawable.id; - root.defaultColormap = pScreen->defColormap; - root.whitePixel = pScreen->whitePixel; - root.blackPixel = pScreen->blackPixel; - root.currentInputMask = 0; /* filled in when sent */ - root.pixWidth = pScreen->width; - root.pixHeight = pScreen->height; - root.mmWidth = pScreen->mmWidth; - root.mmHeight = pScreen->mmHeight; - root.minInstalledMaps = pScreen->minInstalledCmaps; - root.maxInstalledMaps = pScreen->maxInstalledCmaps; - root.rootVisualID = pScreen->rootVisual; - root.backingStore = pScreen->backingStoreSupport; - root.saveUnders = FALSE; - root.rootDepth = pScreen->rootDepth; - root.nDepths = pScreen->numDepths; - memmove(pBuf, (char *) &root, sizeof(xWindowRoot)); - sizesofar += sizeof(xWindowRoot); - pBuf += sizeof(xWindowRoot); - - pDepth = pScreen->allowedDepths; - for (j = 0; j < pScreen->numDepths; j++, pDepth++) { - lenofblock += sizeof(xDepth) + - (pDepth->numVids * sizeof(xVisualType)); - pBuf = (char *) realloc(ConnectionInfo, lenofblock); - if (!pBuf) { - free(ConnectionInfo); - return FALSE; - } - ConnectionInfo = pBuf; - pBuf += sizesofar; - depth.depth = pDepth->depth; - depth.nVisuals = pDepth->numVids; - memmove(pBuf, (char *) &depth, sizeof(xDepth)); - pBuf += sizeof(xDepth); - sizesofar += sizeof(xDepth); - for (k = 0; k < pDepth->numVids; k++) { - vid = pDepth->vids[k]; - for (pVisual = pScreen->visuals; - pVisual->vid != vid; pVisual++); - visual.visualID = vid; - visual.class = pVisual->class; - visual.bitsPerRGB = pVisual->bitsPerRGBValue; - visual.colormapEntries = pVisual->ColormapEntries; - visual.redMask = pVisual->redMask; - visual.greenMask = pVisual->greenMask; - visual.blueMask = pVisual->blueMask; - memmove(pBuf, (char *) &visual, sizeof(xVisualType)); - pBuf += sizeof(xVisualType); - sizesofar += sizeof(xVisualType); - } - } - } - connSetupPrefix.success = xTrue; - connSetupPrefix.length = lenofblock / 4; - connSetupPrefix.majorVersion = X_PROTOCOL; - connSetupPrefix.minorVersion = X_PROTOCOL_REVISION; - return TRUE; -} - -int -ProcBadRequest(ClientPtr client) -{ - return BadRequest; -} - -int -ProcCreateWindow(ClientPtr client) -{ - WindowPtr pParent, pWin; - - REQUEST(xCreateWindowReq); - int len, rc; - - REQUEST_AT_LEAST_SIZE(xCreateWindowReq); - - LEGAL_NEW_RESOURCE(stuff->wid, client); - rc = dixLookupWindow(&pParent, stuff->parent, client, DixAddAccess); - if (rc != Success) - return rc; - len = client->req_len - bytes_to_int32(sizeof(xCreateWindowReq)); - if (Ones(stuff->mask) != len) - return BadLength; - if (!stuff->width || !stuff->height) { - client->errorValue = 0; - return BadValue; - } - pWin = CreateWindow(stuff->wid, pParent, stuff->x, - stuff->y, stuff->width, stuff->height, - stuff->borderWidth, stuff->class, - stuff->mask, (XID *) &stuff[1], - (int) stuff->depth, client, stuff->visual, &rc); - if (pWin) { - Mask mask = pWin->eventMask; - - pWin->eventMask = 0; /* subterfuge in case AddResource fails */ - if (!AddResource(stuff->wid, RT_WINDOW, (void *) pWin)) - return BadAlloc; - pWin->eventMask = mask; - } - return rc; -} - -int -ProcChangeWindowAttributes(ClientPtr client) -{ - WindowPtr pWin; - - REQUEST(xChangeWindowAttributesReq); - int len, rc; - Mask access_mode = 0; - - REQUEST_AT_LEAST_SIZE(xChangeWindowAttributesReq); - access_mode |= (stuff->valueMask & CWEventMask) ? DixReceiveAccess : 0; - access_mode |= (stuff->valueMask & ~CWEventMask) ? DixSetAttrAccess : 0; - rc = dixLookupWindow(&pWin, stuff->window, client, access_mode); - if (rc != Success) - return rc; - len = client->req_len - bytes_to_int32(sizeof(xChangeWindowAttributesReq)); - if (len != Ones(stuff->valueMask)) - return BadLength; - return ChangeWindowAttributes(pWin, - stuff->valueMask, (XID *) &stuff[1], client); -} - -int -ProcGetWindowAttributes(ClientPtr client) -{ - WindowPtr pWin; - - REQUEST(xResourceReq); - xGetWindowAttributesReply wa; - int rc; - - REQUEST_SIZE_MATCH(xResourceReq); - rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess); - if (rc != Success) - return rc; - memset(&wa, 0, sizeof(xGetWindowAttributesReply)); - GetWindowAttributes(pWin, client, &wa); - WriteReplyToClient(client, sizeof(xGetWindowAttributesReply), &wa); - return Success; -} - -int -ProcDestroyWindow(ClientPtr client) -{ - WindowPtr pWin; - - REQUEST(xResourceReq); - int rc; - - REQUEST_SIZE_MATCH(xResourceReq); - rc = dixLookupWindow(&pWin, stuff->id, client, DixDestroyAccess); - if (rc != Success) - return rc; - if (pWin->parent) { - rc = dixLookupWindow(&pWin, pWin->parent->drawable.id, client, - DixRemoveAccess); - if (rc != Success) - return rc; - FreeResource(stuff->id, RT_NONE); - } - return Success; -} - -int -ProcDestroySubwindows(ClientPtr client) -{ - WindowPtr pWin; - - REQUEST(xResourceReq); - int rc; - - REQUEST_SIZE_MATCH(xResourceReq); - rc = dixLookupWindow(&pWin, stuff->id, client, DixRemoveAccess); - if (rc != Success) - return rc; - DestroySubwindows(pWin, client); - return Success; -} - -int -ProcChangeSaveSet(ClientPtr client) -{ - WindowPtr pWin; - - REQUEST(xChangeSaveSetReq); - int rc; - - REQUEST_SIZE_MATCH(xChangeSaveSetReq); - rc = dixLookupWindow(&pWin, stuff->window, client, DixManageAccess); - if (rc != Success) - return rc; - if (client->clientAsMask == (CLIENT_BITS(pWin->drawable.id))) - return BadMatch; - if ((stuff->mode == SetModeInsert) || (stuff->mode == SetModeDelete)) - return AlterSaveSetForClient(client, pWin, stuff->mode, FALSE, TRUE); - client->errorValue = stuff->mode; - return BadValue; -} - -int -ProcReparentWindow(ClientPtr client) -{ - WindowPtr pWin, pParent; - - REQUEST(xReparentWindowReq); - int rc; - - REQUEST_SIZE_MATCH(xReparentWindowReq); - rc = dixLookupWindow(&pWin, stuff->window, client, DixManageAccess); - if (rc != Success) - return rc; - rc = dixLookupWindow(&pParent, stuff->parent, client, DixAddAccess); - if (rc != Success) - return rc; - if (!SAME_SCREENS(pWin->drawable, pParent->drawable)) - return BadMatch; - if ((pWin->backgroundState == ParentRelative) && - (pParent->drawable.depth != pWin->drawable.depth)) - return BadMatch; - if ((pWin->drawable.class != InputOnly) && - (pParent->drawable.class == InputOnly)) - return BadMatch; - return ReparentWindow(pWin, pParent, - (short) stuff->x, (short) stuff->y, client); -} - -int -ProcMapWindow(ClientPtr client) -{ - WindowPtr pWin; - - REQUEST(xResourceReq); - int rc; - - REQUEST_SIZE_MATCH(xResourceReq); - rc = dixLookupWindow(&pWin, stuff->id, client, DixShowAccess); - if (rc != Success) - return rc; - MapWindow(pWin, client); - /* update cache to say it is mapped */ - return Success; -} - -int -ProcMapSubwindows(ClientPtr client) -{ - WindowPtr pWin; - - REQUEST(xResourceReq); - int rc; - - REQUEST_SIZE_MATCH(xResourceReq); - rc = dixLookupWindow(&pWin, stuff->id, client, DixListAccess); - if (rc != Success) - return rc; - MapSubwindows(pWin, client); - /* update cache to say it is mapped */ - return Success; -} - -int -ProcUnmapWindow(ClientPtr client) -{ - WindowPtr pWin; - - REQUEST(xResourceReq); - int rc; - - REQUEST_SIZE_MATCH(xResourceReq); - rc = dixLookupWindow(&pWin, stuff->id, client, DixHideAccess); - if (rc != Success) - return rc; - UnmapWindow(pWin, FALSE); - /* update cache to say it is mapped */ - return Success; -} - -int -ProcUnmapSubwindows(ClientPtr client) -{ - WindowPtr pWin; - - REQUEST(xResourceReq); - int rc; - - REQUEST_SIZE_MATCH(xResourceReq); - rc = dixLookupWindow(&pWin, stuff->id, client, DixListAccess); - if (rc != Success) - return rc; - UnmapSubwindows(pWin); - return Success; -} - -int -ProcConfigureWindow(ClientPtr client) -{ - WindowPtr pWin; - - REQUEST(xConfigureWindowReq); - int len, rc; - - REQUEST_AT_LEAST_SIZE(xConfigureWindowReq); - rc = dixLookupWindow(&pWin, stuff->window, client, - DixManageAccess | DixSetAttrAccess); - if (rc != Success) - return rc; - len = client->req_len - bytes_to_int32(sizeof(xConfigureWindowReq)); - if (Ones((Mask) stuff->mask) != len) - return BadLength; - return ConfigureWindow(pWin, (Mask) stuff->mask, (XID *) &stuff[1], client); -} - -int -ProcCirculateWindow(ClientPtr client) -{ - WindowPtr pWin; - - REQUEST(xCirculateWindowReq); - int rc; - - REQUEST_SIZE_MATCH(xCirculateWindowReq); - if ((stuff->direction != RaiseLowest) && (stuff->direction != LowerHighest)) { - client->errorValue = stuff->direction; - return BadValue; - } - rc = dixLookupWindow(&pWin, stuff->window, client, DixManageAccess); - if (rc != Success) - return rc; - CirculateWindow(pWin, (int) stuff->direction, client); - return Success; -} - -static int -GetGeometry(ClientPtr client, xGetGeometryReply * rep) -{ - DrawablePtr pDraw; - int rc; - - REQUEST(xResourceReq); - REQUEST_SIZE_MATCH(xResourceReq); - - rc = dixLookupDrawable(&pDraw, stuff->id, client, M_ANY, DixGetAttrAccess); - if (rc != Success) - return rc; - - rep->type = X_Reply; - rep->length = 0; - rep->sequenceNumber = client->sequence; - rep->root = pDraw->pScreen->root->drawable.id; - rep->depth = pDraw->depth; - rep->width = pDraw->width; - rep->height = pDraw->height; - - if (WindowDrawable(pDraw->type)) { - WindowPtr pWin = (WindowPtr) pDraw; - - rep->x = pWin->origin.x - wBorderWidth(pWin); - rep->y = pWin->origin.y - wBorderWidth(pWin); - rep->borderWidth = pWin->borderWidth; - } - else { /* DRAWABLE_PIXMAP */ - - rep->x = rep->y = rep->borderWidth = 0; - } - - return Success; -} - -int -ProcGetGeometry(ClientPtr client) -{ - xGetGeometryReply rep = { .type = X_Reply }; - int status; - - if ((status = GetGeometry(client, &rep)) != Success) - return status; - - WriteReplyToClient(client, sizeof(xGetGeometryReply), &rep); - return Success; -} - -int -ProcQueryTree(ClientPtr client) -{ - xQueryTreeReply reply; - int rc, numChildren = 0; - WindowPtr pChild, pWin, pHead; - Window *childIDs = (Window *) NULL; - - REQUEST(xResourceReq); - - REQUEST_SIZE_MATCH(xResourceReq); - rc = dixLookupWindow(&pWin, stuff->id, client, DixListAccess); - if (rc != Success) - return rc; - - reply = (xQueryTreeReply) { - .type = X_Reply, - .sequenceNumber = client->sequence, - .root = pWin->drawable.pScreen->root->drawable.id, - .parent = (pWin->parent) ? pWin->parent->drawable.id : (Window) None - }; - pHead = RealChildHead(pWin); - for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib) - numChildren++; - if (numChildren) { - int curChild = 0; - - childIDs = malloc(numChildren * sizeof(Window)); - if (!childIDs) - return BadAlloc; - for (pChild = pWin->lastChild; pChild != pHead; - pChild = pChild->prevSib) - childIDs[curChild++] = pChild->drawable.id; - } - - reply.nChildren = numChildren; - reply.length = bytes_to_int32(numChildren * sizeof(Window)); - - WriteReplyToClient(client, sizeof(xQueryTreeReply), &reply); - if (numChildren) { - client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; - WriteSwappedDataToClient(client, numChildren * sizeof(Window), - childIDs); - free(childIDs); - } - - return Success; -} - -int -ProcInternAtom(ClientPtr client) -{ - Atom atom; - char *tchar; - - REQUEST(xInternAtomReq); - - REQUEST_FIXED_SIZE(xInternAtomReq, stuff->nbytes); - if ((stuff->onlyIfExists != xTrue) && (stuff->onlyIfExists != xFalse)) { - client->errorValue = stuff->onlyIfExists; - return BadValue; - } - tchar = (char *) &stuff[1]; - atom = MakeAtom(tchar, stuff->nbytes, !stuff->onlyIfExists); - if (atom != BAD_RESOURCE) { - xInternAtomReply reply = { - .type = X_Reply, - .sequenceNumber = client->sequence, - .length = 0, - .atom = atom - }; - WriteReplyToClient(client, sizeof(xInternAtomReply), &reply); - return Success; - } - else - return BadAlloc; -} - -int -ProcGetAtomName(ClientPtr client) -{ - const char *str; - - REQUEST(xResourceReq); - - REQUEST_SIZE_MATCH(xResourceReq); - if ((str = NameForAtom(stuff->id))) { - int len = strlen(str); - xGetAtomNameReply reply = { - .type = X_Reply, - .sequenceNumber = client->sequence, - .length = bytes_to_int32(len), - .nameLength = len - }; - - WriteReplyToClient(client, sizeof(xGetAtomNameReply), &reply); - WriteToClient(client, len, str); - return Success; - } - else { - client->errorValue = stuff->id; - return BadAtom; - } -} - -int -ProcGrabServer(ClientPtr client) -{ - int rc; - - REQUEST_SIZE_MATCH(xReq); - if (grabState != GrabNone && client != grabClient) { - ResetCurrentRequest(client); - client->sequence--; - BITSET(grabWaiters, client->index); - IgnoreClient(client); - return Success; - } - rc = OnlyListenToOneClient(client); - if (rc != Success) - return rc; - grabState = GrabKickout; - grabClient = client; - - if (ServerGrabCallback) { - ServerGrabInfoRec grabinfo; - - grabinfo.client = client; - grabinfo.grabstate = SERVER_GRABBED; - CallCallbacks(&ServerGrabCallback, (void *) &grabinfo); - } - - return Success; -} - -static void -UngrabServer(ClientPtr client) -{ - int i; - - grabState = GrabNone; - ListenToAllClients(); - for (i = mskcnt; --i >= 0 && !grabWaiters[i];); - if (i >= 0) { - i <<= 5; - while (!GETBIT(grabWaiters, i)) - i++; - BITCLEAR(grabWaiters, i); - AttendClient(clients[i]); - } - - if (ServerGrabCallback) { - ServerGrabInfoRec grabinfo; - - grabinfo.client = client; - grabinfo.grabstate = SERVER_UNGRABBED; - CallCallbacks(&ServerGrabCallback, (void *) &grabinfo); - } -} - -int -ProcUngrabServer(ClientPtr client) -{ - REQUEST_SIZE_MATCH(xReq); - UngrabServer(client); - return Success; -} - -int -ProcTranslateCoords(ClientPtr client) -{ - REQUEST(xTranslateCoordsReq); - - WindowPtr pWin, pDst; - xTranslateCoordsReply rep; - int rc; - - REQUEST_SIZE_MATCH(xTranslateCoordsReq); - rc = dixLookupWindow(&pWin, stuff->srcWid, client, DixGetAttrAccess); - if (rc != Success) - return rc; - rc = dixLookupWindow(&pDst, stuff->dstWid, client, DixGetAttrAccess); - if (rc != Success) - return rc; - - rep = (xTranslateCoordsReply) { - .type = X_Reply, - .sequenceNumber = client->sequence, - .length = 0 - }; - if (!SAME_SCREENS(pWin->drawable, pDst->drawable)) { - rep.sameScreen = xFalse; - rep.child = None; - rep.dstX = rep.dstY = 0; - } - else { - INT16 x, y; - - rep.sameScreen = xTrue; - rep.child = None; - /* computing absolute coordinates -- adjust to destination later */ - x = pWin->drawable.x + stuff->srcX; - y = pWin->drawable.y + stuff->srcY; - pWin = pDst->firstChild; - while (pWin) { - BoxRec box; - - if ((pWin->mapped) && - (x >= pWin->drawable.x - wBorderWidth(pWin)) && - (x < pWin->drawable.x + (int) pWin->drawable.width + - wBorderWidth(pWin)) && - (y >= pWin->drawable.y - wBorderWidth(pWin)) && - (y < pWin->drawable.y + (int) pWin->drawable.height + - wBorderWidth(pWin)) - /* When a window is shaped, a further check - * is made to see if the point is inside - * borderSize - */ - && (!wBoundingShape(pWin) || - RegionContainsPoint(&pWin->borderSize, x, y, &box)) - - && (!wInputShape(pWin) || - RegionContainsPoint(wInputShape(pWin), - x - pWin->drawable.x, - y - pWin->drawable.y, &box)) - ) { - rep.child = pWin->drawable.id; - pWin = (WindowPtr) NULL; - } - else - pWin = pWin->nextSib; - } - /* adjust to destination coordinates */ - rep.dstX = x - pDst->drawable.x; - rep.dstY = y - pDst->drawable.y; - } - WriteReplyToClient(client, sizeof(xTranslateCoordsReply), &rep); - return Success; -} - -int -ProcOpenFont(ClientPtr client) -{ - int err; - - REQUEST(xOpenFontReq); - - REQUEST_FIXED_SIZE(xOpenFontReq, stuff->nbytes); - client->errorValue = stuff->fid; - LEGAL_NEW_RESOURCE(stuff->fid, client); - err = OpenFont(client, stuff->fid, (Mask) 0, - stuff->nbytes, (char *) &stuff[1]); - if (err == Success) { - return Success; - } - else - return err; -} - -int -ProcCloseFont(ClientPtr client) -{ - FontPtr pFont; - int rc; - - REQUEST(xResourceReq); - - REQUEST_SIZE_MATCH(xResourceReq); - rc = dixLookupResourceByType((void **) &pFont, stuff->id, RT_FONT, - client, DixDestroyAccess); - if (rc == Success) { - FreeResource(stuff->id, RT_NONE); - return Success; - } - else { - client->errorValue = stuff->id; - return rc; - } -} - -int -ProcQueryFont(ClientPtr client) -{ - xQueryFontReply *reply; - FontPtr pFont; - int rc; - - REQUEST(xResourceReq); - REQUEST_SIZE_MATCH(xResourceReq); - - rc = dixLookupFontable(&pFont, stuff->id, client, DixGetAttrAccess); - if (rc != Success) - return rc; - - { - xCharInfo *pmax = FONTINKMAX(pFont); - xCharInfo *pmin = FONTINKMIN(pFont); - int nprotoxcistructs; - int rlength; - - nprotoxcistructs = (pmax->rightSideBearing == pmin->rightSideBearing && - pmax->leftSideBearing == pmin->leftSideBearing && - pmax->descent == pmin->descent && - pmax->ascent == pmin->ascent && - pmax->characterWidth == pmin->characterWidth) ? - 0 : N2dChars(pFont); - - rlength = sizeof(xQueryFontReply) + - FONTINFONPROPS(FONTCHARSET(pFont)) * sizeof(xFontProp) + - nprotoxcistructs * sizeof(xCharInfo); - reply = calloc(1, rlength); - if (!reply) { - return BadAlloc; - } - - reply->type = X_Reply; - reply->length = bytes_to_int32(rlength - sizeof(xGenericReply)); - reply->sequenceNumber = client->sequence; - QueryFont(pFont, reply, nprotoxcistructs); - - WriteReplyToClient(client, rlength, reply); - free(reply); - return Success; - } -} - -int -ProcQueryTextExtents(ClientPtr client) -{ - xQueryTextExtentsReply reply; - FontPtr pFont; - ExtentInfoRec info; - unsigned long length; - int rc; - - REQUEST(xQueryTextExtentsReq); - REQUEST_AT_LEAST_SIZE(xQueryTextExtentsReq); - - rc = dixLookupFontable(&pFont, stuff->fid, client, DixGetAttrAccess); - if (rc != Success) - return rc; - - length = client->req_len - bytes_to_int32(sizeof(xQueryTextExtentsReq)); - length = length << 1; - if (stuff->oddLength) { - if (length == 0) - return BadLength; - length--; - } - if (!QueryTextExtents(pFont, length, (unsigned char *) &stuff[1], &info)) - return BadAlloc; - reply = (xQueryTextExtentsReply) { - .type = X_Reply, - .drawDirection = info.drawDirection, - .sequenceNumber = client->sequence, - .length = 0, - .fontAscent = info.fontAscent, - .fontDescent = info.fontDescent, - .overallAscent = info.overallAscent, - .overallDescent = info.overallDescent, - .overallWidth = info.overallWidth, - .overallLeft = info.overallLeft, - .overallRight = info.overallRight - }; - WriteReplyToClient(client, sizeof(xQueryTextExtentsReply), &reply); - return Success; -} - -int -ProcListFonts(ClientPtr client) -{ - REQUEST(xListFontsReq); - - REQUEST_FIXED_SIZE(xListFontsReq, stuff->nbytes); - - return ListFonts(client, (unsigned char *) &stuff[1], stuff->nbytes, - stuff->maxNames); -} - -int -ProcListFontsWithInfo(ClientPtr client) -{ - REQUEST(xListFontsWithInfoReq); - - REQUEST_FIXED_SIZE(xListFontsWithInfoReq, stuff->nbytes); - - return StartListFontsWithInfo(client, stuff->nbytes, - (unsigned char *) &stuff[1], stuff->maxNames); -} - -/** - * - * \param value must conform to DeleteType - */ -int -dixDestroyPixmap(void *value, XID pid) -{ - PixmapPtr pPixmap = (PixmapPtr) value; - - return (*pPixmap->drawable.pScreen->DestroyPixmap) (pPixmap); -} - -int -ProcCreatePixmap(ClientPtr client) -{ - PixmapPtr pMap; - DrawablePtr pDraw; - - REQUEST(xCreatePixmapReq); - DepthPtr pDepth; - int i, rc; - - REQUEST_SIZE_MATCH(xCreatePixmapReq); - client->errorValue = stuff->pid; - LEGAL_NEW_RESOURCE(stuff->pid, client); - - rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY, - DixGetAttrAccess); - if (rc != Success) - return rc; - - if (!stuff->width || !stuff->height) { - client->errorValue = 0; - return BadValue; - } - if (stuff->width > 32767 || stuff->height > 32767) { - /* It is allowed to try and allocate a pixmap which is larger than - * 32767 in either dimension. However, all of the framebuffer code - * is buggy and does not reliably draw to such big pixmaps, basically - * because the Region data structure operates with signed shorts - * for the rectangles in it. - * - * Furthermore, several places in the X server computes the - * size in bytes of the pixmap and tries to store it in an - * integer. This integer can overflow and cause the allocated size - * to be much smaller. - * - * So, such big pixmaps are rejected here with a BadAlloc - */ - return BadAlloc; - } - if (stuff->depth != 1) { - pDepth = pDraw->pScreen->allowedDepths; - for (i = 0; i < pDraw->pScreen->numDepths; i++, pDepth++) - if (pDepth->depth == stuff->depth) - goto CreatePmap; - client->errorValue = stuff->depth; - return BadValue; - } - CreatePmap: - pMap = (PixmapPtr) (*pDraw->pScreen->CreatePixmap) - (pDraw->pScreen, stuff->width, stuff->height, stuff->depth, 0); - if (pMap) { - pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER; - pMap->drawable.id = stuff->pid; - /* security creation/labeling check */ - rc = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pid, RT_PIXMAP, - pMap, RT_NONE, NULL, DixCreateAccess); - if (rc != Success) { - (*pDraw->pScreen->DestroyPixmap) (pMap); - return rc; - } - if (AddResource(stuff->pid, RT_PIXMAP, (void *) pMap)) - return Success; - } - return BadAlloc; -} - -int -ProcFreePixmap(ClientPtr client) -{ - PixmapPtr pMap; - int rc; - - REQUEST(xResourceReq); - REQUEST_SIZE_MATCH(xResourceReq); - - rc = dixLookupResourceByType((void **) &pMap, stuff->id, RT_PIXMAP, - client, DixDestroyAccess); - if (rc == Success) { - FreeResource(stuff->id, RT_NONE); - return Success; - } - else { - client->errorValue = stuff->id; - return rc; - } -} - -int -ProcCreateGC(ClientPtr client) -{ - int error, rc; - GC *pGC; - DrawablePtr pDraw; - unsigned len; - - REQUEST(xCreateGCReq); - - REQUEST_AT_LEAST_SIZE(xCreateGCReq); - client->errorValue = stuff->gc; - LEGAL_NEW_RESOURCE(stuff->gc, client); - rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0, - DixGetAttrAccess); - if (rc != Success) - return rc; - - len = client->req_len - bytes_to_int32(sizeof(xCreateGCReq)); - if (len != Ones(stuff->mask)) - return BadLength; - pGC = (GC *) CreateGC(pDraw, stuff->mask, (XID *) &stuff[1], &error, - stuff->gc, client); - if (error != Success) - return error; - if (!AddResource(stuff->gc, RT_GC, (void *) pGC)) - return BadAlloc; - return Success; -} - -int -ProcChangeGC(ClientPtr client) -{ - GC *pGC; - int result; - unsigned len; - - REQUEST(xChangeGCReq); - REQUEST_AT_LEAST_SIZE(xChangeGCReq); - - result = dixLookupGC(&pGC, stuff->gc, client, DixSetAttrAccess); - if (result != Success) - return result; - - len = client->req_len - bytes_to_int32(sizeof(xChangeGCReq)); - if (len != Ones(stuff->mask)) - return BadLength; - - return ChangeGCXIDs(client, pGC, stuff->mask, (CARD32 *) &stuff[1]); -} - -int -ProcCopyGC(ClientPtr client) -{ - GC *dstGC; - GC *pGC; - int result; - - REQUEST(xCopyGCReq); - REQUEST_SIZE_MATCH(xCopyGCReq); - - result = dixLookupGC(&pGC, stuff->srcGC, client, DixGetAttrAccess); - if (result != Success) - return result; - result = dixLookupGC(&dstGC, stuff->dstGC, client, DixSetAttrAccess); - if (result != Success) - return result; - if ((dstGC->pScreen != pGC->pScreen) || (dstGC->depth != pGC->depth)) - return BadMatch; - if (stuff->mask & ~GCAllBits) { - client->errorValue = stuff->mask; - return BadValue; - } - return CopyGC(pGC, dstGC, stuff->mask); -} - -int -ProcSetDashes(ClientPtr client) -{ - GC *pGC; - int result; - - REQUEST(xSetDashesReq); - - REQUEST_FIXED_SIZE(xSetDashesReq, stuff->nDashes); - if (stuff->nDashes == 0) { - client->errorValue = 0; - return BadValue; - } - - result = dixLookupGC(&pGC, stuff->gc, client, DixSetAttrAccess); - if (result != Success) - return result; - - /* If there's an error, either there's no sensible errorValue, - * or there was a dash segment of 0. */ - client->errorValue = 0; - return SetDashes(pGC, stuff->dashOffset, stuff->nDashes, - (unsigned char *) &stuff[1]); -} - -int -ProcSetClipRectangles(ClientPtr client) -{ - int nr, result; - GC *pGC; - - REQUEST(xSetClipRectanglesReq); - - REQUEST_AT_LEAST_SIZE(xSetClipRectanglesReq); - if ((stuff->ordering != Unsorted) && (stuff->ordering != YSorted) && - (stuff->ordering != YXSorted) && (stuff->ordering != YXBanded)) { - client->errorValue = stuff->ordering; - return BadValue; - } - result = dixLookupGC(&pGC, stuff->gc, client, DixSetAttrAccess); - if (result != Success) - return result; - - nr = (client->req_len << 2) - sizeof(xSetClipRectanglesReq); - if (nr & 4) - return BadLength; - nr >>= 3; - return SetClipRects(pGC, stuff->xOrigin, stuff->yOrigin, - nr, (xRectangle *) &stuff[1], (int) stuff->ordering); -} - -int -ProcFreeGC(ClientPtr client) -{ - GC *pGC; - int rc; - - REQUEST(xResourceReq); - REQUEST_SIZE_MATCH(xResourceReq); - - rc = dixLookupGC(&pGC, stuff->id, client, DixDestroyAccess); - if (rc != Success) - return rc; - - FreeResource(stuff->id, RT_NONE); - return Success; -} - -int -ProcClearToBackground(ClientPtr client) -{ - REQUEST(xClearAreaReq); - WindowPtr pWin; - int rc; - - REQUEST_SIZE_MATCH(xClearAreaReq); - rc = dixLookupWindow(&pWin, stuff->window, client, DixWriteAccess); - if (rc != Success) - return rc; - if (pWin->drawable.class == InputOnly) { - client->errorValue = stuff->window; - return BadMatch; - } - if ((stuff->exposures != xTrue) && (stuff->exposures != xFalse)) { - client->errorValue = stuff->exposures; - return BadValue; - } - (*pWin->drawable.pScreen->ClearToBackground) (pWin, stuff->x, stuff->y, - stuff->width, stuff->height, - (Bool) stuff->exposures); - return Success; -} - -/* send GraphicsExpose events, or a NoExpose event, based on the region */ -void -SendGraphicsExpose(ClientPtr client, RegionPtr pRgn, XID drawable, - int major, int minor) -{ - if (pRgn && !RegionNil(pRgn)) { - xEvent *pEvent; - xEvent *pe; - BoxPtr pBox; - int i; - int numRects; - - numRects = RegionNumRects(pRgn); - pBox = RegionRects(pRgn); - if (!(pEvent = calloc(numRects, sizeof(xEvent)))) - return; - pe = pEvent; - - for (i = 1; i <= numRects; i++, pe++, pBox++) { - pe->u.u.type = GraphicsExpose; - pe->u.graphicsExposure.drawable = drawable; - pe->u.graphicsExposure.x = pBox->x1; - pe->u.graphicsExposure.y = pBox->y1; - pe->u.graphicsExposure.width = pBox->x2 - pBox->x1; - pe->u.graphicsExposure.height = pBox->y2 - pBox->y1; - pe->u.graphicsExposure.count = numRects - i; - pe->u.graphicsExposure.majorEvent = major; - pe->u.graphicsExposure.minorEvent = minor; - } - /* GraphicsExpose is a "critical event", which TryClientEvents - * handles specially. */ - TryClientEvents(client, NULL, pEvent, numRects, - (Mask) 0, NoEventMask, NullGrab); - free(pEvent); - } - else { - xEvent event = { - .u.noExposure.drawable = drawable, - .u.noExposure.majorEvent = major, - .u.noExposure.minorEvent = minor - }; - event.u.u.type = NoExpose; - WriteEventsToClient(client, 1, &event); - } -} - -int -ProcCopyArea(ClientPtr client) -{ - DrawablePtr pDst; - DrawablePtr pSrc; - GC *pGC; - - REQUEST(xCopyAreaReq); - RegionPtr pRgn; - int rc; - - REQUEST_SIZE_MATCH(xCopyAreaReq); - - VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pDst, DixWriteAccess); - if (stuff->dstDrawable != stuff->srcDrawable) { - rc = dixLookupDrawable(&pSrc, stuff->srcDrawable, client, 0, - DixReadAccess); - if (rc != Success) - return rc; - if ((pDst->pScreen != pSrc->pScreen) || (pDst->depth != pSrc->depth)) { - client->errorValue = stuff->dstDrawable; - return BadMatch; - } - } - else - pSrc = pDst; - - pRgn = (*pGC->ops->CopyArea) (pSrc, pDst, pGC, stuff->srcX, stuff->srcY, - stuff->width, stuff->height, - stuff->dstX, stuff->dstY); - if (pGC->graphicsExposures) { - SendGraphicsExpose(client, pRgn, stuff->dstDrawable, X_CopyArea, 0); - if (pRgn) - RegionDestroy(pRgn); - } - - return Success; -} - -int -ProcCopyPlane(ClientPtr client) -{ - DrawablePtr psrcDraw, pdstDraw; - GC *pGC; - - REQUEST(xCopyPlaneReq); - RegionPtr pRgn; - int rc; - - REQUEST_SIZE_MATCH(xCopyPlaneReq); - - VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pdstDraw, DixWriteAccess); - if (stuff->dstDrawable != stuff->srcDrawable) { - rc = dixLookupDrawable(&psrcDraw, stuff->srcDrawable, client, 0, - DixReadAccess); - if (rc != Success) - return rc; - - if (pdstDraw->pScreen != psrcDraw->pScreen) { - client->errorValue = stuff->dstDrawable; - return BadMatch; - } - } - else - psrcDraw = pdstDraw; - - /* Check to see if stuff->bitPlane has exactly ONE good bit set */ - if (stuff->bitPlane == 0 || (stuff->bitPlane & (stuff->bitPlane - 1)) || - (stuff->bitPlane > (1L << (psrcDraw->depth - 1)))) { - client->errorValue = stuff->bitPlane; - return BadValue; - } - - pRgn = - (*pGC->ops->CopyPlane) (psrcDraw, pdstDraw, pGC, stuff->srcX, - stuff->srcY, stuff->width, stuff->height, - stuff->dstX, stuff->dstY, stuff->bitPlane); - if (pGC->graphicsExposures) { - SendGraphicsExpose(client, pRgn, stuff->dstDrawable, X_CopyPlane, 0); - if (pRgn) - RegionDestroy(pRgn); - } - return Success; -} - -int -ProcPolyPoint(ClientPtr client) -{ - int npoint; - GC *pGC; - DrawablePtr pDraw; - - REQUEST(xPolyPointReq); - - REQUEST_AT_LEAST_SIZE(xPolyPointReq); - if ((stuff->coordMode != CoordModeOrigin) && - (stuff->coordMode != CoordModePrevious)) { - client->errorValue = stuff->coordMode; - return BadValue; - } - VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); - npoint = bytes_to_int32((client->req_len << 2) - sizeof(xPolyPointReq)); - if (npoint) - (*pGC->ops->PolyPoint) (pDraw, pGC, stuff->coordMode, npoint, - (xPoint *) &stuff[1]); - return Success; -} - -int -ProcPolyLine(ClientPtr client) -{ - int npoint; - GC *pGC; - DrawablePtr pDraw; - - REQUEST(xPolyLineReq); - - REQUEST_AT_LEAST_SIZE(xPolyLineReq); - if ((stuff->coordMode != CoordModeOrigin) && - (stuff->coordMode != CoordModePrevious)) { - client->errorValue = stuff->coordMode; - return BadValue; - } - VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); - npoint = bytes_to_int32((client->req_len << 2) - sizeof(xPolyLineReq)); - if (npoint > 1) - (*pGC->ops->Polylines) (pDraw, pGC, stuff->coordMode, npoint, - (DDXPointPtr) &stuff[1]); - return Success; -} - -int -ProcPolySegment(ClientPtr client) -{ - int nsegs; - GC *pGC; - DrawablePtr pDraw; - - REQUEST(xPolySegmentReq); - - REQUEST_AT_LEAST_SIZE(xPolySegmentReq); - VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); - nsegs = (client->req_len << 2) - sizeof(xPolySegmentReq); - if (nsegs & 4) - return BadLength; - nsegs >>= 3; - if (nsegs) - (*pGC->ops->PolySegment) (pDraw, pGC, nsegs, (xSegment *) &stuff[1]); - return Success; -} - -int -ProcPolyRectangle(ClientPtr client) -{ - int nrects; - GC *pGC; - DrawablePtr pDraw; - - REQUEST(xPolyRectangleReq); - - REQUEST_AT_LEAST_SIZE(xPolyRectangleReq); - VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); - nrects = (client->req_len << 2) - sizeof(xPolyRectangleReq); - if (nrects & 4) - return BadLength; - nrects >>= 3; - if (nrects) - (*pGC->ops->PolyRectangle) (pDraw, pGC, - nrects, (xRectangle *) &stuff[1]); - return Success; -} - -int -ProcPolyArc(ClientPtr client) -{ - int narcs; - GC *pGC; - DrawablePtr pDraw; - - REQUEST(xPolyArcReq); - - REQUEST_AT_LEAST_SIZE(xPolyArcReq); - VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); - narcs = (client->req_len << 2) - sizeof(xPolyArcReq); - if (narcs % sizeof(xArc)) - return BadLength; - narcs /= sizeof(xArc); - if (narcs) - (*pGC->ops->PolyArc) (pDraw, pGC, narcs, (xArc *) &stuff[1]); - return Success; -} - -int -ProcFillPoly(ClientPtr client) -{ - int things; - GC *pGC; - DrawablePtr pDraw; - - REQUEST(xFillPolyReq); - - REQUEST_AT_LEAST_SIZE(xFillPolyReq); - if ((stuff->shape != Complex) && (stuff->shape != Nonconvex) && - (stuff->shape != Convex)) { - client->errorValue = stuff->shape; - return BadValue; - } - if ((stuff->coordMode != CoordModeOrigin) && - (stuff->coordMode != CoordModePrevious)) { - client->errorValue = stuff->coordMode; - return BadValue; - } - - VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); - things = bytes_to_int32((client->req_len << 2) - sizeof(xFillPolyReq)); - if (things) - (*pGC->ops->FillPolygon) (pDraw, pGC, stuff->shape, - stuff->coordMode, things, - (DDXPointPtr) &stuff[1]); - return Success; -} - -int -ProcPolyFillRectangle(ClientPtr client) -{ - int things; - GC *pGC; - DrawablePtr pDraw; - - REQUEST(xPolyFillRectangleReq); - - REQUEST_AT_LEAST_SIZE(xPolyFillRectangleReq); - VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); - things = (client->req_len << 2) - sizeof(xPolyFillRectangleReq); - if (things & 4) - return BadLength; - things >>= 3; - - if (things) - (*pGC->ops->PolyFillRect) (pDraw, pGC, things, - (xRectangle *) &stuff[1]); - return Success; -} - -int -ProcPolyFillArc(ClientPtr client) -{ - int narcs; - GC *pGC; - DrawablePtr pDraw; - - REQUEST(xPolyFillArcReq); - - REQUEST_AT_LEAST_SIZE(xPolyFillArcReq); - VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); - narcs = (client->req_len << 2) - sizeof(xPolyFillArcReq); - if (narcs % sizeof(xArc)) - return BadLength; - narcs /= sizeof(xArc); - if (narcs) - (*pGC->ops->PolyFillArc) (pDraw, pGC, narcs, (xArc *) &stuff[1]); - return Success; -} - -#ifdef MATCH_CLIENT_ENDIAN - -int -ServerOrder(void) -{ - int whichbyte = 1; - - if (*((char *) &whichbyte)) - return LSBFirst; - return MSBFirst; -} - -#define ClientOrder(client) ((client)->swapped ? !ServerOrder() : ServerOrder()) - -void -ReformatImage(char *base, int nbytes, int bpp, int order) -{ - switch (bpp) { - case 1: /* yuck */ - if (BITMAP_BIT_ORDER != order) - BitOrderInvert((unsigned char *) base, nbytes); -#if IMAGE_BYTE_ORDER != BITMAP_BIT_ORDER && BITMAP_SCANLINE_UNIT != 8 - ReformatImage(base, nbytes, BITMAP_SCANLINE_UNIT, order); -#endif - break; - case 4: - break; /* yuck */ - case 8: - break; - case 16: - if (IMAGE_BYTE_ORDER != order) - TwoByteSwap((unsigned char *) base, nbytes); - break; - case 32: - if (IMAGE_BYTE_ORDER != order) - FourByteSwap((unsigned char *) base, nbytes); - break; - } -} -#else -#define ReformatImage(b,n,bpp,o) -#endif - -/* 64-bit server notes: the protocol restricts padding of images to - * 8-, 16-, or 32-bits. We would like to have 64-bits for the server - * to use internally. Removes need for internal alignment checking. - * All of the PutImage functions could be changed individually, but - * as currently written, they call other routines which require things - * to be 64-bit padded on scanlines, so we changed things here. - * If an image would be padded differently for 64- versus 32-, then - * copy each scanline to a 64-bit padded scanline. - * Also, we need to make sure that the image is aligned on a 64-bit - * boundary, even if the scanlines are padded to our satisfaction. - */ -int -ProcPutImage(ClientPtr client) -{ - GC *pGC; - DrawablePtr pDraw; - long length; /* length of scanline server padded */ - long lengthProto; /* length of scanline protocol padded */ - char *tmpImage; - - REQUEST(xPutImageReq); - - REQUEST_AT_LEAST_SIZE(xPutImageReq); - VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); - if (stuff->format == XYBitmap) { - if ((stuff->depth != 1) || - (stuff->leftPad >= (unsigned int) screenInfo.bitmapScanlinePad)) - return BadMatch; - length = BitmapBytePad(stuff->width + stuff->leftPad); - } - else if (stuff->format == XYPixmap) { - if ((pDraw->depth != stuff->depth) || - (stuff->leftPad >= (unsigned int) screenInfo.bitmapScanlinePad)) - return BadMatch; - length = BitmapBytePad(stuff->width + stuff->leftPad); - length *= stuff->depth; - } - else if (stuff->format == ZPixmap) { - if ((pDraw->depth != stuff->depth) || (stuff->leftPad != 0)) - return BadMatch; - length = PixmapBytePad(stuff->width, stuff->depth); - } - else { - client->errorValue = stuff->format; - return BadValue; - } - - tmpImage = (char *) &stuff[1]; - lengthProto = length; - - if ((bytes_to_int32(lengthProto * stuff->height) + - bytes_to_int32(sizeof(xPutImageReq))) != client->req_len) - return BadLength; - - ReformatImage(tmpImage, lengthProto * stuff->height, - stuff->format == ZPixmap ? BitsPerPixel(stuff->depth) : 1, - ClientOrder(client)); - - (*pGC->ops->PutImage) (pDraw, pGC, stuff->depth, stuff->dstX, stuff->dstY, - stuff->width, stuff->height, - stuff->leftPad, stuff->format, tmpImage); - - return Success; -} - -static int -DoGetImage(ClientPtr client, int format, Drawable drawable, - int x, int y, int width, int height, - Mask planemask) -{ - DrawablePtr pDraw, pBoundingDraw; - int nlines, linesPerBuf, rc; - int linesDone; - - /* coordinates relative to the bounding drawable */ - int relx, rely; - long widthBytesLine, length; - Mask plane = 0; - char *pBuf; - xGetImageReply xgi; - RegionPtr pVisibleRegion = NULL; - - if ((format != XYPixmap) && (format != ZPixmap)) { - client->errorValue = format; - return BadValue; - } - rc = dixLookupDrawable(&pDraw, drawable, client, 0, DixReadAccess); - if (rc != Success) - return rc; - - memset(&xgi, 0, sizeof(xGetImageReply)); - - relx = x; - rely = y; - - if (pDraw->type == DRAWABLE_WINDOW) { - WindowPtr pWin = (WindowPtr) pDraw; - - /* "If the drawable is a window, the window must be viewable ... or a - * BadMatch error results" */ - if (!pWin->viewable) - return BadMatch; - - /* If the drawable is a window, the rectangle must be contained within - * its bounds (including the border). */ - if (x < -wBorderWidth(pWin) || - x + width > wBorderWidth(pWin) + (int) pDraw->width || - y < -wBorderWidth(pWin) || - y + height > wBorderWidth(pWin) + (int) pDraw->height) - return BadMatch; - - relx += pDraw->x; - rely += pDraw->y; - - if (pDraw->pScreen->GetWindowPixmap) { - PixmapPtr pPix = (*pDraw->pScreen->GetWindowPixmap) (pWin); - - pBoundingDraw = &pPix->drawable; -#ifdef COMPOSITE - relx -= pPix->screen_x; - rely -= pPix->screen_y; -#endif - } - else { - pBoundingDraw = (DrawablePtr) pDraw->pScreen->root; - } - - xgi.visual = wVisual(pWin); - } - else { - pBoundingDraw = pDraw; - xgi.visual = None; - } - - /* "If the drawable is a pixmap, the given rectangle must be wholly - * contained within the pixmap, or a BadMatch error results. If the - * drawable is a window [...] it must be the case that if there were no - * inferiors or overlapping windows, the specified rectangle of the window - * would be fully visible on the screen and wholly contained within the - * outside edges of the window, or a BadMatch error results." - * - * We relax the window case slightly to mean that the rectangle must exist - * within the bounds of the window's backing pixmap. In particular, this - * means that a GetImage request may succeed or fail with BadMatch depending - * on whether any of its ancestor windows are redirected. */ - if (relx < 0 || relx + width > (int) pBoundingDraw->width || - rely < 0 || rely + height > (int) pBoundingDraw->height) - return BadMatch; - - xgi.type = X_Reply; - xgi.sequenceNumber = client->sequence; - xgi.depth = pDraw->depth; - if (format == ZPixmap) { - widthBytesLine = PixmapBytePad(width, pDraw->depth); - length = widthBytesLine * height; - - } - else { - widthBytesLine = BitmapBytePad(width); - plane = ((Mask) 1) << (pDraw->depth - 1); - /* only planes asked for */ - length = widthBytesLine * height * - Ones(planemask & (plane | (plane - 1))); - - } - - xgi.length = length; - - xgi.length = bytes_to_int32(xgi.length); - if (widthBytesLine == 0 || height == 0) - linesPerBuf = 0; - else if (widthBytesLine >= IMAGE_BUFSIZE) - linesPerBuf = 1; - else { - linesPerBuf = IMAGE_BUFSIZE / widthBytesLine; - if (linesPerBuf > height) - linesPerBuf = height; - } - length = linesPerBuf * widthBytesLine; - if (linesPerBuf < height) { - /* we have to make sure intermediate buffers don't need padding */ - while ((linesPerBuf > 1) && - (length & ((1L << LOG2_BYTES_PER_SCANLINE_PAD) - 1))) { - linesPerBuf--; - length -= widthBytesLine; - } - while (length & ((1L << LOG2_BYTES_PER_SCANLINE_PAD) - 1)) { - linesPerBuf++; - length += widthBytesLine; - } - } - if (!(pBuf = calloc(1, length))) - return BadAlloc; - WriteReplyToClient(client, sizeof(xGetImageReply), &xgi); - - if (pDraw->type == DRAWABLE_WINDOW) { - pVisibleRegion = NotClippedByChildren((WindowPtr) pDraw); - if (pVisibleRegion) { - RegionTranslate(pVisibleRegion, -pDraw->x, -pDraw->y); - } - } - - if (linesPerBuf == 0) { - /* nothing to do */ - } - else if (format == ZPixmap) { - linesDone = 0; - while (height - linesDone > 0) { - nlines = min(linesPerBuf, height - linesDone); - (*pDraw->pScreen->GetImage) (pDraw, - x, - y + linesDone, - width, - nlines, - format, planemask, (void *) pBuf); - if (pVisibleRegion) - XaceCensorImage(client, pVisibleRegion, widthBytesLine, - pDraw, x, y + linesDone, width, - nlines, format, pBuf); - - /* Note that this is NOT a call to WriteSwappedDataToClient, - as we do NOT byte swap */ - ReformatImage(pBuf, (int) (nlines * widthBytesLine), - BitsPerPixel(pDraw->depth), ClientOrder(client)); - - WriteToClient(client, (int) (nlines * widthBytesLine), pBuf); - linesDone += nlines; - } - } - else { /* XYPixmap */ - - for (; plane; plane >>= 1) { - if (planemask & plane) { - linesDone = 0; - while (height - linesDone > 0) { - nlines = min(linesPerBuf, height - linesDone); - (*pDraw->pScreen->GetImage) (pDraw, - x, - y + linesDone, - width, - nlines, - format, plane, (void *) pBuf); - if (pVisibleRegion) - XaceCensorImage(client, pVisibleRegion, - widthBytesLine, - pDraw, x, y + linesDone, width, - nlines, format, pBuf); - - /* Note: NOT a call to WriteSwappedDataToClient, - as we do NOT byte swap */ - ReformatImage(pBuf, (int) (nlines * widthBytesLine), - 1, ClientOrder(client)); - - WriteToClient(client, (int)(nlines * widthBytesLine), pBuf); - linesDone += nlines; - } - } - } - } - if (pVisibleRegion) - RegionDestroy(pVisibleRegion); - free(pBuf); - return Success; -} - -int -ProcGetImage(ClientPtr client) -{ - REQUEST(xGetImageReq); - - REQUEST_SIZE_MATCH(xGetImageReq); - - return DoGetImage(client, stuff->format, stuff->drawable, - stuff->x, stuff->y, - (int) stuff->width, (int) stuff->height, - stuff->planeMask); -} - -int -ProcPolyText(ClientPtr client) -{ - int err; - - REQUEST(xPolyTextReq); - DrawablePtr pDraw; - GC *pGC; - - REQUEST_AT_LEAST_SIZE(xPolyTextReq); - VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); - - err = PolyText(client, - pDraw, - pGC, - (unsigned char *) &stuff[1], - ((unsigned char *) stuff) + (client->req_len << 2), - stuff->x, stuff->y, stuff->reqType, stuff->drawable); - - if (err == Success) { - return Success; - } - else - return err; -} - -int -ProcImageText8(ClientPtr client) -{ - int err; - DrawablePtr pDraw; - GC *pGC; - - REQUEST(xImageTextReq); - - REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars); - VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); - - err = ImageText(client, - pDraw, - pGC, - stuff->nChars, - (unsigned char *) &stuff[1], - stuff->x, stuff->y, stuff->reqType, stuff->drawable); - - if (err == Success) { - return Success; - } - else - return err; -} - -int -ProcImageText16(ClientPtr client) -{ - int err; - DrawablePtr pDraw; - GC *pGC; - - REQUEST(xImageTextReq); - - REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars << 1); - VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); - - err = ImageText(client, - pDraw, - pGC, - stuff->nChars, - (unsigned char *) &stuff[1], - stuff->x, stuff->y, stuff->reqType, stuff->drawable); - - if (err == Success) { - return Success; - } - else - return err; -} - -int -ProcCreateColormap(ClientPtr client) -{ - VisualPtr pVisual; - ColormapPtr pmap; - Colormap mid; - WindowPtr pWin; - ScreenPtr pScreen; - - REQUEST(xCreateColormapReq); - int i, result; - - REQUEST_SIZE_MATCH(xCreateColormapReq); - - if ((stuff->alloc != AllocNone) && (stuff->alloc != AllocAll)) { - client->errorValue = stuff->alloc; - return BadValue; - } - mid = stuff->mid; - LEGAL_NEW_RESOURCE(mid, client); - result = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); - if (result != Success) - return result; - - pScreen = pWin->drawable.pScreen; - for (i = 0, pVisual = pScreen->visuals; - i < pScreen->numVisuals; i++, pVisual++) { - if (pVisual->vid != stuff->visual) - continue; - return CreateColormap(mid, pScreen, pVisual, &pmap, - (int) stuff->alloc, client->index); - } - client->errorValue = stuff->visual; - return BadMatch; -} - -int -ProcFreeColormap(ClientPtr client) -{ - ColormapPtr pmap; - int rc; - - REQUEST(xResourceReq); - - REQUEST_SIZE_MATCH(xResourceReq); - rc = dixLookupResourceByType((void **) &pmap, stuff->id, RT_COLORMAP, - client, DixDestroyAccess); - if (rc == Success) { - /* Freeing a default colormap is a no-op */ - if (!(pmap->flags & IsDefault)) - FreeResource(stuff->id, RT_NONE); - return Success; - } - else { - client->errorValue = stuff->id; - return rc; - } -} - -int -ProcCopyColormapAndFree(ClientPtr client) -{ - Colormap mid; - ColormapPtr pSrcMap; - - REQUEST(xCopyColormapAndFreeReq); - int rc; - - REQUEST_SIZE_MATCH(xCopyColormapAndFreeReq); - mid = stuff->mid; - LEGAL_NEW_RESOURCE(mid, client); - rc = dixLookupResourceByType((void **) &pSrcMap, stuff->srcCmap, - RT_COLORMAP, client, - DixReadAccess | DixRemoveAccess); - if (rc == Success) - return CopyColormapAndFree(mid, pSrcMap, client->index); - client->errorValue = stuff->srcCmap; - return rc; -} - -int -ProcInstallColormap(ClientPtr client) -{ - ColormapPtr pcmp; - int rc; - - REQUEST(xResourceReq); - REQUEST_SIZE_MATCH(xResourceReq); - - rc = dixLookupResourceByType((void **) &pcmp, stuff->id, RT_COLORMAP, - client, DixInstallAccess); - if (rc != Success) - goto out; - - rc = XaceHook(XACE_SCREEN_ACCESS, client, pcmp->pScreen, DixSetAttrAccess); - if (rc != Success) { - if (rc == BadValue) - rc = BadColor; - goto out; - } - - (*(pcmp->pScreen->InstallColormap)) (pcmp); - return Success; - - out: - client->errorValue = stuff->id; - return rc; -} - -int -ProcUninstallColormap(ClientPtr client) -{ - ColormapPtr pcmp; - int rc; - - REQUEST(xResourceReq); - REQUEST_SIZE_MATCH(xResourceReq); - - rc = dixLookupResourceByType((void **) &pcmp, stuff->id, RT_COLORMAP, - client, DixUninstallAccess); - if (rc != Success) - goto out; - - rc = XaceHook(XACE_SCREEN_ACCESS, client, pcmp->pScreen, DixSetAttrAccess); - if (rc != Success) { - if (rc == BadValue) - rc = BadColor; - goto out; - } - - if (pcmp->mid != pcmp->pScreen->defColormap) - (*(pcmp->pScreen->UninstallColormap)) (pcmp); - return Success; - - out: - client->errorValue = stuff->id; - return rc; -} - -int -ProcListInstalledColormaps(ClientPtr client) -{ - xListInstalledColormapsReply *preply; - int nummaps, rc; - WindowPtr pWin; - - REQUEST(xResourceReq); - REQUEST_SIZE_MATCH(xResourceReq); - - rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess); - if (rc != Success) - return rc; - - rc = XaceHook(XACE_SCREEN_ACCESS, client, pWin->drawable.pScreen, - DixGetAttrAccess); - if (rc != Success) - return rc; - - preply = malloc(sizeof(xListInstalledColormapsReply) + - pWin->drawable.pScreen->maxInstalledCmaps * - sizeof(Colormap)); - if (!preply) - return BadAlloc; - - preply->type = X_Reply; - preply->sequenceNumber = client->sequence; - nummaps = (*pWin->drawable.pScreen->ListInstalledColormaps) - (pWin->drawable.pScreen, (Colormap *) &preply[1]); - preply->nColormaps = nummaps; - preply->length = nummaps; - WriteReplyToClient(client, sizeof(xListInstalledColormapsReply), preply); - client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; - WriteSwappedDataToClient(client, nummaps * sizeof(Colormap), &preply[1]); - free(preply); - return Success; -} - -int -ProcAllocColor(ClientPtr client) -{ - ColormapPtr pmap; - int rc; - - REQUEST(xAllocColorReq); - - REQUEST_SIZE_MATCH(xAllocColorReq); - rc = dixLookupResourceByType((void **) &pmap, stuff->cmap, RT_COLORMAP, - client, DixAddAccess); - if (rc == Success) { - xAllocColorReply acr = { - .type = X_Reply, - .sequenceNumber = client->sequence, - .length = 0, - .red = stuff->red, - .green = stuff->green, - .blue = stuff->blue, - .pixel = 0 - }; - if ((rc = AllocColor(pmap, &acr.red, &acr.green, &acr.blue, - &acr.pixel, client->index))) - return rc; -#ifdef PANORAMIX - if (noPanoramiXExtension || !pmap->pScreen->myNum) -#endif - WriteReplyToClient(client, sizeof(xAllocColorReply), &acr); - return Success; - - } - else { - client->errorValue = stuff->cmap; - return rc; - } -} - -int -ProcAllocNamedColor(ClientPtr client) -{ - ColormapPtr pcmp; - int rc; - - REQUEST(xAllocNamedColorReq); - - REQUEST_FIXED_SIZE(xAllocNamedColorReq, stuff->nbytes); - rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP, - client, DixAddAccess); - if (rc == Success) { - xAllocNamedColorReply ancr = { - .type = X_Reply, - .sequenceNumber = client->sequence, - .length = 0 - }; - if (OsLookupColor - (pcmp->pScreen->myNum, (char *) &stuff[1], stuff->nbytes, - &ancr.exactRed, &ancr.exactGreen, &ancr.exactBlue)) { - ancr.screenRed = ancr.exactRed; - ancr.screenGreen = ancr.exactGreen; - ancr.screenBlue = ancr.exactBlue; - ancr.pixel = 0; - if ((rc = AllocColor(pcmp, - &ancr.screenRed, &ancr.screenGreen, - &ancr.screenBlue, &ancr.pixel, client->index))) - return rc; -#ifdef PANORAMIX - if (noPanoramiXExtension || !pcmp->pScreen->myNum) -#endif - WriteReplyToClient(client, sizeof(xAllocNamedColorReply), - &ancr); - return Success; - } - else - return BadName; - - } - else { - client->errorValue = stuff->cmap; - return rc; - } -} - -int -ProcAllocColorCells(ClientPtr client) -{ - ColormapPtr pcmp; - int rc; - - REQUEST(xAllocColorCellsReq); - - REQUEST_SIZE_MATCH(xAllocColorCellsReq); - rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP, - client, DixAddAccess); - if (rc == Success) { - int npixels, nmasks; - long length; - Pixel *ppixels, *pmasks; - - npixels = stuff->colors; - if (!npixels) { - client->errorValue = npixels; - return BadValue; - } - if (stuff->contiguous != xTrue && stuff->contiguous != xFalse) { - client->errorValue = stuff->contiguous; - return BadValue; - } - nmasks = stuff->planes; - length = ((long) npixels + (long) nmasks) * sizeof(Pixel); - ppixels = malloc(length); - if (!ppixels) - return BadAlloc; - pmasks = ppixels + npixels; - - if ((rc = AllocColorCells(client->index, pcmp, npixels, nmasks, - (Bool) stuff->contiguous, ppixels, pmasks))) { - free(ppixels); - return rc; - } -#ifdef PANORAMIX - if (noPanoramiXExtension || !pcmp->pScreen->myNum) -#endif - { - xAllocColorCellsReply accr = { - .type = X_Reply, - .sequenceNumber = client->sequence, - .length = bytes_to_int32(length), - .nPixels = npixels, - .nMasks = nmasks - }; - WriteReplyToClient(client, sizeof(xAllocColorCellsReply), &accr); - client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; - WriteSwappedDataToClient(client, length, ppixels); - } - free(ppixels); - return Success; - } - else { - client->errorValue = stuff->cmap; - return rc; - } -} - -int -ProcAllocColorPlanes(ClientPtr client) -{ - ColormapPtr pcmp; - int rc; - - REQUEST(xAllocColorPlanesReq); - - REQUEST_SIZE_MATCH(xAllocColorPlanesReq); - rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP, - client, DixAddAccess); - if (rc == Success) { - xAllocColorPlanesReply acpr; - int npixels; - long length; - Pixel *ppixels; - - npixels = stuff->colors; - if (!npixels) { - client->errorValue = npixels; - return BadValue; - } - if (stuff->contiguous != xTrue && stuff->contiguous != xFalse) { - client->errorValue = stuff->contiguous; - return BadValue; - } - acpr = (xAllocColorPlanesReply) { - .type = X_Reply, - .sequenceNumber = client->sequence, - .nPixels = npixels - }; - length = (long) npixels *sizeof(Pixel); - - ppixels = malloc(length); - if (!ppixels) - return BadAlloc; - if ((rc = AllocColorPlanes(client->index, pcmp, npixels, - (int) stuff->red, (int) stuff->green, - (int) stuff->blue, (Bool) stuff->contiguous, - ppixels, &acpr.redMask, &acpr.greenMask, - &acpr.blueMask))) { - free(ppixels); - return rc; - } - acpr.length = bytes_to_int32(length); -#ifdef PANORAMIX - if (noPanoramiXExtension || !pcmp->pScreen->myNum) -#endif - { - WriteReplyToClient(client, sizeof(xAllocColorPlanesReply), &acpr); - client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; - WriteSwappedDataToClient(client, length, ppixels); - } - free(ppixels); - return Success; - } - else { - client->errorValue = stuff->cmap; - return rc; - } -} - -int -ProcFreeColors(ClientPtr client) -{ - ColormapPtr pcmp; - int rc; - - REQUEST(xFreeColorsReq); - - REQUEST_AT_LEAST_SIZE(xFreeColorsReq); - rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP, - client, DixRemoveAccess); - if (rc == Success) { - int count; - - if (pcmp->flags & AllAllocated) - return BadAccess; - count = bytes_to_int32((client->req_len << 2) - sizeof(xFreeColorsReq)); - return FreeColors(pcmp, client->index, count, - (Pixel *) &stuff[1], (Pixel) stuff->planeMask); - } - else { - client->errorValue = stuff->cmap; - return rc; - } -} - -int -ProcStoreColors(ClientPtr client) -{ - ColormapPtr pcmp; - int rc; - - REQUEST(xStoreColorsReq); - - REQUEST_AT_LEAST_SIZE(xStoreColorsReq); - rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP, - client, DixWriteAccess); - if (rc == Success) { - int count; - - count = (client->req_len << 2) - sizeof(xStoreColorsReq); - if (count % sizeof(xColorItem)) - return BadLength; - count /= sizeof(xColorItem); - return StoreColors(pcmp, count, (xColorItem *) &stuff[1], client); - } - else { - client->errorValue = stuff->cmap; - return rc; - } -} - -int -ProcStoreNamedColor(ClientPtr client) -{ - ColormapPtr pcmp; - int rc; - - REQUEST(xStoreNamedColorReq); - - REQUEST_FIXED_SIZE(xStoreNamedColorReq, stuff->nbytes); - rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP, - client, DixWriteAccess); - if (rc == Success) { - xColorItem def; - - if (OsLookupColor(pcmp->pScreen->myNum, (char *) &stuff[1], - stuff->nbytes, &def.red, &def.green, &def.blue)) { - def.flags = stuff->flags; - def.pixel = stuff->pixel; - return StoreColors(pcmp, 1, &def, client); - } - return BadName; - } - else { - client->errorValue = stuff->cmap; - return rc; - } -} - -int -ProcQueryColors(ClientPtr client) -{ - ColormapPtr pcmp; - int rc; - - REQUEST(xQueryColorsReq); - - REQUEST_AT_LEAST_SIZE(xQueryColorsReq); - rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP, - client, DixReadAccess); - if (rc == Success) { - int count; - xrgb *prgbs; - xQueryColorsReply qcr; - - count = - bytes_to_int32((client->req_len << 2) - sizeof(xQueryColorsReq)); - prgbs = calloc(1, count * sizeof(xrgb)); - if (!prgbs && count) - return BadAlloc; - if ((rc = - QueryColors(pcmp, count, (Pixel *) &stuff[1], prgbs, client))) { - free(prgbs); - return rc; - } - qcr = (xQueryColorsReply) { - .type = X_Reply, - .sequenceNumber = client->sequence, - .length = bytes_to_int32(count * sizeof(xrgb)), - .nColors = count - }; - WriteReplyToClient(client, sizeof(xQueryColorsReply), &qcr); - if (count) { - client->pSwapReplyFunc = (ReplySwapPtr) SQColorsExtend; - WriteSwappedDataToClient(client, count * sizeof(xrgb), prgbs); - } - free(prgbs); - return Success; - - } - else { - client->errorValue = stuff->cmap; - return rc; - } -} - -int -ProcLookupColor(ClientPtr client) -{ - ColormapPtr pcmp; - int rc; - - REQUEST(xLookupColorReq); - - REQUEST_FIXED_SIZE(xLookupColorReq, stuff->nbytes); - rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP, - client, DixReadAccess); - if (rc == Success) { - CARD16 exactRed, exactGreen, exactBlue; - - if (OsLookupColor - (pcmp->pScreen->myNum, (char *) &stuff[1], stuff->nbytes, - &exactRed, &exactGreen, &exactBlue)) { - xLookupColorReply lcr = { - .type = X_Reply, - .sequenceNumber = client->sequence, - .length = 0, - .exactRed = exactRed, - .exactGreen = exactGreen, - .exactBlue = exactBlue, - .screenRed = exactRed, - .screenGreen = exactGreen, - .screenBlue = exactBlue - }; - (*pcmp->pScreen->ResolveColor) (&lcr.screenRed, - &lcr.screenGreen, - &lcr.screenBlue, pcmp->pVisual); - WriteReplyToClient(client, sizeof(xLookupColorReply), &lcr); - return Success; - } - return BadName; - } - else { - client->errorValue = stuff->cmap; - return rc; - } -} - -int -ProcCreateCursor(ClientPtr client) -{ - CursorPtr pCursor; - PixmapPtr src; - PixmapPtr msk; - unsigned char *srcbits; - unsigned char *mskbits; - unsigned short width, height; - long n; - CursorMetricRec cm; - int rc; - - REQUEST(xCreateCursorReq); - - REQUEST_SIZE_MATCH(xCreateCursorReq); - LEGAL_NEW_RESOURCE(stuff->cid, client); - - rc = dixLookupResourceByType((void **) &src, stuff->source, RT_PIXMAP, - client, DixReadAccess); - if (rc != Success) { - client->errorValue = stuff->source; - return rc; - } - - if (src->drawable.depth != 1) - return (BadMatch); - - /* Find and validate cursor mask pixmap, if one is provided */ - if (stuff->mask != None) { - rc = dixLookupResourceByType((void **) &msk, stuff->mask, RT_PIXMAP, - client, DixReadAccess); - if (rc != Success) { - client->errorValue = stuff->mask; - return rc; - } - - if (src->drawable.width != msk->drawable.width - || src->drawable.height != msk->drawable.height - || src->drawable.depth != 1 || msk->drawable.depth != 1) - return BadMatch; - } - else - msk = NULL; - - width = src->drawable.width; - height = src->drawable.height; - - if (stuff->x > width || stuff->y > height) - return BadMatch; - - n = BitmapBytePad(width) * height; - srcbits = calloc(1, n); - if (!srcbits) - return BadAlloc; - mskbits = malloc(n); - if (!mskbits) { - free(srcbits); - return BadAlloc; - } - - (*src->drawable.pScreen->GetImage) ((DrawablePtr) src, 0, 0, width, height, - XYPixmap, 1, (void *) srcbits); - if (msk == (PixmapPtr) NULL) { - unsigned char *bits = mskbits; - - while (--n >= 0) - *bits++ = ~0; - } - else { - /* zeroing the (pad) bits helps some ddx cursor handling */ - memset((char *) mskbits, 0, n); - (*msk->drawable.pScreen->GetImage) ((DrawablePtr) msk, 0, 0, width, - height, XYPixmap, 1, - (void *) mskbits); - } - cm.width = width; - cm.height = height; - cm.xhot = stuff->x; - cm.yhot = stuff->y; - rc = AllocARGBCursor(srcbits, mskbits, NULL, &cm, - stuff->foreRed, stuff->foreGreen, stuff->foreBlue, - stuff->backRed, stuff->backGreen, stuff->backBlue, - &pCursor, client, stuff->cid); - - if (rc != Success) - goto bail; - if (!AddResource(stuff->cid, RT_CURSOR, (void *) pCursor)) { - rc = BadAlloc; - goto bail; - } - - return Success; - bail: - free(srcbits); - free(mskbits); - return rc; -} - -int -ProcCreateGlyphCursor(ClientPtr client) -{ - CursorPtr pCursor; - int res; - - REQUEST(xCreateGlyphCursorReq); - - REQUEST_SIZE_MATCH(xCreateGlyphCursorReq); - LEGAL_NEW_RESOURCE(stuff->cid, client); - - res = AllocGlyphCursor(stuff->source, stuff->sourceChar, - stuff->mask, stuff->maskChar, - stuff->foreRed, stuff->foreGreen, stuff->foreBlue, - stuff->backRed, stuff->backGreen, stuff->backBlue, - &pCursor, client, stuff->cid); - if (res != Success) - return res; - if (AddResource(stuff->cid, RT_CURSOR, (void *) pCursor)) - return Success; - return BadAlloc; -} - -int -ProcFreeCursor(ClientPtr client) -{ - CursorPtr pCursor; - int rc; - - REQUEST(xResourceReq); - - REQUEST_SIZE_MATCH(xResourceReq); - rc = dixLookupResourceByType((void **) &pCursor, stuff->id, RT_CURSOR, - client, DixDestroyAccess); - if (rc == Success) { - FreeResource(stuff->id, RT_NONE); - return Success; - } - else { - client->errorValue = stuff->id; - return rc; - } -} - -int -ProcQueryBestSize(ClientPtr client) -{ - xQueryBestSizeReply reply; - DrawablePtr pDraw; - ScreenPtr pScreen; - int rc; - - REQUEST(xQueryBestSizeReq); - REQUEST_SIZE_MATCH(xQueryBestSizeReq); - - if ((stuff->class != CursorShape) && - (stuff->class != TileShape) && (stuff->class != StippleShape)) { - client->errorValue = stuff->class; - return BadValue; - } - - rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY, - DixGetAttrAccess); - if (rc != Success) - return rc; - if (stuff->class != CursorShape && pDraw->type == UNDRAWABLE_WINDOW) - return BadMatch; - pScreen = pDraw->pScreen; - rc = XaceHook(XACE_SCREEN_ACCESS, client, pScreen, DixGetAttrAccess); - if (rc != Success) - return rc; - (*pScreen->QueryBestSize) (stuff->class, &stuff->width, - &stuff->height, pScreen); - reply = (xQueryBestSizeReply) { - .type = X_Reply, - .sequenceNumber = client->sequence, - .length = 0, - .width = stuff->width, - .height = stuff->height - }; - WriteReplyToClient(client, sizeof(xQueryBestSizeReply), &reply); - return Success; -} - -int -ProcSetScreenSaver(ClientPtr client) -{ - int rc, i, blankingOption, exposureOption; - - REQUEST(xSetScreenSaverReq); - REQUEST_SIZE_MATCH(xSetScreenSaverReq); - - for (i = 0; i < screenInfo.numScreens; i++) { - rc = XaceHook(XACE_SCREENSAVER_ACCESS, client, screenInfo.screens[i], - DixSetAttrAccess); - if (rc != Success) - return rc; - } - - blankingOption = stuff->preferBlank; - if ((blankingOption != DontPreferBlanking) && - (blankingOption != PreferBlanking) && - (blankingOption != DefaultBlanking)) { - client->errorValue = blankingOption; - return BadValue; - } - exposureOption = stuff->allowExpose; - if ((exposureOption != DontAllowExposures) && - (exposureOption != AllowExposures) && - (exposureOption != DefaultExposures)) { - client->errorValue = exposureOption; - return BadValue; - } - if (stuff->timeout < -1) { - client->errorValue = stuff->timeout; - return BadValue; - } - if (stuff->interval < -1) { - client->errorValue = stuff->interval; - return BadValue; - } - - if (blankingOption == DefaultBlanking) - ScreenSaverBlanking = defaultScreenSaverBlanking; - else - ScreenSaverBlanking = blankingOption; - if (exposureOption == DefaultExposures) - ScreenSaverAllowExposures = defaultScreenSaverAllowExposures; - else - ScreenSaverAllowExposures = exposureOption; - - if (stuff->timeout >= 0) - ScreenSaverTime = stuff->timeout * MILLI_PER_SECOND; - else - ScreenSaverTime = defaultScreenSaverTime; - if (stuff->interval >= 0) - ScreenSaverInterval = stuff->interval * MILLI_PER_SECOND; - else - ScreenSaverInterval = defaultScreenSaverInterval; - - SetScreenSaverTimer(); - return Success; -} - -int -ProcGetScreenSaver(ClientPtr client) -{ - xGetScreenSaverReply rep; - int rc, i; - - REQUEST_SIZE_MATCH(xReq); - - for (i = 0; i < screenInfo.numScreens; i++) { - rc = XaceHook(XACE_SCREENSAVER_ACCESS, client, screenInfo.screens[i], - DixGetAttrAccess); - if (rc != Success) - return rc; - } - - rep = (xGetScreenSaverReply) { - .type = X_Reply, - .sequenceNumber = client->sequence, - .length = 0, - .timeout = ScreenSaverTime / MILLI_PER_SECOND, - .interval = ScreenSaverInterval / MILLI_PER_SECOND, - .preferBlanking = ScreenSaverBlanking, - .allowExposures = ScreenSaverAllowExposures - }; - WriteReplyToClient(client, sizeof(xGetScreenSaverReply), &rep); - return Success; -} - -int -ProcChangeHosts(ClientPtr client) -{ - REQUEST(xChangeHostsReq); - - REQUEST_FIXED_SIZE(xChangeHostsReq, stuff->hostLength); - - if (stuff->mode == HostInsert) - return AddHost(client, (int) stuff->hostFamily, - stuff->hostLength, (void *) &stuff[1]); - if (stuff->mode == HostDelete) - return RemoveHost(client, (int) stuff->hostFamily, - stuff->hostLength, (void *) &stuff[1]); - client->errorValue = stuff->mode; - return BadValue; -} - -int -ProcListHosts(ClientPtr client) -{ - xListHostsReply reply; - int len, nHosts, result; - BOOL enabled; - void *pdata; - - /* REQUEST(xListHostsReq); */ - - REQUEST_SIZE_MATCH(xListHostsReq); - - /* untrusted clients can't list hosts */ - result = XaceHook(XACE_SERVER_ACCESS, client, DixReadAccess); - if (result != Success) - return result; - - result = GetHosts(&pdata, &nHosts, &len, &enabled); - if (result != Success) - return result; - - reply = (xListHostsReply) { - .type = X_Reply, - .enabled = enabled, - .sequenceNumber = client->sequence, - .length = bytes_to_int32(len), - .nHosts = nHosts - }; - WriteReplyToClient(client, sizeof(xListHostsReply), &reply); - if (nHosts) { - client->pSwapReplyFunc = (ReplySwapPtr) SLHostsExtend; - WriteSwappedDataToClient(client, len, pdata); - } - free(pdata); - return Success; -} - -int -ProcChangeAccessControl(ClientPtr client) -{ - REQUEST(xSetAccessControlReq); - - REQUEST_SIZE_MATCH(xSetAccessControlReq); - if ((stuff->mode != EnableAccess) && (stuff->mode != DisableAccess)) { - client->errorValue = stuff->mode; - return BadValue; - } - return ChangeAccessControl(client, stuff->mode == EnableAccess); -} - -/********************* - * CloseDownRetainedResources - * - * Find all clients that are gone and have terminated in RetainTemporary - * and destroy their resources. - *********************/ - -static void -CloseDownRetainedResources(void) -{ - int i; - ClientPtr client; - - for (i = 1; i < currentMaxClients; i++) { - client = clients[i]; - if (client && (client->closeDownMode == RetainTemporary) - && (client->clientGone)) - CloseDownClient(client); - } -} - -int -ProcKillClient(ClientPtr client) -{ - REQUEST(xResourceReq); - ClientPtr killclient; - int rc; - - REQUEST_SIZE_MATCH(xResourceReq); - if (stuff->id == AllTemporary) { - CloseDownRetainedResources(); - return Success; - } - - rc = dixLookupClient(&killclient, stuff->id, client, DixDestroyAccess); - if (rc == Success) { - CloseDownClient(killclient); - if (client == killclient) { - /* force yield and return Success, so that Dispatch() - * doesn't try to touch client - */ - isItTimeToYield = TRUE; - } - return Success; - } - else - return rc; -} - -int -ProcSetFontPath(ClientPtr client) -{ - unsigned char *ptr; - unsigned long nbytes, total; - long nfonts; - int n; - - REQUEST(xSetFontPathReq); - - REQUEST_AT_LEAST_SIZE(xSetFontPathReq); - - nbytes = (client->req_len << 2) - sizeof(xSetFontPathReq); - total = nbytes; - ptr = (unsigned char *) &stuff[1]; - nfonts = stuff->nFonts; - while (--nfonts >= 0) { - if ((total == 0) || (total < (n = (*ptr + 1)))) - return BadLength; - total -= n; - ptr += n; - } - if (total >= 4) - return BadLength; - return SetFontPath(client, stuff->nFonts, (unsigned char *) &stuff[1]); -} - -int -ProcGetFontPath(ClientPtr client) -{ - xGetFontPathReply reply; - int rc, stringLens, numpaths; - unsigned char *bufferStart; - - /* REQUEST (xReq); */ - - REQUEST_SIZE_MATCH(xReq); - rc = GetFontPath(client, &numpaths, &stringLens, &bufferStart); - if (rc != Success) - return rc; - - reply = (xGetFontPathReply) { - .type = X_Reply, - .sequenceNumber = client->sequence, - .length = bytes_to_int32(stringLens + numpaths), - .nPaths = numpaths - }; - - WriteReplyToClient(client, sizeof(xGetFontPathReply), &reply); - if (stringLens || numpaths) - WriteToClient(client, stringLens + numpaths, bufferStart); - return Success; -} - -int -ProcChangeCloseDownMode(ClientPtr client) -{ - int rc; - - REQUEST(xSetCloseDownModeReq); - REQUEST_SIZE_MATCH(xSetCloseDownModeReq); - - rc = XaceHook(XACE_CLIENT_ACCESS, client, client, DixManageAccess); - if (rc != Success) - return rc; - - if ((stuff->mode == AllTemporary) || - (stuff->mode == RetainPermanent) || (stuff->mode == RetainTemporary)) { - client->closeDownMode = stuff->mode; - return Success; - } - else { - client->errorValue = stuff->mode; - return BadValue; - } -} - -int -ProcForceScreenSaver(ClientPtr client) -{ - int rc; - - REQUEST(xForceScreenSaverReq); - - REQUEST_SIZE_MATCH(xForceScreenSaverReq); - - if ((stuff->mode != ScreenSaverReset) && (stuff->mode != ScreenSaverActive)) { - client->errorValue = stuff->mode; - return BadValue; - } - rc = dixSaveScreens(client, SCREEN_SAVER_FORCER, (int) stuff->mode); - if (rc != Success) - return rc; - return Success; -} - -int -ProcNoOperation(ClientPtr client) -{ - REQUEST_AT_LEAST_SIZE(xReq); - - /* noop -- don't do anything */ - return Success; -} - -/********************** - * CloseDownClient - * - * Client can either mark his resources destroy or retain. If retained and - * then killed again, the client is really destroyed. - *********************/ - -char dispatchExceptionAtReset = DE_RESET; - -void -CloseDownClient(ClientPtr client) -{ - Bool really_close_down = client->clientGone || - client->closeDownMode == DestroyAll; - - if (!client->clientGone) { - /* ungrab server if grabbing client dies */ - if (grabState != GrabNone && grabClient == client) { - UngrabServer(client); - } - BITCLEAR(grabWaiters, client->index); - DeleteClientFromAnySelections(client); - ReleaseActiveGrabs(client); - DeleteClientFontStuff(client); - if (!really_close_down) { - /* This frees resources that should never be retained - * no matter what the close down mode is. Actually we - * could do this unconditionally, but it's probably - * better not to traverse all the client's resources - * twice (once here, once a few lines down in - * FreeClientResources) in the common case of - * really_close_down == TRUE. - */ - FreeClientNeverRetainResources(client); - client->clientState = ClientStateRetained; - if (ClientStateCallback) { - NewClientInfoRec clientinfo; - - clientinfo.client = client; - clientinfo.prefix = (xConnSetupPrefix *) NULL; - clientinfo.setup = (xConnSetup *) NULL; - CallCallbacks((&ClientStateCallback), (void *) &clientinfo); - } - } - client->clientGone = TRUE; /* so events aren't sent to client */ - if (ClientIsAsleep(client)) - ClientSignal(client); - ProcessWorkQueueZombies(); - CloseDownConnection(client); - - /* If the client made it to the Running stage, nClients has - * been incremented on its behalf, so we need to decrement it - * now. If it hasn't gotten to Running, nClients has *not* - * been incremented, so *don't* decrement it. - */ - if (client->clientState != ClientStateInitial) { - --nClients; - } - } - - if (really_close_down) { - if (client->clientState == ClientStateRunning && nClients == 0) - dispatchException |= dispatchExceptionAtReset; - - client->clientState = ClientStateGone; - if (ClientStateCallback) { - NewClientInfoRec clientinfo; - - clientinfo.client = client; - clientinfo.prefix = (xConnSetupPrefix *) NULL; - clientinfo.setup = (xConnSetup *) NULL; - CallCallbacks((&ClientStateCallback), (void *) &clientinfo); - } - TouchListenerGone(client->clientAsMask); - FreeClientResources(client); - /* Disable client ID tracking. This must be done after - * ClientStateCallback. */ - ReleaseClientIds(client); -#ifdef XSERVER_DTRACE - XSERVER_CLIENT_DISCONNECT(client->index); -#endif - if (client->index < nextFreeClientID) - nextFreeClientID = client->index; - clients[client->index] = NullClient; - SmartLastClient = NullClient; - dixFreeObjectWithPrivates(client, PRIVATE_CLIENT); - - while (!clients[currentMaxClients - 1]) - currentMaxClients--; - } -} - -static void -KillAllClients(void) -{ - int i; - - for (i = 1; i < currentMaxClients; i++) - if (clients[i]) { - /* Make sure Retained clients are released. */ - clients[i]->closeDownMode = DestroyAll; - CloseDownClient(clients[i]); - } -} - -void -InitClient(ClientPtr client, int i, void *ospriv) -{ - client->index = i; - client->clientAsMask = ((Mask) i) << CLIENTOFFSET; - client->closeDownMode = i ? DestroyAll : RetainPermanent; - client->requestVector = InitialVector; - client->osPrivate = ospriv; - QueryMinMaxKeyCodes(&client->minKC, &client->maxKC); - client->smart_start_tick = SmartScheduleTime; - client->smart_stop_tick = SmartScheduleTime; - client->clientIds = NULL; -} - -/************************ - * int NextAvailableClient(ospriv) - * - * OS dependent portion can't assign client id's because of CloseDownModes. - * Returns NULL if there are no free clients. - *************************/ - -ClientPtr -NextAvailableClient(void *ospriv) -{ - int i; - ClientPtr client; - xReq data; - - i = nextFreeClientID; - if (i == MAXCLIENTS) - return (ClientPtr) NULL; - clients[i] = client = - dixAllocateObjectWithPrivates(ClientRec, PRIVATE_CLIENT); - if (!client) - return (ClientPtr) NULL; - InitClient(client, i, ospriv); - if (!InitClientResources(client)) { - dixFreeObjectWithPrivates(client, PRIVATE_CLIENT); - return (ClientPtr) NULL; - } - data.reqType = 1; - data.length = bytes_to_int32(sz_xReq + sz_xConnClientPrefix); - if (!InsertFakeRequest(client, (char *) &data, sz_xReq)) { - FreeClientResources(client); - dixFreeObjectWithPrivates(client, PRIVATE_CLIENT); - return (ClientPtr) NULL; - } - if (i == currentMaxClients) - currentMaxClients++; - while ((nextFreeClientID < MAXCLIENTS) && clients[nextFreeClientID]) - nextFreeClientID++; - - /* Enable client ID tracking. This must be done before - * ClientStateCallback. */ - ReserveClientIds(client); - - if (ClientStateCallback) { - NewClientInfoRec clientinfo; - - clientinfo.client = client; - clientinfo.prefix = (xConnSetupPrefix *) NULL; - clientinfo.setup = (xConnSetup *) NULL; - CallCallbacks((&ClientStateCallback), (void *) &clientinfo); - } - return client; -} - -int -ProcInitialConnection(ClientPtr client) -{ - REQUEST(xReq); - xConnClientPrefix *prefix; - int whichbyte = 1; - char order; - - prefix = (xConnClientPrefix *) ((char *)stuff + sz_xReq); - order = prefix->byteOrder; - if (order != 'l' && order != 'B' && order != 'r' && order != 'R') - return client->noClientException = -1; - if (((*(char *) &whichbyte) && (order == 'B' || order == 'R')) || - (!(*(char *) &whichbyte) && (order == 'l' || order == 'r'))) { - client->swapped = TRUE; - SwapConnClientPrefix(prefix); - } - stuff->reqType = 2; - stuff->length += bytes_to_int32(prefix->nbytesAuthProto) + - bytes_to_int32(prefix->nbytesAuthString); - if (client->swapped) { - swaps(&stuff->length); - } - if (order == 'r' || order == 'R') { - client->local = FALSE; - } - ResetCurrentRequest(client); - return Success; -} - -static int -SendConnSetup(ClientPtr client, const char *reason) -{ - xWindowRoot *root; - int i; - int numScreens; - char *lConnectionInfo; - xConnSetupPrefix *lconnSetupPrefix; - - if (reason) { - xConnSetupPrefix csp; - - csp.success = xFalse; - csp.lengthReason = strlen(reason); - csp.length = bytes_to_int32(csp.lengthReason); - csp.majorVersion = X_PROTOCOL; - csp.minorVersion = X_PROTOCOL_REVISION; - if (client->swapped) - WriteSConnSetupPrefix(client, &csp); - else - WriteToClient(client, sz_xConnSetupPrefix, &csp); - WriteToClient(client, (int) csp.lengthReason, reason); - return client->noClientException = -1; - } - - numScreens = screenInfo.numScreens; - lConnectionInfo = ConnectionInfo; - lconnSetupPrefix = &connSetupPrefix; - - /* We're about to start speaking X protocol back to the client by - * sending the connection setup info. This means the authorization - * step is complete, and we can count the client as an - * authorized one. - */ - nClients++; - - client->requestVector = client->swapped ? SwappedProcVector : ProcVector; - client->sequence = 0; - ((xConnSetup *) lConnectionInfo)->ridBase = client->clientAsMask; - ((xConnSetup *) lConnectionInfo)->ridMask = RESOURCE_ID_MASK; -#ifdef MATCH_CLIENT_ENDIAN - ((xConnSetup *) lConnectionInfo)->imageByteOrder = ClientOrder(client); - ((xConnSetup *) lConnectionInfo)->bitmapBitOrder = ClientOrder(client); -#endif - /* fill in the "currentInputMask" */ - root = (xWindowRoot *) (lConnectionInfo + connBlockScreenStart); -#ifdef PANORAMIX - if (noPanoramiXExtension) - numScreens = screenInfo.numScreens; - else - numScreens = ((xConnSetup *) ConnectionInfo)->numRoots; -#endif - - for (i = 0; i < numScreens; i++) { - unsigned int j; - xDepth *pDepth; - WindowPtr pRoot = screenInfo.screens[i]->root; - - root->currentInputMask = pRoot->eventMask | wOtherEventMasks(pRoot); - pDepth = (xDepth *) (root + 1); - for (j = 0; j < root->nDepths; j++) { - pDepth = (xDepth *) (((char *) (pDepth + 1)) + - pDepth->nVisuals * sizeof(xVisualType)); - } - root = (xWindowRoot *) pDepth; - } - - if (client->swapped) { - WriteSConnSetupPrefix(client, lconnSetupPrefix); - WriteSConnectionInfo(client, - (unsigned long) (lconnSetupPrefix->length << 2), - lConnectionInfo); - } - else { - WriteToClient(client, sizeof(xConnSetupPrefix), lconnSetupPrefix); - WriteToClient(client, (int) (lconnSetupPrefix->length << 2), - lConnectionInfo); - } - client->clientState = ClientStateRunning; - if (ClientStateCallback) { - NewClientInfoRec clientinfo; - - clientinfo.client = client; - clientinfo.prefix = lconnSetupPrefix; - clientinfo.setup = (xConnSetup *) lConnectionInfo; - CallCallbacks((&ClientStateCallback), (void *) &clientinfo); - } - return Success; -} - -int -ProcEstablishConnection(ClientPtr client) -{ - const char *reason; - char *auth_proto, *auth_string; - xConnClientPrefix *prefix; - - REQUEST(xReq); - - prefix = (xConnClientPrefix *) ((char *) stuff + sz_xReq); - auth_proto = (char *) prefix + sz_xConnClientPrefix; - auth_string = auth_proto + pad_to_int32(prefix->nbytesAuthProto); - if ((prefix->majorVersion != X_PROTOCOL) || - (prefix->minorVersion != X_PROTOCOL_REVISION)) - reason = "Protocol version mismatch"; - else - reason = ClientAuthorized(client, - (unsigned short) prefix->nbytesAuthProto, - auth_proto, - (unsigned short) prefix->nbytesAuthString, - auth_string); - - return (SendConnSetup(client, reason)); -} - -void -SendErrorToClient(ClientPtr client, unsigned majorCode, unsigned minorCode, - XID resId, int errorCode) -{ - xError rep = { - .type = X_Error, - .errorCode = errorCode, - .resourceID = resId, - .minorCode = minorCode, - .majorCode = majorCode - }; - - WriteEventsToClient(client, 1, (xEvent *) &rep); -} - -void -MarkClientException(ClientPtr client) -{ - client->noClientException = -1; -} - -/* - * This array encodes the answer to the question "what is the log base 2 - * of the number of pixels that fit in a scanline pad unit?" - * Note that ~0 is an invalid entry (mostly for the benefit of the reader). - */ -static int answer[6][4] = { - /* pad pad pad pad */ - /* 8 16 32 64 */ - - {3, 4, 5, 6}, /* 1 bit per pixel */ - {1, 2, 3, 4}, /* 4 bits per pixel */ - {0, 1, 2, 3}, /* 8 bits per pixel */ - {~0, 0, 1, 2}, /* 16 bits per pixel */ - {~0, ~0, 0, 1}, /* 24 bits per pixel */ - {~0, ~0, 0, 1} /* 32 bits per pixel */ -}; - -/* - * This array gives the answer to the question "what is the first index for - * the answer array above given the number of bits per pixel?" - * Note that ~0 is an invalid entry (mostly for the benefit of the reader). - */ -static int indexForBitsPerPixel[33] = { - ~0, 0, ~0, ~0, /* 1 bit per pixel */ - 1, ~0, ~0, ~0, /* 4 bits per pixel */ - 2, ~0, ~0, ~0, /* 8 bits per pixel */ - ~0, ~0, ~0, ~0, - 3, ~0, ~0, ~0, /* 16 bits per pixel */ - ~0, ~0, ~0, ~0, - 4, ~0, ~0, ~0, /* 24 bits per pixel */ - ~0, ~0, ~0, ~0, - 5 /* 32 bits per pixel */ -}; - -/* - * This array gives the bytesperPixel value for cases where the number - * of bits per pixel is a multiple of 8 but not a power of 2. - */ -static int answerBytesPerPixel[33] = { - ~0, 0, ~0, ~0, /* 1 bit per pixel */ - 0, ~0, ~0, ~0, /* 4 bits per pixel */ - 0, ~0, ~0, ~0, /* 8 bits per pixel */ - ~0, ~0, ~0, ~0, - 0, ~0, ~0, ~0, /* 16 bits per pixel */ - ~0, ~0, ~0, ~0, - 3, ~0, ~0, ~0, /* 24 bits per pixel */ - ~0, ~0, ~0, ~0, - 0 /* 32 bits per pixel */ -}; - -/* - * This array gives the answer to the question "what is the second index for - * the answer array above given the number of bits per scanline pad unit?" - * Note that ~0 is an invalid entry (mostly for the benefit of the reader). - */ -static int indexForScanlinePad[65] = { - ~0, ~0, ~0, ~0, - ~0, ~0, ~0, ~0, - 0, ~0, ~0, ~0, /* 8 bits per scanline pad unit */ - ~0, ~0, ~0, ~0, - 1, ~0, ~0, ~0, /* 16 bits per scanline pad unit */ - ~0, ~0, ~0, ~0, - ~0, ~0, ~0, ~0, - ~0, ~0, ~0, ~0, - 2, ~0, ~0, ~0, /* 32 bits per scanline pad unit */ - ~0, ~0, ~0, ~0, - ~0, ~0, ~0, ~0, - ~0, ~0, ~0, ~0, - ~0, ~0, ~0, ~0, - ~0, ~0, ~0, ~0, - ~0, ~0, ~0, ~0, - ~0, ~0, ~0, ~0, - 3 /* 64 bits per scanline pad unit */ -}; - -/* - grow the array of screenRecs if necessary. - call the device-supplied initialization procedure -with its screen number, a pointer to its ScreenRec, argc, and argv. - return the number of successfully installed screens. - -*/ - -static int init_screen(ScreenPtr pScreen, int i, Bool gpu) -{ - int scanlinepad, format, depth, bitsPerPixel, j, k; - - dixInitScreenSpecificPrivates(pScreen); - - if (!dixAllocatePrivates(&pScreen->devPrivates, PRIVATE_SCREEN)) { - return -1; - } - pScreen->myNum = i; - if (gpu) { - pScreen->myNum += GPU_SCREEN_OFFSET; - pScreen->isGPU = TRUE; - } - pScreen->totalPixmapSize = 0; /* computed in CreateScratchPixmapForScreen */ - pScreen->ClipNotify = 0; /* for R4 ddx compatibility */ - pScreen->CreateScreenResources = 0; - - xorg_list_init(&pScreen->pixmap_dirty_list); - xorg_list_init(&pScreen->unattached_list); - xorg_list_init(&pScreen->output_slave_list); - xorg_list_init(&pScreen->offload_slave_list); - - /* - * This loop gets run once for every Screen that gets added, - * but thats ok. If the ddx layer initializes the formats - * one at a time calling AddScreen() after each, then each - * iteration will make it a little more accurate. Worst case - * we do this loop N * numPixmapFormats where N is # of screens. - * Anyway, this must be called after InitOutput and before the - * screen init routine is called. - */ - for (format = 0; format < screenInfo.numPixmapFormats; format++) { - depth = screenInfo.formats[format].depth; - bitsPerPixel = screenInfo.formats[format].bitsPerPixel; - scanlinepad = screenInfo.formats[format].scanlinePad; - j = indexForBitsPerPixel[bitsPerPixel]; - k = indexForScanlinePad[scanlinepad]; - PixmapWidthPaddingInfo[depth].padPixelsLog2 = answer[j][k]; - PixmapWidthPaddingInfo[depth].padRoundUp = - (scanlinepad / bitsPerPixel) - 1; - j = indexForBitsPerPixel[8]; /* bits per byte */ - PixmapWidthPaddingInfo[depth].padBytesLog2 = answer[j][k]; - PixmapWidthPaddingInfo[depth].bitsPerPixel = bitsPerPixel; - if (answerBytesPerPixel[bitsPerPixel]) { - PixmapWidthPaddingInfo[depth].notPower2 = 1; - PixmapWidthPaddingInfo[depth].bytesPerPixel = - answerBytesPerPixel[bitsPerPixel]; - } - else { - PixmapWidthPaddingInfo[depth].notPower2 = 0; - } - } - return 0; -} - -int -AddScreen(Bool (*pfnInit) (ScreenPtr /*pScreen */ , - int /*argc */ , - char ** /*argv */ - ), int argc, char **argv) -{ - - int i; - ScreenPtr pScreen; - Bool ret; - - i = screenInfo.numScreens; - if (i == MAXSCREENS) - return -1; - - pScreen = (ScreenPtr) calloc(1, sizeof(ScreenRec)); - if (!pScreen) - return -1; - - ret = init_screen(pScreen, i, FALSE); - if (ret != 0) { - free(pScreen); - return ret; - } - /* This is where screen specific stuff gets initialized. Load the - screen structure, call the hardware, whatever. - This is also where the default colormap should be allocated and - also pixel values for blackPixel, whitePixel, and the cursor - Note that InitScreen is NOT allowed to modify argc, argv, or - any of the strings pointed to by argv. They may be passed to - multiple screens. - */ - screenInfo.screens[i] = pScreen; - screenInfo.numScreens++; - if (!(*pfnInit) (pScreen, argc, argv)) { - dixFreeScreenSpecificPrivates(pScreen); - dixFreePrivates(pScreen->devPrivates, PRIVATE_SCREEN); - free(pScreen); - screenInfo.numScreens--; - return -1; - } - - update_desktop_dimensions(); - - dixRegisterScreenPrivateKey(&cursorScreenDevPriv, pScreen, PRIVATE_CURSOR, - 0); - - return i; -} - -int -AddGPUScreen(Bool (*pfnInit) (ScreenPtr /*pScreen */ , - int /*argc */ , - char ** /*argv */ - ), - int argc, char **argv) -{ - int i; - ScreenPtr pScreen; - Bool ret; - - i = screenInfo.numGPUScreens; - if (i == MAXGPUSCREENS) - return -1; - - pScreen = (ScreenPtr) calloc(1, sizeof(ScreenRec)); - if (!pScreen) - return -1; - - ret = init_screen(pScreen, i, TRUE); - if (ret != 0) { - free(pScreen); - return ret; - } - - /* This is where screen specific stuff gets initialized. Load the - screen structure, call the hardware, whatever. - This is also where the default colormap should be allocated and - also pixel values for blackPixel, whitePixel, and the cursor - Note that InitScreen is NOT allowed to modify argc, argv, or - any of the strings pointed to by argv. They may be passed to - multiple screens. - */ - screenInfo.gpuscreens[i] = pScreen; - screenInfo.numGPUScreens++; - if (!(*pfnInit) (pScreen, argc, argv)) { - dixFreePrivates(pScreen->devPrivates, PRIVATE_SCREEN); - free(pScreen); - screenInfo.numGPUScreens--; - return -1; - } - - update_desktop_dimensions(); - - return i; -} - -void -RemoveGPUScreen(ScreenPtr pScreen) -{ - int idx, j; - if (!pScreen->isGPU) - return; - - idx = pScreen->myNum - GPU_SCREEN_OFFSET; - for (j = idx; j < screenInfo.numGPUScreens - 1; j++) { - screenInfo.gpuscreens[j] = screenInfo.gpuscreens[j + 1]; - screenInfo.gpuscreens[j]->myNum = j + GPU_SCREEN_OFFSET; - } - screenInfo.numGPUScreens--; - - /* this gets freed later in the resource list, but without - * the screen existing it causes crashes - so remove it here */ - if (pScreen->defColormap) - FreeResource(pScreen->defColormap, RT_COLORMAP); - free(pScreen); - -} - -void -AttachUnboundGPU(ScreenPtr pScreen, ScreenPtr new) -{ - assert(new->isGPU); - assert(!new->current_master); - xorg_list_add(&new->unattached_head, &pScreen->unattached_list); - new->current_master = pScreen; -} - -void -DetachUnboundGPU(ScreenPtr slave) -{ - assert(slave->isGPU); - xorg_list_del(&slave->unattached_head); - slave->current_master = NULL; -} - -void -AttachOutputGPU(ScreenPtr pScreen, ScreenPtr new) -{ - assert(new->isGPU); - xorg_list_add(&new->output_head, &pScreen->output_slave_list); - new->current_master = pScreen; -} - -void -DetachOutputGPU(ScreenPtr slave) -{ - assert(slave->isGPU); - xorg_list_del(&slave->output_head); - slave->current_master = NULL; -} - -void -AttachOffloadGPU(ScreenPtr pScreen, ScreenPtr new) -{ - assert(new->isGPU); - xorg_list_add(&new->offload_head, &pScreen->offload_slave_list); - new->current_master = pScreen; -} - -void -DetachOffloadGPU(ScreenPtr slave) -{ - assert(slave->isGPU); - xorg_list_del(&slave->offload_head); - slave->current_master = NULL; -} - +/************************************************************
+
+Copyright 1987, 1989, 1998 The Open Group
+
+Permission to use, copy, modify, distribute, and sell this software and its
+documentation for any purpose is hereby granted without fee, provided that
+the above copyright notice appear in all copies and that both that
+copyright notice and this permission notice appear in supporting
+documentation.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
+AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
+CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of The Open Group shall not be
+used in advertising or otherwise to promote the sale, use or other dealings
+in this Software without prior written authorization from The Open Group.
+
+Copyright 1987, 1989 by Digital Equipment Corporation, Maynard, Massachusetts.
+
+ All Rights Reserved
+
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
+provided that the above copyright notice appear in all copies and that
+both that copyright notice and this permission notice appear in
+supporting documentation, and that the name of Digital not be
+used in advertising or publicity pertaining to distribution of the
+software without specific, written prior permission.
+
+DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
+ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
+DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
+ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
+WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
+ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
+SOFTWARE.
+
+********************************************************/
+
+/* The panoramix components contained the following notice */
+/*****************************************************************
+
+Copyright (c) 1991, 1997 Digital Equipment Corporation, Maynard, Massachusetts.
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software.
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+DIGITAL EQUIPMENT CORPORATION BE LIABLE FOR ANY CLAIM, DAMAGES, INCLUDING,
+BUT NOT LIMITED TO CONSEQUENTIAL OR INCIDENTAL DAMAGES, OR OTHER LIABILITY,
+WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR
+IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+
+Except as contained in this notice, the name of Digital Equipment Corporation
+shall not be used in advertising or otherwise to promote the sale, use or other
+dealings in this Software without prior written authorization from Digital
+Equipment Corporation.
+
+******************************************************************/
+
+/* XSERVER_DTRACE additions:
+ * Copyright (c) 2005-2006, Oracle and/or its affiliates. All rights reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the "Software"),
+ * to deal in the Software without restriction, including without limitation
+ * the rights to use, copy, modify, merge, publish, distribute, sublicense,
+ * and/or sell copies of the Software, and to permit persons to whom the
+ * Software is furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the next
+ * paragraph) shall be included in all copies or substantial portions of the
+ * Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
+ * DEALINGS IN THE SOFTWARE.
+ */
+
+#ifdef HAVE_DIX_CONFIG_H
+#include <dix-config.h>
+#include <version-config.h>
+#endif
+
+#ifdef CreateWindow
+#undef CreateWindow
+#endif
+
+#ifdef PANORAMIX_DEBUG
+#include <stdio.h>
+int ProcInitialConnection();
+#endif
+
+#include "windowstr.h"
+#include <X11/fonts/fontstruct.h>
+#include "dixfontstr.h"
+#include "gcstruct.h"
+#include "selection.h"
+#include "colormapst.h"
+#include "cursorstr.h"
+#include "scrnintstr.h"
+#include "opaque.h"
+#include "input.h"
+#include "servermd.h"
+#include "extnsionst.h"
+#include "dixfont.h"
+#include "dispatch.h"
+#include "swaprep.h"
+#include "swapreq.h"
+#include "privates.h"
+#include "xace.h"
+#include "inputstr.h"
+#include "xkbsrv.h"
+#include "site.h"
+#include "client.h"
+
+#ifdef XSERVER_DTRACE
+#include "registry.h"
+#include <sys/types.h>
+typedef const char *string;
+
+#include "Xserver-dtrace.h"
+#endif
+
+#define mskcnt ((MAXCLIENTS + 31) / 32)
+#define BITMASK(i) (1U << ((i) & 31))
+#define MASKIDX(i) ((i) >> 5)
+#define MASKWORD(buf, i) buf[MASKIDX(i)]
+#define BITSET(buf, i) MASKWORD(buf, i) |= BITMASK(i)
+#define BITCLEAR(buf, i) MASKWORD(buf, i) &= ~BITMASK(i)
+#define GETBIT(buf, i) (MASKWORD(buf, i) & BITMASK(i))
+
+xConnSetupPrefix connSetupPrefix;
+
+PaddingInfo PixmapWidthPaddingInfo[33];
+
+static ClientPtr grabClient;
+
+#define GrabNone 0
+#define GrabActive 1
+#define GrabKickout 2
+static int grabState = GrabNone;
+static long grabWaiters[mskcnt];
+CallbackListPtr ServerGrabCallback = NULL;
+HWEventQueuePtr checkForInput[2];
+int connBlockScreenStart;
+
+static void KillAllClients(void);
+
+static int nextFreeClientID; /* always MIN free client ID */
+
+static int nClients; /* number of authorized clients */
+
+CallbackListPtr ClientStateCallback;
+
+/* dispatchException & isItTimeToYield must be declared volatile since they
+ * are modified by signal handlers - otherwise optimizer may assume it doesn't
+ * need to actually check value in memory when used and may miss changes from
+ * signal handlers.
+ */
+volatile char dispatchException = 0;
+volatile char isItTimeToYield;
+
+#define SAME_SCREENS(a, b) (\
+ (a.pScreen == b.pScreen))
+
+void
+SetInputCheck(HWEventQueuePtr c0, HWEventQueuePtr c1)
+{
+ checkForInput[0] = c0;
+ checkForInput[1] = c1;
+}
+
+void
+UpdateCurrentTime(void)
+{
+ TimeStamp systime;
+
+ /* To avoid time running backwards, we must call GetTimeInMillis before
+ * calling ProcessInputEvents.
+ */
+ systime.months = currentTime.months;
+ systime.milliseconds = GetTimeInMillis();
+ if (systime.milliseconds < currentTime.milliseconds)
+ systime.months++;
+ if (*checkForInput[0] != *checkForInput[1])
+ ProcessInputEvents();
+ if (CompareTimeStamps(systime, currentTime) == LATER)
+ currentTime = systime;
+}
+
+/* Like UpdateCurrentTime, but can't call ProcessInputEvents */
+void
+UpdateCurrentTimeIf(void)
+{
+ TimeStamp systime;
+
+ systime.months = currentTime.months;
+ systime.milliseconds = GetTimeInMillis();
+ if (systime.milliseconds < currentTime.milliseconds)
+ systime.months++;
+ if (CompareTimeStamps(systime, currentTime) == LATER)
+ currentTime = systime;
+}
+
+#undef SMART_DEBUG
+
+/* in milliseconds */
+#define SMART_SCHEDULE_DEFAULT_INTERVAL 5
+#define SMART_SCHEDULE_MAX_SLICE 15
+
+#if defined(WIN32) && !defined(__CYGWIN__) && !defined(_MSC_VER)
+Bool SmartScheduleDisable = TRUE;
+#else
+Bool SmartScheduleDisable = FALSE;
+#endif
+long SmartScheduleSlice = SMART_SCHEDULE_DEFAULT_INTERVAL;
+long SmartScheduleInterval = SMART_SCHEDULE_DEFAULT_INTERVAL;
+long SmartScheduleMaxSlice = SMART_SCHEDULE_MAX_SLICE;
+long SmartScheduleTime;
+int SmartScheduleLatencyLimited = 0;
+static ClientPtr SmartLastClient;
+static int SmartLastIndex[SMART_MAX_PRIORITY - SMART_MIN_PRIORITY + 1];
+
+#ifdef SMART_DEBUG
+long SmartLastPrint;
+#endif
+
+void Dispatch(void);
+
+static int
+SmartScheduleClient(int *clientReady, int nready)
+{
+ ClientPtr pClient;
+ int i;
+ int client;
+ int bestPrio, best = 0;
+ int bestRobin, robin;
+ long now = SmartScheduleTime;
+ long idle;
+
+ bestPrio = -0x7fffffff;
+ bestRobin = 0;
+ idle = 2 * SmartScheduleSlice;
+ for (i = 0; i < nready; i++) {
+ client = clientReady[i];
+ pClient = clients[client];
+ /* Praise clients which haven't run in a while */
+ if ((now - pClient->smart_stop_tick) >= idle) {
+ if (pClient->smart_priority < 0)
+ pClient->smart_priority++;
+ }
+
+ /* check priority to select best client */
+ robin =
+ (pClient->index -
+ SmartLastIndex[pClient->smart_priority -
+ SMART_MIN_PRIORITY]) & 0xff;
+ if (pClient->smart_priority > bestPrio ||
+ (pClient->smart_priority == bestPrio && robin > bestRobin)) {
+ bestPrio = pClient->smart_priority;
+ bestRobin = robin;
+ best = client;
+ }
+#ifdef SMART_DEBUG
+ if ((now - SmartLastPrint) >= 5000)
+ fprintf(stderr, " %2d: %3d", client, pClient->smart_priority);
+#endif
+ }
+#ifdef SMART_DEBUG
+ if ((now - SmartLastPrint) >= 5000) {
+ fprintf(stderr, " use %2d\n", best);
+ SmartLastPrint = now;
+ }
+#endif
+ pClient = clients[best];
+ SmartLastIndex[bestPrio - SMART_MIN_PRIORITY] = pClient->index;
+ /*
+ * Set current client pointer
+ */
+ if (SmartLastClient != pClient) {
+ pClient->smart_start_tick = now;
+ SmartLastClient = pClient;
+ }
+ /*
+ * Adjust slice
+ */
+ if (nready == 1 && SmartScheduleLatencyLimited == 0) {
+ /*
+ * If it's been a long time since another client
+ * has run, bump the slice up to get maximal
+ * performance from a single client
+ */
+ if ((now - pClient->smart_start_tick) > 1000 &&
+ SmartScheduleSlice < SmartScheduleMaxSlice) {
+ SmartScheduleSlice += SmartScheduleInterval;
+ }
+ }
+ else {
+ SmartScheduleSlice = SmartScheduleInterval;
+ }
+ return best;
+}
+
+void
+EnableLimitedSchedulingLatency(void)
+{
+ ++SmartScheduleLatencyLimited;
+ SmartScheduleSlice = SmartScheduleInterval;
+}
+
+void
+DisableLimitedSchedulingLatency(void)
+{
+ --SmartScheduleLatencyLimited;
+
+ /* protect against bugs */
+ if (SmartScheduleLatencyLimited < 0)
+ SmartScheduleLatencyLimited = 0;
+}
+
+void
+Dispatch(void)
+{
+ int *clientReady; /* array of request ready clients */
+ int result;
+ ClientPtr client;
+ int nready;
+ HWEventQueuePtr *icheck = checkForInput;
+ long start_tick;
+
+ nextFreeClientID = 1;
+ nClients = 0;
+
+ clientReady = malloc(sizeof(int) * MaxClients);
+ if (!clientReady)
+ return;
+
+ SmartScheduleSlice = SmartScheduleInterval;
+ while (!dispatchException) {
+ if (*icheck[0] != *icheck[1]) {
+ ProcessInputEvents();
+ FlushIfCriticalOutputPending();
+ }
+
+ nready = WaitForSomething(clientReady);
+
+ if (nready && !SmartScheduleDisable) {
+ clientReady[0] = SmartScheduleClient(clientReady, nready);
+ nready = 1;
+ }
+ /*****************
+ * Handle events in round robin fashion, doing input between
+ * each round
+ *****************/
+
+ while (!dispatchException && (--nready >= 0)) {
+ client = clients[clientReady[nready]];
+ if (!client) {
+ /* KillClient can cause this to happen */
+ continue;
+ }
+ /* GrabServer activation can cause this to be true */
+ if (grabState == GrabKickout) {
+ grabState = GrabActive;
+ break;
+ }
+ isItTimeToYield = FALSE;
+
+ start_tick = SmartScheduleTime;
+ while (!isItTimeToYield) {
+#ifdef XSERVER_DTRACE
+ CARD8 StartMajorOp;
+#endif
+ if (*icheck[0] != *icheck[1])
+ ProcessInputEvents();
+
+ FlushIfCriticalOutputPending();
+ if (!SmartScheduleDisable &&
+ (SmartScheduleTime - start_tick) >= SmartScheduleSlice) {
+ /* Penalize clients which consume ticks */
+ if (client->smart_priority > SMART_MIN_PRIORITY)
+ client->smart_priority--;
+ break;
+ }
+ /* now, finally, deal with client requests */
+
+ /* Update currentTime so request time checks, such as for input
+ * device grabs, are calculated correctly */
+ UpdateCurrentTimeIf();
+ result = ReadRequestFromClient(client);
+ if (result <= 0) {
+ if (result < 0)
+ CloseDownClient(client);
+ break;
+ }
+
+ client->sequence++;
+ client->majorOp = ((xReq *) client->requestBuffer)->reqType;
+ client->minorOp = 0;
+ if (client->majorOp >= EXTENSION_BASE) {
+ ExtensionEntry *ext = GetExtensionEntry(client->majorOp);
+
+ if (ext)
+ client->minorOp = ext->MinorOpcode(client);
+ }
+#ifdef XSERVER_DTRACE
+ if (XSERVER_REQUEST_START_ENABLED())
+ {
+ StartMajorOp=client->majorOp;
+ XSERVER_REQUEST_START(LookupMajorName(client->majorOp),
+ client->majorOp,
+ ((xReq *) client->requestBuffer)->length,
+ client->index,
+ client->requestBuffer);
+ }
+#endif
+ if (result > (maxBigRequestSize << 2))
+ result = BadLength;
+ else {
+ result = XaceHookDispatch(client, client->majorOp);
+ if (result == Success)
+ result =
+ (*client->requestVector[client->majorOp]) (client);
+ XaceHookAuditEnd(client, result);
+ }
+#ifdef XSERVER_DTRACE
+ if (XSERVER_REQUEST_DONE_ENABLED())
+ {
+ if (result!=Success)
+ {
+ char Message[255];
+ sprintf(Message,"ERROR: %s (0x%x)",LookupMajorName(client->majorOp),client->errorValue);
+ XSERVER_REQUEST_DONE(Message,
+ client->majorOp, client->sequence,
+ client->index, result);
+ }
+ else
+ {
+ if (StartMajorOp!=client->majorOp)
+ {
+ char Message[255];
+ sprintf(Message,"Changed request: %s -> %s",LookupMajorName(StartMajorOp),LookupMajorName(client->majorOp));
+ XSERVER_REQUEST_DONE(Message,
+ client->majorOp, client->sequence,
+ client->index, result);
+ }
+ else
+ {
+ XSERVER_REQUEST_DONE(LookupMajorName(client->majorOp),
+ client->majorOp, client->sequence,
+ client->index, result);
+ }
+ }
+ }
+#endif
+
+ if (client->noClientException != Success) {
+ CloseDownClient(client);
+ break;
+ }
+ else if (result != Success) {
+ SendErrorToClient(client, client->majorOp,
+ client->minorOp,
+ client->errorValue, result);
+ break;
+ }
+ }
+ FlushAllOutput();
+ client = clients[clientReady[nready]];
+ if (client)
+ client->smart_stop_tick = SmartScheduleTime;
+ }
+ dispatchException &= ~DE_PRIORITYCHANGE;
+ }
+#if defined(DDXBEFORERESET)
+ ddxBeforeReset();
+#endif
+ KillAllClients();
+ free(clientReady);
+ dispatchException &= ~DE_RESET;
+ SmartScheduleLatencyLimited = 0;
+ ResetOsBuffers();
+}
+
+static int VendorRelease = VENDOR_RELEASE;
+static const char *VendorString = VENDOR_NAME;
+
+void
+SetVendorRelease(int release)
+{
+ VendorRelease = release;
+}
+
+void
+SetVendorString(const char *vendor)
+{
+ VendorString = vendor;
+}
+
+Bool
+CreateConnectionBlock(void)
+{
+ xConnSetup setup;
+ xWindowRoot root;
+ xDepth depth;
+ xVisualType visual;
+ xPixmapFormat format;
+ unsigned long vid;
+ int i, j, k, lenofblock, sizesofar = 0;
+ char *pBuf;
+
+ memset(&setup, 0, sizeof(xConnSetup));
+ /* Leave off the ridBase and ridMask, these must be sent with
+ connection */
+
+ setup.release = VendorRelease;
+ /*
+ * per-server image and bitmap parameters are defined in Xmd.h
+ */
+ setup.imageByteOrder = screenInfo.imageByteOrder;
+
+ setup.bitmapScanlineUnit = screenInfo.bitmapScanlineUnit;
+ setup.bitmapScanlinePad = screenInfo.bitmapScanlinePad;
+
+ setup.bitmapBitOrder = screenInfo.bitmapBitOrder;
+ setup.motionBufferSize = NumMotionEvents();
+ setup.numRoots = screenInfo.numScreens;
+ setup.nbytesVendor = strlen(VendorString);
+ setup.numFormats = screenInfo.numPixmapFormats;
+ setup.maxRequestSize = MAX_REQUEST_SIZE;
+ QueryMinMaxKeyCodes(&setup.minKeyCode, &setup.maxKeyCode);
+
+ lenofblock = sizeof(xConnSetup) +
+ pad_to_int32(setup.nbytesVendor) +
+ (setup.numFormats * sizeof(xPixmapFormat)) +
+ (setup.numRoots * sizeof(xWindowRoot));
+ ConnectionInfo = malloc(lenofblock);
+ if (!ConnectionInfo)
+ return FALSE;
+
+ memmove(ConnectionInfo, (char *) &setup, sizeof(xConnSetup));
+ sizesofar = sizeof(xConnSetup);
+ pBuf = ConnectionInfo + sizeof(xConnSetup);
+
+ memmove(pBuf, VendorString, (int) setup.nbytesVendor);
+ sizesofar += setup.nbytesVendor;
+ pBuf += setup.nbytesVendor;
+ i = padding_for_int32(setup.nbytesVendor);
+ sizesofar += i;
+ while (--i >= 0)
+ *pBuf++ = 0;
+
+ memset(&format, 0, sizeof(xPixmapFormat));
+ for (i = 0; i < screenInfo.numPixmapFormats; i++) {
+ format.depth = screenInfo.formats[i].depth;
+ format.bitsPerPixel = screenInfo.formats[i].bitsPerPixel;
+ format.scanLinePad = screenInfo.formats[i].scanlinePad;
+ memmove(pBuf, (char *) &format, sizeof(xPixmapFormat));
+ pBuf += sizeof(xPixmapFormat);
+ sizesofar += sizeof(xPixmapFormat);
+ }
+
+ connBlockScreenStart = sizesofar;
+ memset(&depth, 0, sizeof(xDepth));
+ memset(&visual, 0, sizeof(xVisualType));
+ for (i = 0; i < screenInfo.numScreens; i++) {
+ ScreenPtr pScreen;
+ DepthPtr pDepth;
+ VisualPtr pVisual;
+
+ pScreen = screenInfo.screens[i];
+ root.windowId = pScreen->root->drawable.id;
+ root.defaultColormap = pScreen->defColormap;
+ root.whitePixel = pScreen->whitePixel;
+ root.blackPixel = pScreen->blackPixel;
+ root.currentInputMask = 0; /* filled in when sent */
+ root.pixWidth = pScreen->width;
+ root.pixHeight = pScreen->height;
+ root.mmWidth = pScreen->mmWidth;
+ root.mmHeight = pScreen->mmHeight;
+ root.minInstalledMaps = pScreen->minInstalledCmaps;
+ root.maxInstalledMaps = pScreen->maxInstalledCmaps;
+ root.rootVisualID = pScreen->rootVisual;
+ root.backingStore = pScreen->backingStoreSupport;
+ root.saveUnders = FALSE;
+ root.rootDepth = pScreen->rootDepth;
+ root.nDepths = pScreen->numDepths;
+ memmove(pBuf, (char *) &root, sizeof(xWindowRoot));
+ sizesofar += sizeof(xWindowRoot);
+ pBuf += sizeof(xWindowRoot);
+
+ pDepth = pScreen->allowedDepths;
+ for (j = 0; j < pScreen->numDepths; j++, pDepth++) {
+ lenofblock += sizeof(xDepth) +
+ (pDepth->numVids * sizeof(xVisualType));
+ pBuf = (char *) realloc(ConnectionInfo, lenofblock);
+ if (!pBuf) {
+ free(ConnectionInfo);
+ return FALSE;
+ }
+ ConnectionInfo = pBuf;
+ pBuf += sizesofar;
+ depth.depth = pDepth->depth;
+ depth.nVisuals = pDepth->numVids;
+ memmove(pBuf, (char *) &depth, sizeof(xDepth));
+ pBuf += sizeof(xDepth);
+ sizesofar += sizeof(xDepth);
+ for (k = 0; k < pDepth->numVids; k++) {
+ vid = pDepth->vids[k];
+ for (pVisual = pScreen->visuals;
+ pVisual->vid != vid; pVisual++);
+ visual.visualID = vid;
+ visual.class = pVisual->class;
+ visual.bitsPerRGB = pVisual->bitsPerRGBValue;
+ visual.colormapEntries = pVisual->ColormapEntries;
+ visual.redMask = pVisual->redMask;
+ visual.greenMask = pVisual->greenMask;
+ visual.blueMask = pVisual->blueMask;
+ memmove(pBuf, (char *) &visual, sizeof(xVisualType));
+ pBuf += sizeof(xVisualType);
+ sizesofar += sizeof(xVisualType);
+ }
+ }
+ }
+ connSetupPrefix.success = xTrue;
+ connSetupPrefix.length = lenofblock / 4;
+ connSetupPrefix.majorVersion = X_PROTOCOL;
+ connSetupPrefix.minorVersion = X_PROTOCOL_REVISION;
+ return TRUE;
+}
+
+int
+ProcBadRequest(ClientPtr client)
+{
+ return BadRequest;
+}
+
+int
+ProcCreateWindow(ClientPtr client)
+{
+ WindowPtr pParent, pWin;
+
+ REQUEST(xCreateWindowReq);
+ int len, rc;
+
+ REQUEST_AT_LEAST_SIZE(xCreateWindowReq);
+
+ LEGAL_NEW_RESOURCE(stuff->wid, client);
+ rc = dixLookupWindow(&pParent, stuff->parent, client, DixAddAccess);
+ if (rc != Success)
+ return rc;
+ len = client->req_len - bytes_to_int32(sizeof(xCreateWindowReq));
+ if (Ones(stuff->mask) != len)
+ return BadLength;
+ if (!stuff->width || !stuff->height) {
+ client->errorValue = 0;
+ return BadValue;
+ }
+ pWin = CreateWindow(stuff->wid, pParent, stuff->x,
+ stuff->y, stuff->width, stuff->height,
+ stuff->borderWidth, stuff->class,
+ stuff->mask, (XID *) &stuff[1],
+ (int) stuff->depth, client, stuff->visual, &rc);
+ if (pWin) {
+ Mask mask = pWin->eventMask;
+
+ pWin->eventMask = 0; /* subterfuge in case AddResource fails */
+ if (!AddResource(stuff->wid, RT_WINDOW, (void *) pWin))
+ return BadAlloc;
+ pWin->eventMask = mask;
+ }
+ return rc;
+}
+
+int
+ProcChangeWindowAttributes(ClientPtr client)
+{
+ WindowPtr pWin;
+
+ REQUEST(xChangeWindowAttributesReq);
+ int len, rc;
+ Mask access_mode = 0;
+
+ REQUEST_AT_LEAST_SIZE(xChangeWindowAttributesReq);
+ access_mode |= (stuff->valueMask & CWEventMask) ? DixReceiveAccess : 0;
+ access_mode |= (stuff->valueMask & ~CWEventMask) ? DixSetAttrAccess : 0;
+ rc = dixLookupWindow(&pWin, stuff->window, client, access_mode);
+ if (rc != Success)
+ return rc;
+ len = client->req_len - bytes_to_int32(sizeof(xChangeWindowAttributesReq));
+ if (len != Ones(stuff->valueMask))
+ return BadLength;
+ return ChangeWindowAttributes(pWin,
+ stuff->valueMask, (XID *) &stuff[1], client);
+}
+
+int
+ProcGetWindowAttributes(ClientPtr client)
+{
+ WindowPtr pWin;
+
+ REQUEST(xResourceReq);
+ xGetWindowAttributesReply wa;
+ int rc;
+
+ REQUEST_SIZE_MATCH(xResourceReq);
+ rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+ memset(&wa, 0, sizeof(xGetWindowAttributesReply));
+ GetWindowAttributes(pWin, client, &wa);
+ WriteReplyToClient(client, sizeof(xGetWindowAttributesReply), &wa);
+ return Success;
+}
+
+int
+ProcDestroyWindow(ClientPtr client)
+{
+ WindowPtr pWin;
+
+ REQUEST(xResourceReq);
+ int rc;
+
+ REQUEST_SIZE_MATCH(xResourceReq);
+ rc = dixLookupWindow(&pWin, stuff->id, client, DixDestroyAccess);
+ if (rc != Success)
+ return rc;
+ if (pWin->parent) {
+ rc = dixLookupWindow(&pWin, pWin->parent->drawable.id, client,
+ DixRemoveAccess);
+ if (rc != Success)
+ return rc;
+ FreeResource(stuff->id, RT_NONE);
+ }
+ return Success;
+}
+
+int
+ProcDestroySubwindows(ClientPtr client)
+{
+ WindowPtr pWin;
+
+ REQUEST(xResourceReq);
+ int rc;
+
+ REQUEST_SIZE_MATCH(xResourceReq);
+ rc = dixLookupWindow(&pWin, stuff->id, client, DixRemoveAccess);
+ if (rc != Success)
+ return rc;
+ DestroySubwindows(pWin, client);
+ return Success;
+}
+
+int
+ProcChangeSaveSet(ClientPtr client)
+{
+ WindowPtr pWin;
+
+ REQUEST(xChangeSaveSetReq);
+ int rc;
+
+ REQUEST_SIZE_MATCH(xChangeSaveSetReq);
+ rc = dixLookupWindow(&pWin, stuff->window, client, DixManageAccess);
+ if (rc != Success)
+ return rc;
+ if (client->clientAsMask == (CLIENT_BITS(pWin->drawable.id)))
+ return BadMatch;
+ if ((stuff->mode == SetModeInsert) || (stuff->mode == SetModeDelete))
+ return AlterSaveSetForClient(client, pWin, stuff->mode, FALSE, TRUE);
+ client->errorValue = stuff->mode;
+ return BadValue;
+}
+
+int
+ProcReparentWindow(ClientPtr client)
+{
+ WindowPtr pWin, pParent;
+
+ REQUEST(xReparentWindowReq);
+ int rc;
+
+ REQUEST_SIZE_MATCH(xReparentWindowReq);
+ rc = dixLookupWindow(&pWin, stuff->window, client, DixManageAccess);
+ if (rc != Success)
+ return rc;
+ rc = dixLookupWindow(&pParent, stuff->parent, client, DixAddAccess);
+ if (rc != Success)
+ return rc;
+ if (!SAME_SCREENS(pWin->drawable, pParent->drawable))
+ return BadMatch;
+ if ((pWin->backgroundState == ParentRelative) &&
+ (pParent->drawable.depth != pWin->drawable.depth))
+ return BadMatch;
+ if ((pWin->drawable.class != InputOnly) &&
+ (pParent->drawable.class == InputOnly))
+ return BadMatch;
+ return ReparentWindow(pWin, pParent,
+ (short) stuff->x, (short) stuff->y, client);
+}
+
+int
+ProcMapWindow(ClientPtr client)
+{
+ WindowPtr pWin;
+
+ REQUEST(xResourceReq);
+ int rc;
+
+ REQUEST_SIZE_MATCH(xResourceReq);
+ rc = dixLookupWindow(&pWin, stuff->id, client, DixShowAccess);
+ if (rc != Success)
+ return rc;
+ MapWindow(pWin, client);
+ /* update cache to say it is mapped */
+ return Success;
+}
+
+int
+ProcMapSubwindows(ClientPtr client)
+{
+ WindowPtr pWin;
+
+ REQUEST(xResourceReq);
+ int rc;
+
+ REQUEST_SIZE_MATCH(xResourceReq);
+ rc = dixLookupWindow(&pWin, stuff->id, client, DixListAccess);
+ if (rc != Success)
+ return rc;
+ MapSubwindows(pWin, client);
+ /* update cache to say it is mapped */
+ return Success;
+}
+
+int
+ProcUnmapWindow(ClientPtr client)
+{
+ WindowPtr pWin;
+
+ REQUEST(xResourceReq);
+ int rc;
+
+ REQUEST_SIZE_MATCH(xResourceReq);
+ rc = dixLookupWindow(&pWin, stuff->id, client, DixHideAccess);
+ if (rc != Success)
+ return rc;
+ UnmapWindow(pWin, FALSE);
+ /* update cache to say it is mapped */
+ return Success;
+}
+
+int
+ProcUnmapSubwindows(ClientPtr client)
+{
+ WindowPtr pWin;
+
+ REQUEST(xResourceReq);
+ int rc;
+
+ REQUEST_SIZE_MATCH(xResourceReq);
+ rc = dixLookupWindow(&pWin, stuff->id, client, DixListAccess);
+ if (rc != Success)
+ return rc;
+ UnmapSubwindows(pWin);
+ return Success;
+}
+
+int
+ProcConfigureWindow(ClientPtr client)
+{
+ WindowPtr pWin;
+
+ REQUEST(xConfigureWindowReq);
+ int len, rc;
+
+ REQUEST_AT_LEAST_SIZE(xConfigureWindowReq);
+ rc = dixLookupWindow(&pWin, stuff->window, client,
+ DixManageAccess | DixSetAttrAccess);
+ if (rc != Success)
+ return rc;
+ len = client->req_len - bytes_to_int32(sizeof(xConfigureWindowReq));
+ if (Ones((Mask) stuff->mask) != len)
+ return BadLength;
+ return ConfigureWindow(pWin, (Mask) stuff->mask, (XID *) &stuff[1], client);
+}
+
+int
+ProcCirculateWindow(ClientPtr client)
+{
+ WindowPtr pWin;
+
+ REQUEST(xCirculateWindowReq);
+ int rc;
+
+ REQUEST_SIZE_MATCH(xCirculateWindowReq);
+ if ((stuff->direction != RaiseLowest) && (stuff->direction != LowerHighest)) {
+ client->errorValue = stuff->direction;
+ return BadValue;
+ }
+ rc = dixLookupWindow(&pWin, stuff->window, client, DixManageAccess);
+ if (rc != Success)
+ return rc;
+ CirculateWindow(pWin, (int) stuff->direction, client);
+ return Success;
+}
+
+static int
+GetGeometry(ClientPtr client, xGetGeometryReply * rep)
+{
+ DrawablePtr pDraw;
+ int rc;
+
+ REQUEST(xResourceReq);
+ REQUEST_SIZE_MATCH(xResourceReq);
+
+ rc = dixLookupDrawable(&pDraw, stuff->id, client, M_ANY, DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+
+ rep->type = X_Reply;
+ rep->length = 0;
+ rep->sequenceNumber = client->sequence;
+ rep->root = pDraw->pScreen->root->drawable.id;
+ rep->depth = pDraw->depth;
+ rep->width = pDraw->width;
+ rep->height = pDraw->height;
+
+ if (WindowDrawable(pDraw->type)) {
+ WindowPtr pWin = (WindowPtr) pDraw;
+
+ rep->x = pWin->origin.x - wBorderWidth(pWin);
+ rep->y = pWin->origin.y - wBorderWidth(pWin);
+ rep->borderWidth = pWin->borderWidth;
+ }
+ else { /* DRAWABLE_PIXMAP */
+
+ rep->x = rep->y = rep->borderWidth = 0;
+ }
+
+ return Success;
+}
+
+int
+ProcGetGeometry(ClientPtr client)
+{
+ xGetGeometryReply rep;
+ int status;
+
+ memset(&rep, 0, sizeof(xGetGeometryReply));
+ rep.type = X_Reply ;
+ if ((status = GetGeometry(client, &rep)) != Success)
+ return status;
+
+ WriteReplyToClient(client, sizeof(xGetGeometryReply), &rep);
+ return Success;
+}
+
+#ifdef WIN32
+/* Do not return the clipboard window in ProcQueryTree, cause this may cause
+ the clipboard client being closed when connecting through xdmcp.
+*/
+extern Window g_iClipboardWindow;
+
+#endif
+int
+ProcQueryTree(ClientPtr client)
+{
+ xQueryTreeReply reply;
+ int rc, numChildren = 0;
+ WindowPtr pChild, pWin, pHead;
+ Window *childIDs = (Window *) NULL;
+
+ REQUEST(xResourceReq);
+
+ REQUEST_SIZE_MATCH(xResourceReq);
+ rc = dixLookupWindow(&pWin, stuff->id, client, DixListAccess);
+ if (rc != Success)
+ return rc;
+ memset(&reply, 0, sizeof(xQueryTreeReply));
+ reply.type = X_Reply;
+ reply.sequenceNumber = client->sequence;
+ reply.root = pWin->drawable.pScreen->root->drawable.id;
+ reply.parent = (pWin->parent) ? pWin->parent->drawable.id : (Window) None;
+
+ pHead = RealChildHead(pWin);
+ for (pChild = pWin->lastChild; pChild != pHead; pChild = pChild->prevSib)
+#ifdef WIN32
+ if (pChild->drawable.id!=g_iClipboardWindow)
+#endif
+ numChildren++;
+ if (numChildren) {
+ int curChild = 0;
+
+ childIDs = malloc(numChildren * sizeof(Window));
+ if (!childIDs)
+ return BadAlloc;
+ for (pChild = pWin->lastChild; pChild != pHead;
+ pChild = pChild->prevSib)
+#ifdef WIN32
+ if (pChild->drawable.id!=g_iClipboardWindow)
+#endif
+ childIDs[curChild++] = pChild->drawable.id;
+ }
+
+ reply.nChildren = numChildren;
+ reply.length = bytes_to_int32(numChildren * sizeof(Window));
+
+ WriteReplyToClient(client, sizeof(xQueryTreeReply), &reply);
+ if (numChildren) {
+ client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
+ WriteSwappedDataToClient(client, numChildren * sizeof(Window),
+ childIDs);
+ free(childIDs);
+ }
+
+ return Success;
+}
+
+int
+ProcInternAtom(ClientPtr client)
+{
+ Atom atom;
+ char *tchar;
+
+ REQUEST(xInternAtomReq);
+
+ REQUEST_FIXED_SIZE(xInternAtomReq, stuff->nbytes);
+ if ((stuff->onlyIfExists != xTrue) && (stuff->onlyIfExists != xFalse)) {
+ client->errorValue = stuff->onlyIfExists;
+ return BadValue;
+ }
+ tchar = (char *) &stuff[1];
+ atom = MakeAtom(tchar, stuff->nbytes, !stuff->onlyIfExists);
+ if (atom != BAD_RESOURCE) {
+ xInternAtomReply reply; memset(&reply, 0, sizeof(xInternAtomReply));
+ reply.type = X_Reply;
+ reply.sequenceNumber = client->sequence;
+ reply.length = 0;
+ reply.atom = atom;
+
+ WriteReplyToClient(client, sizeof(xInternAtomReply), &reply);
+ return Success;
+ }
+ else
+ return BadAlloc;
+}
+
+int
+ProcGetAtomName(ClientPtr client)
+{
+ const char *str;
+
+ REQUEST(xResourceReq);
+
+ REQUEST_SIZE_MATCH(xResourceReq);
+ if ((str = NameForAtom(stuff->id))) {
+ xGetAtomNameReply reply;
+ int len = strlen(str);
+ memset(&reply, 0, sizeof(xGetAtomNameReply));
+ reply.type = X_Reply;
+ reply.sequenceNumber = client->sequence;
+ reply.length = bytes_to_int32(len);
+ reply.nameLength = len;
+ WriteReplyToClient(client, sizeof(xGetAtomNameReply), &reply);
+ WriteToClient(client, len, str);
+ return Success;
+ }
+ else {
+ client->errorValue = stuff->id;
+ return BadAtom;
+ }
+}
+
+int
+ProcGrabServer(ClientPtr client)
+{
+ int rc;
+
+ REQUEST_SIZE_MATCH(xReq);
+ if (grabState != GrabNone && client != grabClient) {
+ ResetCurrentRequest(client);
+ client->sequence--;
+ BITSET(grabWaiters, client->index);
+ IgnoreClient(client);
+ return Success;
+ }
+ rc = OnlyListenToOneClient(client);
+ if (rc != Success)
+ return rc;
+ grabState = GrabKickout;
+ grabClient = client;
+
+ if (ServerGrabCallback) {
+ ServerGrabInfoRec grabinfo;
+
+ grabinfo.client = client;
+ grabinfo.grabstate = SERVER_GRABBED;
+ CallCallbacks(&ServerGrabCallback, (void *) &grabinfo);
+ }
+
+ return Success;
+}
+
+static void
+UngrabServer(ClientPtr client)
+{
+ int i;
+
+ grabState = GrabNone;
+ ListenToAllClients();
+ for (i = mskcnt; --i >= 0 && !grabWaiters[i];);
+ if (i >= 0) {
+ i <<= 5;
+ while (!GETBIT(grabWaiters, i))
+ i++;
+ BITCLEAR(grabWaiters, i);
+ AttendClient(clients[i]);
+ }
+
+ if (ServerGrabCallback) {
+ ServerGrabInfoRec grabinfo;
+
+ grabinfo.client = client;
+ grabinfo.grabstate = SERVER_UNGRABBED;
+ CallCallbacks(&ServerGrabCallback, (void *) &grabinfo);
+ }
+}
+
+int
+ProcUngrabServer(ClientPtr client)
+{
+ REQUEST_SIZE_MATCH(xReq);
+ UngrabServer(client);
+ return Success;
+}
+
+int
+ProcTranslateCoords(ClientPtr client)
+{
+ REQUEST(xTranslateCoordsReq);
+
+ WindowPtr pWin, pDst;
+ xTranslateCoordsReply rep;
+ int rc;
+
+ REQUEST_SIZE_MATCH(xTranslateCoordsReq);
+ rc = dixLookupWindow(&pWin, stuff->srcWid, client, DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+ rc = dixLookupWindow(&pDst, stuff->dstWid, client, DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+ memset(&rep, 0, sizeof(xTranslateCoordsReply));
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.length = 0;
+
+ if (!SAME_SCREENS(pWin->drawable, pDst->drawable)) {
+ rep.sameScreen = xFalse;
+ rep.child = None;
+ rep.dstX = rep.dstY = 0;
+ }
+ else {
+ INT16 x, y;
+
+ rep.sameScreen = xTrue;
+ rep.child = None;
+ /* computing absolute coordinates -- adjust to destination later */
+ x = pWin->drawable.x + stuff->srcX;
+ y = pWin->drawable.y + stuff->srcY;
+ pWin = pDst->firstChild;
+ while (pWin) {
+ BoxRec box;
+
+ if ((pWin->mapped) &&
+ (x >= pWin->drawable.x - wBorderWidth(pWin)) &&
+ (x < pWin->drawable.x + (int) pWin->drawable.width +
+ wBorderWidth(pWin)) &&
+ (y >= pWin->drawable.y - wBorderWidth(pWin)) &&
+ (y < pWin->drawable.y + (int) pWin->drawable.height +
+ wBorderWidth(pWin))
+ /* When a window is shaped, a further check
+ * is made to see if the point is inside
+ * borderSize
+ */
+ && (!wBoundingShape(pWin) ||
+ RegionContainsPoint(&pWin->borderSize, x, y, &box))
+
+ && (!wInputShape(pWin) ||
+ RegionContainsPoint(wInputShape(pWin),
+ x - pWin->drawable.x,
+ y - pWin->drawable.y, &box))
+ ) {
+ rep.child = pWin->drawable.id;
+ pWin = (WindowPtr) NULL;
+ }
+ else
+ pWin = pWin->nextSib;
+ }
+ /* adjust to destination coordinates */
+ rep.dstX = x - pDst->drawable.x;
+ rep.dstY = y - pDst->drawable.y;
+ }
+ WriteReplyToClient(client, sizeof(xTranslateCoordsReply), &rep);
+ return Success;
+}
+
+int
+ProcOpenFont(ClientPtr client)
+{
+ int err;
+
+ REQUEST(xOpenFontReq);
+
+ REQUEST_FIXED_SIZE(xOpenFontReq, stuff->nbytes);
+ client->errorValue = stuff->fid;
+ LEGAL_NEW_RESOURCE(stuff->fid, client);
+ err = OpenFont(client, stuff->fid, (Mask) 0,
+ stuff->nbytes, (char *) &stuff[1]);
+ if (err == Success) {
+ return Success;
+ }
+ else
+ return err;
+}
+
+int
+ProcCloseFont(ClientPtr client)
+{
+ FontPtr pFont;
+ int rc;
+
+ REQUEST(xResourceReq);
+
+ REQUEST_SIZE_MATCH(xResourceReq);
+ rc = dixLookupResourceByType((void **) &pFont, stuff->id, RT_FONT,
+ client, DixDestroyAccess);
+ if (rc == Success) {
+ FreeResource(stuff->id, RT_NONE);
+ return Success;
+ }
+ else {
+ client->errorValue = stuff->id;
+ return rc;
+ }
+}
+
+int
+ProcQueryFont(ClientPtr client)
+{
+ xQueryFontReply *reply;
+ FontPtr pFont;
+ int rc;
+
+ REQUEST(xResourceReq);
+ REQUEST_SIZE_MATCH(xResourceReq);
+
+ rc = dixLookupFontable(&pFont, stuff->id, client, DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+
+ {
+ xCharInfo *pmax = FONTINKMAX(pFont);
+ xCharInfo *pmin = FONTINKMIN(pFont);
+ int nprotoxcistructs;
+ int rlength;
+
+ nprotoxcistructs = (pmax->rightSideBearing == pmin->rightSideBearing &&
+ pmax->leftSideBearing == pmin->leftSideBearing &&
+ pmax->descent == pmin->descent &&
+ pmax->ascent == pmin->ascent &&
+ pmax->characterWidth == pmin->characterWidth) ?
+ 0 : N2dChars(pFont);
+
+ rlength = sizeof(xQueryFontReply) +
+ FONTINFONPROPS(FONTCHARSET(pFont)) * sizeof(xFontProp) +
+ nprotoxcistructs * sizeof(xCharInfo);
+ reply = calloc(1, rlength);
+ if (!reply) {
+ return BadAlloc;
+ }
+
+ reply->type = X_Reply;
+ reply->length = bytes_to_int32(rlength - sizeof(xGenericReply));
+ reply->sequenceNumber = client->sequence;
+ QueryFont(pFont, reply, nprotoxcistructs);
+
+ WriteReplyToClient(client, rlength, reply);
+ free(reply);
+ return Success;
+ }
+}
+
+int
+ProcQueryTextExtents(ClientPtr client)
+{
+ xQueryTextExtentsReply reply;
+ FontPtr pFont;
+ ExtentInfoRec info;
+ unsigned long length;
+ int rc;
+
+ REQUEST(xQueryTextExtentsReq);
+ REQUEST_AT_LEAST_SIZE(xQueryTextExtentsReq);
+
+ rc = dixLookupFontable(&pFont, stuff->fid, client, DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+
+ length = client->req_len - bytes_to_int32(sizeof(xQueryTextExtentsReq));
+ length = length << 1;
+ if (stuff->oddLength) {
+ if (length == 0)
+ return BadLength;
+ length--;
+ }
+ if (!QueryTextExtents(pFont, length, (unsigned char *) &stuff[1], &info))
+ return BadAlloc;
+
+ reply.type = X_Reply;
+ reply.drawDirection = info.drawDirection;
+ reply.sequenceNumber = client->sequence;
+ reply.length = 0;
+ reply.fontAscent = info.fontAscent;
+ reply.fontDescent = info.fontDescent;
+ reply.overallAscent = info.overallAscent;
+ reply.overallDescent = info.overallDescent;
+ reply.overallWidth = info.overallWidth;
+ reply.overallLeft = info.overallLeft;
+ reply.overallRight = info.overallRight;
+
+ WriteReplyToClient(client, sizeof(xQueryTextExtentsReply), &reply);
+ return Success;
+}
+
+int
+ProcListFonts(ClientPtr client)
+{
+ REQUEST(xListFontsReq);
+
+ REQUEST_FIXED_SIZE(xListFontsReq, stuff->nbytes);
+
+ return ListFonts(client, (unsigned char *) &stuff[1], stuff->nbytes,
+ stuff->maxNames);
+}
+
+int
+ProcListFontsWithInfo(ClientPtr client)
+{
+ REQUEST(xListFontsWithInfoReq);
+
+ REQUEST_FIXED_SIZE(xListFontsWithInfoReq, stuff->nbytes);
+
+ return StartListFontsWithInfo(client, stuff->nbytes,
+ (unsigned char *) &stuff[1], stuff->maxNames);
+}
+
+/**
+ *
+ * \param value must conform to DeleteType
+ */
+int
+dixDestroyPixmap(void *value, XID pid)
+{
+ PixmapPtr pPixmap = (PixmapPtr) value;
+
+ return (*pPixmap->drawable.pScreen->DestroyPixmap) (pPixmap);
+}
+
+int
+ProcCreatePixmap(ClientPtr client)
+{
+ PixmapPtr pMap;
+ DrawablePtr pDraw;
+
+ REQUEST(xCreatePixmapReq);
+ DepthPtr pDepth;
+ int i, rc;
+
+ REQUEST_SIZE_MATCH(xCreatePixmapReq);
+ client->errorValue = stuff->pid;
+ LEGAL_NEW_RESOURCE(stuff->pid, client);
+
+ rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY,
+ DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+
+ if (!stuff->width || !stuff->height) {
+ client->errorValue = 0;
+ return BadValue;
+ }
+ if (stuff->width > 32767 || stuff->height > 32767) {
+ /* It is allowed to try and allocate a pixmap which is larger than
+ * 32767 in either dimension. However, all of the framebuffer code
+ * is buggy and does not reliably draw to such big pixmaps, basically
+ * because the Region data structure operates with signed shorts
+ * for the rectangles in it.
+ *
+ * Furthermore, several places in the X server computes the
+ * size in bytes of the pixmap and tries to store it in an
+ * integer. This integer can overflow and cause the allocated size
+ * to be much smaller.
+ *
+ * So, such big pixmaps are rejected here with a BadAlloc
+ */
+ return BadAlloc;
+ }
+ if (stuff->depth != 1) {
+ pDepth = pDraw->pScreen->allowedDepths;
+ for (i = 0; i < pDraw->pScreen->numDepths; i++, pDepth++)
+ if (pDepth->depth == stuff->depth)
+ goto CreatePmap;
+ client->errorValue = stuff->depth;
+ return BadValue;
+ }
+ CreatePmap:
+ pMap = (PixmapPtr) (*pDraw->pScreen->CreatePixmap)
+ (pDraw->pScreen, stuff->width, stuff->height, stuff->depth, 0);
+ if (pMap) {
+ pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
+ pMap->drawable.id = stuff->pid;
+ /* security creation/labeling check */
+ rc = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pid, RT_PIXMAP,
+ pMap, RT_NONE, NULL, DixCreateAccess);
+ if (rc != Success) {
+ (*pDraw->pScreen->DestroyPixmap) (pMap);
+ return rc;
+ }
+ if (AddResource(stuff->pid, RT_PIXMAP, (void *) pMap))
+ return Success;
+ }
+ return BadAlloc;
+}
+
+int
+ProcFreePixmap(ClientPtr client)
+{
+ PixmapPtr pMap;
+ int rc;
+
+ REQUEST(xResourceReq);
+ REQUEST_SIZE_MATCH(xResourceReq);
+
+ rc = dixLookupResourceByType((void **) &pMap, stuff->id, RT_PIXMAP,
+ client, DixDestroyAccess);
+ if (rc == Success) {
+ FreeResource(stuff->id, RT_NONE);
+ return Success;
+ }
+ else {
+ client->errorValue = stuff->id;
+ return rc;
+ }
+}
+
+int
+ProcCreateGC(ClientPtr client)
+{
+ int error, rc;
+ GC *pGC;
+ DrawablePtr pDraw;
+ unsigned len;
+
+ REQUEST(xCreateGCReq);
+
+ REQUEST_AT_LEAST_SIZE(xCreateGCReq);
+ client->errorValue = stuff->gc;
+ LEGAL_NEW_RESOURCE(stuff->gc, client);
+ rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0,
+ DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+
+ len = client->req_len - bytes_to_int32(sizeof(xCreateGCReq));
+ if (len != Ones(stuff->mask))
+ return BadLength;
+ pGC = (GC *) CreateGC(pDraw, stuff->mask, (XID *) &stuff[1], &error,
+ stuff->gc, client);
+ if (error != Success)
+ return error;
+ if (!AddResource(stuff->gc, RT_GC, (void *) pGC))
+ return BadAlloc;
+ return Success;
+}
+
+int
+ProcChangeGC(ClientPtr client)
+{
+ GC *pGC;
+ int result;
+ unsigned len;
+
+ REQUEST(xChangeGCReq);
+ REQUEST_AT_LEAST_SIZE(xChangeGCReq);
+
+ result = dixLookupGC(&pGC, stuff->gc, client, DixSetAttrAccess);
+ if (result != Success)
+ return result;
+
+ len = client->req_len - bytes_to_int32(sizeof(xChangeGCReq));
+ if (len != Ones(stuff->mask))
+ return BadLength;
+
+ return ChangeGCXIDs(client, pGC, stuff->mask, (CARD32 *) &stuff[1]);
+}
+
+int
+ProcCopyGC(ClientPtr client)
+{
+ GC *dstGC;
+ GC *pGC;
+ int result;
+
+ REQUEST(xCopyGCReq);
+ REQUEST_SIZE_MATCH(xCopyGCReq);
+
+ result = dixLookupGC(&pGC, stuff->srcGC, client, DixGetAttrAccess);
+ if (result != Success)
+ return result;
+ result = dixLookupGC(&dstGC, stuff->dstGC, client, DixSetAttrAccess);
+ if (result != Success)
+ return result;
+ if ((dstGC->pScreen != pGC->pScreen) || (dstGC->depth != pGC->depth))
+ return BadMatch;
+ if (stuff->mask & ~GCAllBits) {
+ client->errorValue = stuff->mask;
+ return BadValue;
+ }
+ return CopyGC(pGC, dstGC, stuff->mask);
+}
+
+int
+ProcSetDashes(ClientPtr client)
+{
+ GC *pGC;
+ int result;
+
+ REQUEST(xSetDashesReq);
+
+ REQUEST_FIXED_SIZE(xSetDashesReq, stuff->nDashes);
+ if (stuff->nDashes == 0) {
+ client->errorValue = 0;
+ return BadValue;
+ }
+
+ result = dixLookupGC(&pGC, stuff->gc, client, DixSetAttrAccess);
+ if (result != Success)
+ return result;
+
+ /* If there's an error, either there's no sensible errorValue,
+ * or there was a dash segment of 0. */
+ client->errorValue = 0;
+ return SetDashes(pGC, stuff->dashOffset, stuff->nDashes,
+ (unsigned char *) &stuff[1]);
+}
+
+int
+ProcSetClipRectangles(ClientPtr client)
+{
+ int nr, result;
+ GC *pGC;
+
+ REQUEST(xSetClipRectanglesReq);
+
+ REQUEST_AT_LEAST_SIZE(xSetClipRectanglesReq);
+ if ((stuff->ordering != Unsorted) && (stuff->ordering != YSorted) &&
+ (stuff->ordering != YXSorted) && (stuff->ordering != YXBanded)) {
+ client->errorValue = stuff->ordering;
+ return BadValue;
+ }
+ result = dixLookupGC(&pGC, stuff->gc, client, DixSetAttrAccess);
+ if (result != Success)
+ return result;
+
+ nr = (client->req_len << 2) - sizeof(xSetClipRectanglesReq);
+ if (nr & 4)
+ return BadLength;
+ nr >>= 3;
+ return SetClipRects(pGC, stuff->xOrigin, stuff->yOrigin,
+ nr, (xRectangle *) &stuff[1], (int) stuff->ordering);
+}
+
+int
+ProcFreeGC(ClientPtr client)
+{
+ GC *pGC;
+ int rc;
+
+ REQUEST(xResourceReq);
+ REQUEST_SIZE_MATCH(xResourceReq);
+
+ rc = dixLookupGC(&pGC, stuff->id, client, DixDestroyAccess);
+ if (rc != Success)
+ return rc;
+
+ FreeResource(stuff->id, RT_NONE);
+ return Success;
+}
+
+int
+ProcClearToBackground(ClientPtr client)
+{
+ REQUEST(xClearAreaReq);
+ WindowPtr pWin;
+ int rc;
+
+ REQUEST_SIZE_MATCH(xClearAreaReq);
+ rc = dixLookupWindow(&pWin, stuff->window, client, DixWriteAccess);
+ if (rc != Success)
+ return rc;
+ if (pWin->drawable.class == InputOnly) {
+ client->errorValue = stuff->window;
+ return BadMatch;
+ }
+ if ((stuff->exposures != xTrue) && (stuff->exposures != xFalse)) {
+ client->errorValue = stuff->exposures;
+ return BadValue;
+ }
+ (*pWin->drawable.pScreen->ClearToBackground) (pWin, stuff->x, stuff->y,
+ stuff->width, stuff->height,
+ (Bool) stuff->exposures);
+ return Success;
+}
+
+/* send GraphicsExpose events, or a NoExpose event, based on the region */
+void
+SendGraphicsExpose(ClientPtr client, RegionPtr pRgn, XID drawable,
+ int major, int minor)
+{
+ if (pRgn && !RegionNil(pRgn)) {
+ xEvent *pEvent;
+ xEvent *pe;
+ BoxPtr pBox;
+ int i;
+ int numRects;
+
+ numRects = RegionNumRects(pRgn);
+ pBox = RegionRects(pRgn);
+ if (!(pEvent = calloc(numRects, sizeof(xEvent))))
+ return;
+ pe = pEvent;
+
+ for (i = 1; i <= numRects; i++, pe++, pBox++) {
+ pe->u.u.type = GraphicsExpose;
+ pe->u.graphicsExposure.drawable = drawable;
+ pe->u.graphicsExposure.x = pBox->x1;
+ pe->u.graphicsExposure.y = pBox->y1;
+ pe->u.graphicsExposure.width = pBox->x2 - pBox->x1;
+ pe->u.graphicsExposure.height = pBox->y2 - pBox->y1;
+ pe->u.graphicsExposure.count = numRects - i;
+ pe->u.graphicsExposure.majorEvent = major;
+ pe->u.graphicsExposure.minorEvent = minor;
+ }
+ /* GraphicsExpose is a "critical event", which TryClientEvents
+ * handles specially. */
+ TryClientEvents(client, NULL, pEvent, numRects,
+ (Mask) 0, NoEventMask, NullGrab);
+ free(pEvent);
+ }
+ else {
+ xEvent event = {
+ .u.noExposure.drawable = drawable,
+ .u.noExposure.majorEvent = major,
+ .u.noExposure.minorEvent = minor
+ };
+ event.u.u.type = NoExpose;
+ WriteEventsToClient(client, 1, &event);
+ }
+}
+
+int
+ProcCopyArea(ClientPtr client)
+{
+ DrawablePtr pDst;
+ DrawablePtr pSrc;
+ GC *pGC;
+
+ REQUEST(xCopyAreaReq);
+ RegionPtr pRgn;
+ int rc;
+
+ REQUEST_SIZE_MATCH(xCopyAreaReq);
+
+ VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pDst, DixWriteAccess);
+ if (stuff->dstDrawable != stuff->srcDrawable) {
+ rc = dixLookupDrawable(&pSrc, stuff->srcDrawable, client, 0,
+ DixReadAccess);
+ if (rc != Success)
+ return rc;
+ if ((pDst->pScreen != pSrc->pScreen) || (pDst->depth != pSrc->depth)) {
+ client->errorValue = stuff->dstDrawable;
+ return BadMatch;
+ }
+ }
+ else
+ pSrc = pDst;
+
+ pRgn = (*pGC->ops->CopyArea) (pSrc, pDst, pGC, stuff->srcX, stuff->srcY,
+ stuff->width, stuff->height,
+ stuff->dstX, stuff->dstY);
+ if (pGC->graphicsExposures) {
+ SendGraphicsExpose(client, pRgn, stuff->dstDrawable, X_CopyArea, 0);
+ if (pRgn)
+ RegionDestroy(pRgn);
+ }
+
+ return Success;
+}
+
+int
+ProcCopyPlane(ClientPtr client)
+{
+ DrawablePtr psrcDraw, pdstDraw;
+ GC *pGC;
+
+ REQUEST(xCopyPlaneReq);
+ RegionPtr pRgn;
+ int rc;
+
+ REQUEST_SIZE_MATCH(xCopyPlaneReq);
+
+ VALIDATE_DRAWABLE_AND_GC(stuff->dstDrawable, pdstDraw, DixWriteAccess);
+ if (stuff->dstDrawable != stuff->srcDrawable) {
+ rc = dixLookupDrawable(&psrcDraw, stuff->srcDrawable, client, 0,
+ DixReadAccess);
+ if (rc != Success)
+ return rc;
+
+ if (pdstDraw->pScreen != psrcDraw->pScreen) {
+ client->errorValue = stuff->dstDrawable;
+ return BadMatch;
+ }
+ }
+ else
+ psrcDraw = pdstDraw;
+
+ /* Check to see if stuff->bitPlane has exactly ONE good bit set */
+ if (stuff->bitPlane == 0 || (stuff->bitPlane & (stuff->bitPlane - 1)) ||
+ (stuff->bitPlane > (1L << (psrcDraw->depth - 1)))) {
+ client->errorValue = stuff->bitPlane;
+ return BadValue;
+ }
+
+ pRgn =
+ (*pGC->ops->CopyPlane) (psrcDraw, pdstDraw, pGC, stuff->srcX,
+ stuff->srcY, stuff->width, stuff->height,
+ stuff->dstX, stuff->dstY, stuff->bitPlane);
+ if (pGC->graphicsExposures) {
+ SendGraphicsExpose(client, pRgn, stuff->dstDrawable, X_CopyPlane, 0);
+ if (pRgn)
+ RegionDestroy(pRgn);
+ }
+ return Success;
+}
+
+int
+ProcPolyPoint(ClientPtr client)
+{
+ int npoint;
+ GC *pGC;
+ DrawablePtr pDraw;
+
+ REQUEST(xPolyPointReq);
+
+ REQUEST_AT_LEAST_SIZE(xPolyPointReq);
+ if ((stuff->coordMode != CoordModeOrigin) &&
+ (stuff->coordMode != CoordModePrevious)) {
+ client->errorValue = stuff->coordMode;
+ return BadValue;
+ }
+ VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
+ npoint = bytes_to_int32((client->req_len << 2) - sizeof(xPolyPointReq));
+ if (npoint)
+ (*pGC->ops->PolyPoint) (pDraw, pGC, stuff->coordMode, npoint,
+ (xPoint *) &stuff[1]);
+ return Success;
+}
+
+int
+ProcPolyLine(ClientPtr client)
+{
+ int npoint;
+ GC *pGC;
+ DrawablePtr pDraw;
+
+ REQUEST(xPolyLineReq);
+
+ REQUEST_AT_LEAST_SIZE(xPolyLineReq);
+ if ((stuff->coordMode != CoordModeOrigin) &&
+ (stuff->coordMode != CoordModePrevious)) {
+ client->errorValue = stuff->coordMode;
+ return BadValue;
+ }
+ VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
+ npoint = bytes_to_int32((client->req_len << 2) - sizeof(xPolyLineReq));
+ if (npoint > 1)
+ (*pGC->ops->Polylines) (pDraw, pGC, stuff->coordMode, npoint,
+ (DDXPointPtr) &stuff[1]);
+ return Success;
+}
+
+int
+ProcPolySegment(ClientPtr client)
+{
+ int nsegs;
+ GC *pGC;
+ DrawablePtr pDraw;
+
+ REQUEST(xPolySegmentReq);
+
+ REQUEST_AT_LEAST_SIZE(xPolySegmentReq);
+ VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
+ nsegs = (client->req_len << 2) - sizeof(xPolySegmentReq);
+ if (nsegs & 4)
+ return BadLength;
+ nsegs >>= 3;
+ if (nsegs)
+ (*pGC->ops->PolySegment) (pDraw, pGC, nsegs, (xSegment *) &stuff[1]);
+ return Success;
+}
+
+int
+ProcPolyRectangle(ClientPtr client)
+{
+ int nrects;
+ GC *pGC;
+ DrawablePtr pDraw;
+
+ REQUEST(xPolyRectangleReq);
+
+ REQUEST_AT_LEAST_SIZE(xPolyRectangleReq);
+ VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
+ nrects = (client->req_len << 2) - sizeof(xPolyRectangleReq);
+ if (nrects & 4)
+ return BadLength;
+ nrects >>= 3;
+ if (nrects)
+ (*pGC->ops->PolyRectangle) (pDraw, pGC,
+ nrects, (xRectangle *) &stuff[1]);
+ return Success;
+}
+
+int
+ProcPolyArc(ClientPtr client)
+{
+ int narcs;
+ GC *pGC;
+ DrawablePtr pDraw;
+
+ REQUEST(xPolyArcReq);
+
+ REQUEST_AT_LEAST_SIZE(xPolyArcReq);
+ VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
+ narcs = (client->req_len << 2) - sizeof(xPolyArcReq);
+ if (narcs % sizeof(xArc))
+ return BadLength;
+ narcs /= sizeof(xArc);
+ if (narcs)
+ (*pGC->ops->PolyArc) (pDraw, pGC, narcs, (xArc *) &stuff[1]);
+ return Success;
+}
+
+int
+ProcFillPoly(ClientPtr client)
+{
+ int things;
+ GC *pGC;
+ DrawablePtr pDraw;
+
+ REQUEST(xFillPolyReq);
+
+ REQUEST_AT_LEAST_SIZE(xFillPolyReq);
+ if ((stuff->shape != Complex) && (stuff->shape != Nonconvex) &&
+ (stuff->shape != Convex)) {
+ client->errorValue = stuff->shape;
+ return BadValue;
+ }
+ if ((stuff->coordMode != CoordModeOrigin) &&
+ (stuff->coordMode != CoordModePrevious)) {
+ client->errorValue = stuff->coordMode;
+ return BadValue;
+ }
+
+ VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
+ things = bytes_to_int32((client->req_len << 2) - sizeof(xFillPolyReq));
+ if (things)
+ (*pGC->ops->FillPolygon) (pDraw, pGC, stuff->shape,
+ stuff->coordMode, things,
+ (DDXPointPtr) &stuff[1]);
+ return Success;
+}
+
+int
+ProcPolyFillRectangle(ClientPtr client)
+{
+ int things;
+ GC *pGC;
+ DrawablePtr pDraw;
+
+ REQUEST(xPolyFillRectangleReq);
+
+ REQUEST_AT_LEAST_SIZE(xPolyFillRectangleReq);
+ VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
+ things = (client->req_len << 2) - sizeof(xPolyFillRectangleReq);
+ if (things & 4)
+ return BadLength;
+ things >>= 3;
+
+ if (things)
+ (*pGC->ops->PolyFillRect) (pDraw, pGC, things,
+ (xRectangle *) &stuff[1]);
+ return Success;
+}
+
+int
+ProcPolyFillArc(ClientPtr client)
+{
+ int narcs;
+ GC *pGC;
+ DrawablePtr pDraw;
+
+ REQUEST(xPolyFillArcReq);
+
+ REQUEST_AT_LEAST_SIZE(xPolyFillArcReq);
+ VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
+ narcs = (client->req_len << 2) - sizeof(xPolyFillArcReq);
+ if (narcs % sizeof(xArc))
+ return BadLength;
+ narcs /= sizeof(xArc);
+ if (narcs)
+ (*pGC->ops->PolyFillArc) (pDraw, pGC, narcs, (xArc *) &stuff[1]);
+ return Success;
+}
+
+#ifdef MATCH_CLIENT_ENDIAN
+
+int
+ServerOrder(void)
+{
+ int whichbyte = 1;
+
+ if (*((char *) &whichbyte))
+ return LSBFirst;
+ return MSBFirst;
+}
+
+#define ClientOrder(client) ((client)->swapped ? !ServerOrder() : ServerOrder())
+
+void
+ReformatImage(char *base, int nbytes, int bpp, int order)
+{
+ switch (bpp) {
+ case 1: /* yuck */
+ if (BITMAP_BIT_ORDER != order)
+ BitOrderInvert((unsigned char *) base, nbytes);
+#if IMAGE_BYTE_ORDER != BITMAP_BIT_ORDER && BITMAP_SCANLINE_UNIT != 8
+ ReformatImage(base, nbytes, BITMAP_SCANLINE_UNIT, order);
+#endif
+ break;
+ case 4:
+ break; /* yuck */
+ case 8:
+ break;
+ case 16:
+ if (IMAGE_BYTE_ORDER != order)
+ TwoByteSwap((unsigned char *) base, nbytes);
+ break;
+ case 32:
+ if (IMAGE_BYTE_ORDER != order)
+ FourByteSwap((unsigned char *) base, nbytes);
+ break;
+ }
+}
+#else
+#define ReformatImage(b,n,bpp,o)
+#endif
+
+/* 64-bit server notes: the protocol restricts padding of images to
+ * 8-, 16-, or 32-bits. We would like to have 64-bits for the server
+ * to use internally. Removes need for internal alignment checking.
+ * All of the PutImage functions could be changed individually, but
+ * as currently written, they call other routines which require things
+ * to be 64-bit padded on scanlines, so we changed things here.
+ * If an image would be padded differently for 64- versus 32-, then
+ * copy each scanline to a 64-bit padded scanline.
+ * Also, we need to make sure that the image is aligned on a 64-bit
+ * boundary, even if the scanlines are padded to our satisfaction.
+ */
+int
+ProcPutImage(ClientPtr client)
+{
+ GC *pGC;
+ DrawablePtr pDraw;
+ long length; /* length of scanline server padded */
+ long lengthProto; /* length of scanline protocol padded */
+ char *tmpImage;
+
+ REQUEST(xPutImageReq);
+
+ REQUEST_AT_LEAST_SIZE(xPutImageReq);
+ VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
+ if (stuff->format == XYBitmap) {
+ if ((stuff->depth != 1) ||
+ (stuff->leftPad >= (unsigned int) screenInfo.bitmapScanlinePad))
+ return BadMatch;
+ length = BitmapBytePad(stuff->width + stuff->leftPad);
+ }
+ else if (stuff->format == XYPixmap) {
+ if ((pDraw->depth != stuff->depth) ||
+ (stuff->leftPad >= (unsigned int) screenInfo.bitmapScanlinePad))
+ return BadMatch;
+ length = BitmapBytePad(stuff->width + stuff->leftPad);
+ length *= stuff->depth;
+ }
+ else if (stuff->format == ZPixmap) {
+ if ((pDraw->depth != stuff->depth) || (stuff->leftPad != 0))
+ return BadMatch;
+ length = PixmapBytePad(stuff->width, stuff->depth);
+ }
+ else {
+ client->errorValue = stuff->format;
+ return BadValue;
+ }
+
+ tmpImage = (char *) &stuff[1];
+ lengthProto = length;
+
+ if ((bytes_to_int32(lengthProto * stuff->height) +
+ bytes_to_int32(sizeof(xPutImageReq))) != client->req_len)
+ return BadLength;
+
+ ReformatImage(tmpImage, lengthProto * stuff->height,
+ stuff->format == ZPixmap ? BitsPerPixel(stuff->depth) : 1,
+ ClientOrder(client));
+
+ (*pGC->ops->PutImage) (pDraw, pGC, stuff->depth, stuff->dstX, stuff->dstY,
+ stuff->width, stuff->height,
+ stuff->leftPad, stuff->format, tmpImage);
+
+ return Success;
+}
+
+static int
+DoGetImage(ClientPtr client, int format, Drawable drawable,
+ int x, int y, int width, int height,
+ Mask planemask)
+{
+ DrawablePtr pDraw, pBoundingDraw;
+ int nlines, linesPerBuf, rc;
+ int linesDone;
+
+ /* coordinates relative to the bounding drawable */
+ int relx, rely;
+ long widthBytesLine, length;
+ Mask plane = 0;
+ char *pBuf;
+ xGetImageReply xgi;
+ RegionPtr pVisibleRegion = NULL;
+
+ if ((format != XYPixmap) && (format != ZPixmap)) {
+ client->errorValue = format;
+ return BadValue;
+ }
+ rc = dixLookupDrawable(&pDraw, drawable, client, 0, DixReadAccess);
+ if (rc != Success)
+ return rc;
+
+ memset(&xgi, 0, sizeof(xGetImageReply));
+
+ relx = x;
+ rely = y;
+
+ if (pDraw->type == DRAWABLE_WINDOW) {
+ WindowPtr pWin = (WindowPtr) pDraw;
+
+ /* "If the drawable is a window, the window must be viewable ... or a
+ * BadMatch error results" */
+ if (!pWin->viewable)
+ return BadMatch;
+
+ /* If the drawable is a window, the rectangle must be contained within
+ * its bounds (including the border). */
+ if (x < -wBorderWidth(pWin) ||
+ x + width > wBorderWidth(pWin) + (int) pDraw->width ||
+ y < -wBorderWidth(pWin) ||
+ y + height > wBorderWidth(pWin) + (int) pDraw->height)
+ return BadMatch;
+
+ relx += pDraw->x;
+ rely += pDraw->y;
+
+ if (pDraw->pScreen->GetWindowPixmap) {
+ PixmapPtr pPix = (*pDraw->pScreen->GetWindowPixmap) (pWin);
+
+ pBoundingDraw = &pPix->drawable;
+#ifdef COMPOSITE
+ relx -= pPix->screen_x;
+ rely -= pPix->screen_y;
+#endif
+ }
+ else {
+ pBoundingDraw = (DrawablePtr) pDraw->pScreen->root;
+ }
+
+ xgi.visual = wVisual(pWin);
+ }
+ else {
+ pBoundingDraw = pDraw;
+ xgi.visual = None;
+ }
+
+ /* "If the drawable is a pixmap, the given rectangle must be wholly
+ * contained within the pixmap, or a BadMatch error results. If the
+ * drawable is a window [...] it must be the case that if there were no
+ * inferiors or overlapping windows, the specified rectangle of the window
+ * would be fully visible on the screen and wholly contained within the
+ * outside edges of the window, or a BadMatch error results."
+ *
+ * We relax the window case slightly to mean that the rectangle must exist
+ * within the bounds of the window's backing pixmap. In particular, this
+ * means that a GetImage request may succeed or fail with BadMatch depending
+ * on whether any of its ancestor windows are redirected. */
+ if (relx < 0 || relx + width > (int) pBoundingDraw->width ||
+ rely < 0 || rely + height > (int) pBoundingDraw->height)
+ return BadMatch;
+
+ xgi.type = X_Reply;
+ xgi.sequenceNumber = client->sequence;
+ xgi.depth = pDraw->depth;
+ if (format == ZPixmap) {
+ widthBytesLine = PixmapBytePad(width, pDraw->depth);
+ length = widthBytesLine * height;
+
+ }
+ else {
+ widthBytesLine = BitmapBytePad(width);
+ plane = ((Mask) 1) << (pDraw->depth - 1);
+ /* only planes asked for */
+ length = widthBytesLine * height *
+ Ones(planemask & (plane | (plane - 1)));
+
+ }
+
+ xgi.length = length;
+
+ xgi.length = bytes_to_int32(xgi.length);
+ if (widthBytesLine == 0 || height == 0)
+ linesPerBuf = 0;
+ else if (widthBytesLine >= IMAGE_BUFSIZE)
+ linesPerBuf = 1;
+ else {
+ linesPerBuf = IMAGE_BUFSIZE / widthBytesLine;
+ if (linesPerBuf > height)
+ linesPerBuf = height;
+ }
+ length = linesPerBuf * widthBytesLine;
+ if (linesPerBuf < height) {
+ /* we have to make sure intermediate buffers don't need padding */
+ while ((linesPerBuf > 1) &&
+ (length & ((1L << LOG2_BYTES_PER_SCANLINE_PAD) - 1))) {
+ linesPerBuf--;
+ length -= widthBytesLine;
+ }
+ while (length & ((1L << LOG2_BYTES_PER_SCANLINE_PAD) - 1)) {
+ linesPerBuf++;
+ length += widthBytesLine;
+ }
+ }
+ if (!(pBuf = calloc(1, length)))
+ return BadAlloc;
+ WriteReplyToClient(client, sizeof(xGetImageReply), &xgi);
+
+ if (pDraw->type == DRAWABLE_WINDOW) {
+ pVisibleRegion = NotClippedByChildren((WindowPtr) pDraw);
+ if (pVisibleRegion) {
+ RegionTranslate(pVisibleRegion, -pDraw->x, -pDraw->y);
+ }
+ }
+
+ if (linesPerBuf == 0) {
+ /* nothing to do */
+ }
+ else if (format == ZPixmap) {
+ linesDone = 0;
+ while (height - linesDone > 0) {
+ nlines = min(linesPerBuf, height - linesDone);
+ (*pDraw->pScreen->GetImage) (pDraw,
+ x,
+ y + linesDone,
+ width,
+ nlines,
+ format, planemask, (void *) pBuf);
+ if (pVisibleRegion)
+ XaceCensorImage(client, pVisibleRegion, widthBytesLine,
+ pDraw, x, y + linesDone, width,
+ nlines, format, pBuf);
+
+ /* Note that this is NOT a call to WriteSwappedDataToClient,
+ as we do NOT byte swap */
+ ReformatImage(pBuf, (int) (nlines * widthBytesLine),
+ BitsPerPixel(pDraw->depth), ClientOrder(client));
+
+ WriteToClient(client, (int) (nlines * widthBytesLine), pBuf);
+ linesDone += nlines;
+ }
+ }
+ else { /* XYPixmap */
+
+ for (; plane; plane >>= 1) {
+ if (planemask & plane) {
+ linesDone = 0;
+ while (height - linesDone > 0) {
+ nlines = min(linesPerBuf, height - linesDone);
+ (*pDraw->pScreen->GetImage) (pDraw,
+ x,
+ y + linesDone,
+ width,
+ nlines,
+ format, plane, (void *) pBuf);
+ if (pVisibleRegion)
+ XaceCensorImage(client, pVisibleRegion,
+ widthBytesLine,
+ pDraw, x, y + linesDone, width,
+ nlines, format, pBuf);
+
+ /* Note: NOT a call to WriteSwappedDataToClient,
+ as we do NOT byte swap */
+ ReformatImage(pBuf, (int) (nlines * widthBytesLine),
+ 1, ClientOrder(client));
+
+ WriteToClient(client, (int)(nlines * widthBytesLine), pBuf);
+ linesDone += nlines;
+ }
+ }
+ }
+ }
+ if (pVisibleRegion)
+ RegionDestroy(pVisibleRegion);
+ free(pBuf);
+ return Success;
+}
+
+int
+ProcGetImage(ClientPtr client)
+{
+ REQUEST(xGetImageReq);
+
+ REQUEST_SIZE_MATCH(xGetImageReq);
+
+ return DoGetImage(client, stuff->format, stuff->drawable,
+ stuff->x, stuff->y,
+ (int) stuff->width, (int) stuff->height,
+ stuff->planeMask);
+}
+
+int
+ProcPolyText(ClientPtr client)
+{
+ int err;
+
+ REQUEST(xPolyTextReq);
+ DrawablePtr pDraw;
+ GC *pGC;
+
+ REQUEST_AT_LEAST_SIZE(xPolyTextReq);
+ VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
+
+ err = PolyText(client,
+ pDraw,
+ pGC,
+ (unsigned char *) &stuff[1],
+ ((unsigned char *) stuff) + (client->req_len << 2),
+ stuff->x, stuff->y, stuff->reqType, stuff->drawable);
+
+ if (err == Success) {
+ return Success;
+ }
+ else
+ return err;
+}
+
+int
+ProcImageText8(ClientPtr client)
+{
+ int err;
+ DrawablePtr pDraw;
+ GC *pGC;
+
+ REQUEST(xImageTextReq);
+
+ REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars);
+ VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
+
+ err = ImageText(client,
+ pDraw,
+ pGC,
+ stuff->nChars,
+ (unsigned char *) &stuff[1],
+ stuff->x, stuff->y, stuff->reqType, stuff->drawable);
+
+ if (err == Success) {
+ return Success;
+ }
+ else
+ return err;
+}
+
+int
+ProcImageText16(ClientPtr client)
+{
+ int err;
+ DrawablePtr pDraw;
+ GC *pGC;
+
+ REQUEST(xImageTextReq);
+
+ REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars << 1);
+ VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
+
+ err = ImageText(client,
+ pDraw,
+ pGC,
+ stuff->nChars,
+ (unsigned char *) &stuff[1],
+ stuff->x, stuff->y, stuff->reqType, stuff->drawable);
+
+ if (err == Success) {
+ return Success;
+ }
+ else
+ return err;
+}
+
+int
+ProcCreateColormap(ClientPtr client)
+{
+ VisualPtr pVisual;
+ ColormapPtr pmap;
+ Colormap mid;
+ WindowPtr pWin;
+ ScreenPtr pScreen;
+
+ REQUEST(xCreateColormapReq);
+ int i, result;
+
+ REQUEST_SIZE_MATCH(xCreateColormapReq);
+
+ if ((stuff->alloc != AllocNone) && (stuff->alloc != AllocAll)) {
+ client->errorValue = stuff->alloc;
+ return BadValue;
+ }
+ mid = stuff->mid;
+ LEGAL_NEW_RESOURCE(mid, client);
+ result = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess);
+ if (result != Success)
+ return result;
+
+ pScreen = pWin->drawable.pScreen;
+ for (i = 0, pVisual = pScreen->visuals;
+ i < pScreen->numVisuals; i++, pVisual++) {
+ if (pVisual->vid != stuff->visual)
+ continue;
+ return CreateColormap(mid, pScreen, pVisual, &pmap,
+ (int) stuff->alloc, client->index);
+ }
+ client->errorValue = stuff->visual;
+ return BadMatch;
+}
+
+int
+ProcFreeColormap(ClientPtr client)
+{
+ ColormapPtr pmap;
+ int rc;
+
+ REQUEST(xResourceReq);
+
+ REQUEST_SIZE_MATCH(xResourceReq);
+ rc = dixLookupResourceByType((void **) &pmap, stuff->id, RT_COLORMAP,
+ client, DixDestroyAccess);
+ if (rc == Success) {
+ /* Freeing a default colormap is a no-op */
+ if (!(pmap->flags & IsDefault))
+ FreeResource(stuff->id, RT_NONE);
+ return Success;
+ }
+ else {
+ client->errorValue = stuff->id;
+ return rc;
+ }
+}
+
+int
+ProcCopyColormapAndFree(ClientPtr client)
+{
+ Colormap mid;
+ ColormapPtr pSrcMap;
+
+ REQUEST(xCopyColormapAndFreeReq);
+ int rc;
+
+ REQUEST_SIZE_MATCH(xCopyColormapAndFreeReq);
+ mid = stuff->mid;
+ LEGAL_NEW_RESOURCE(mid, client);
+ rc = dixLookupResourceByType((void **) &pSrcMap, stuff->srcCmap,
+ RT_COLORMAP, client,
+ DixReadAccess | DixRemoveAccess);
+ if (rc == Success)
+ return CopyColormapAndFree(mid, pSrcMap, client->index);
+ client->errorValue = stuff->srcCmap;
+ return rc;
+}
+
+int
+ProcInstallColormap(ClientPtr client)
+{
+ ColormapPtr pcmp;
+ int rc;
+
+ REQUEST(xResourceReq);
+ REQUEST_SIZE_MATCH(xResourceReq);
+
+ rc = dixLookupResourceByType((void **) &pcmp, stuff->id, RT_COLORMAP,
+ client, DixInstallAccess);
+ if (rc != Success)
+ goto out;
+
+ rc = XaceHook(XACE_SCREEN_ACCESS, client, pcmp->pScreen, DixSetAttrAccess);
+ if (rc != Success) {
+ if (rc == BadValue)
+ rc = BadColor;
+ goto out;
+ }
+
+ (*(pcmp->pScreen->InstallColormap)) (pcmp);
+ return Success;
+
+ out:
+ client->errorValue = stuff->id;
+ return rc;
+}
+
+int
+ProcUninstallColormap(ClientPtr client)
+{
+ ColormapPtr pcmp;
+ int rc;
+
+ REQUEST(xResourceReq);
+ REQUEST_SIZE_MATCH(xResourceReq);
+
+ rc = dixLookupResourceByType((void **) &pcmp, stuff->id, RT_COLORMAP,
+ client, DixUninstallAccess);
+ if (rc != Success)
+ goto out;
+
+ rc = XaceHook(XACE_SCREEN_ACCESS, client, pcmp->pScreen, DixSetAttrAccess);
+ if (rc != Success) {
+ if (rc == BadValue)
+ rc = BadColor;
+ goto out;
+ }
+
+ if (pcmp->mid != pcmp->pScreen->defColormap)
+ (*(pcmp->pScreen->UninstallColormap)) (pcmp);
+ return Success;
+
+ out:
+ client->errorValue = stuff->id;
+ return rc;
+}
+
+int
+ProcListInstalledColormaps(ClientPtr client)
+{
+ xListInstalledColormapsReply *preply;
+ int nummaps, rc;
+ WindowPtr pWin;
+
+ REQUEST(xResourceReq);
+ REQUEST_SIZE_MATCH(xResourceReq);
+
+ rc = dixLookupWindow(&pWin, stuff->id, client, DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+
+ rc = XaceHook(XACE_SCREEN_ACCESS, client, pWin->drawable.pScreen,
+ DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+
+ preply = malloc(sizeof(xListInstalledColormapsReply) +
+ pWin->drawable.pScreen->maxInstalledCmaps *
+ sizeof(Colormap));
+ if (!preply)
+ return BadAlloc;
+
+ preply->type = X_Reply;
+ preply->sequenceNumber = client->sequence;
+ nummaps = (*pWin->drawable.pScreen->ListInstalledColormaps)
+ (pWin->drawable.pScreen, (Colormap *) &preply[1]);
+ preply->nColormaps = nummaps;
+ preply->length = nummaps;
+ WriteReplyToClient(client, sizeof(xListInstalledColormapsReply), preply);
+ client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
+ WriteSwappedDataToClient(client, nummaps * sizeof(Colormap), &preply[1]);
+ free(preply);
+ return Success;
+}
+
+int
+ProcAllocColor(ClientPtr client)
+{
+ ColormapPtr pmap;
+ int rc;
+
+ REQUEST(xAllocColorReq);
+
+ REQUEST_SIZE_MATCH(xAllocColorReq);
+ rc = dixLookupResourceByType((void **) &pmap, stuff->cmap, RT_COLORMAP,
+ client, DixAddAccess);
+ if (rc == Success) {
+ xAllocColorReply acr;
+ acr.type = X_Reply;
+ acr.sequenceNumber = client->sequence;
+ acr.length = 0;
+ acr.red = stuff->red;
+ acr.green = stuff->green;
+ acr.blue = stuff->blue;
+ acr.pixel = 0;
+ if ((rc = AllocColor(pmap, &acr.red, &acr.green, &acr.blue,
+ &acr.pixel, client->index)))
+ return rc;
+#ifdef PANORAMIX
+ if (noPanoramiXExtension || !pmap->pScreen->myNum)
+#endif
+ WriteReplyToClient(client, sizeof(xAllocColorReply), &acr);
+ return Success;
+
+ }
+ else {
+ client->errorValue = stuff->cmap;
+ return rc;
+ }
+}
+
+int
+ProcAllocNamedColor(ClientPtr client)
+{
+ ColormapPtr pcmp;
+ int rc;
+
+ REQUEST(xAllocNamedColorReq);
+
+ REQUEST_FIXED_SIZE(xAllocNamedColorReq, stuff->nbytes);
+ rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP,
+ client, DixAddAccess);
+ if (rc == Success) {
+ xAllocNamedColorReply ancr;
+ ancr.type = X_Reply;
+ ancr.sequenceNumber = client->sequence;
+ ancr.length = 0;
+
+ if (OsLookupColor
+ (pcmp->pScreen->myNum, (char *) &stuff[1], stuff->nbytes,
+ &ancr.exactRed, &ancr.exactGreen, &ancr.exactBlue)) {
+ ancr.screenRed = ancr.exactRed;
+ ancr.screenGreen = ancr.exactGreen;
+ ancr.screenBlue = ancr.exactBlue;
+ ancr.pixel = 0;
+ if ((rc = AllocColor(pcmp,
+ &ancr.screenRed, &ancr.screenGreen,
+ &ancr.screenBlue, &ancr.pixel, client->index)))
+ return rc;
+#ifdef PANORAMIX
+ if (noPanoramiXExtension || !pcmp->pScreen->myNum)
+#endif
+ WriteReplyToClient(client, sizeof(xAllocNamedColorReply),
+ &ancr);
+ return Success;
+ }
+ else
+ return BadName;
+
+ }
+ else {
+ client->errorValue = stuff->cmap;
+ return rc;
+ }
+}
+
+int
+ProcAllocColorCells(ClientPtr client)
+{
+ ColormapPtr pcmp;
+ int rc;
+
+ REQUEST(xAllocColorCellsReq);
+
+ REQUEST_SIZE_MATCH(xAllocColorCellsReq);
+ rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP,
+ client, DixAddAccess);
+ if (rc == Success) {
+ int npixels, nmasks;
+ long length;
+ Pixel *ppixels, *pmasks;
+
+ npixels = stuff->colors;
+ if (!npixels) {
+ client->errorValue = npixels;
+ return BadValue;
+ }
+ if (stuff->contiguous != xTrue && stuff->contiguous != xFalse) {
+ client->errorValue = stuff->contiguous;
+ return BadValue;
+ }
+ nmasks = stuff->planes;
+ length = ((long) npixels + (long) nmasks) * sizeof(Pixel);
+ ppixels = malloc(length);
+ if (!ppixels)
+ return BadAlloc;
+ pmasks = ppixels + npixels;
+
+ if ((rc = AllocColorCells(client->index, pcmp, npixels, nmasks,
+ (Bool) stuff->contiguous, ppixels, pmasks))) {
+ free(ppixels);
+ return rc;
+ }
+#ifdef PANORAMIX
+ if (noPanoramiXExtension || !pcmp->pScreen->myNum)
+#endif
+ {
+ xAllocColorCellsReply accr;
+ accr.type = X_Reply;
+ accr.sequenceNumber = client->sequence;
+ accr.length = bytes_to_int32(length);
+ accr.nPixels = npixels;
+ accr.nMasks = nmasks;
+ WriteReplyToClient(client, sizeof(xAllocColorCellsReply), &accr);
+ client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
+ WriteSwappedDataToClient(client, length, ppixels);
+ }
+ free(ppixels);
+ return Success;
+ }
+ else {
+ client->errorValue = stuff->cmap;
+ return rc;
+ }
+}
+
+int
+ProcAllocColorPlanes(ClientPtr client)
+{
+ ColormapPtr pcmp;
+ int rc;
+
+ REQUEST(xAllocColorPlanesReq);
+
+ REQUEST_SIZE_MATCH(xAllocColorPlanesReq);
+ rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP,
+ client, DixAddAccess);
+ if (rc == Success) {
+ xAllocColorPlanesReply acpr;
+ int npixels;
+ long length;
+ Pixel *ppixels;
+
+ npixels = stuff->colors;
+ if (!npixels) {
+ client->errorValue = npixels;
+ return BadValue;
+ }
+ if (stuff->contiguous != xTrue && stuff->contiguous != xFalse) {
+ client->errorValue = stuff->contiguous;
+ return BadValue;
+ }
+
+ acpr.type = X_Reply;
+ acpr.sequenceNumber = client->sequence;
+ acpr.nPixels = npixels;
+
+ length = (long) npixels *sizeof(Pixel);
+
+ ppixels = malloc(length);
+ if (!ppixels)
+ return BadAlloc;
+ if ((rc = AllocColorPlanes(client->index, pcmp, npixels,
+ (int) stuff->red, (int) stuff->green,
+ (int) stuff->blue, (Bool) stuff->contiguous,
+ ppixels, &acpr.redMask, &acpr.greenMask,
+ &acpr.blueMask))) {
+ free(ppixels);
+ return rc;
+ }
+ acpr.length = bytes_to_int32(length);
+#ifdef PANORAMIX
+ if (noPanoramiXExtension || !pcmp->pScreen->myNum)
+#endif
+ {
+ WriteReplyToClient(client, sizeof(xAllocColorPlanesReply), &acpr);
+ client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write;
+ WriteSwappedDataToClient(client, length, ppixels);
+ }
+ free(ppixels);
+ return Success;
+ }
+ else {
+ client->errorValue = stuff->cmap;
+ return rc;
+ }
+}
+
+int
+ProcFreeColors(ClientPtr client)
+{
+ ColormapPtr pcmp;
+ int rc;
+
+ REQUEST(xFreeColorsReq);
+
+ REQUEST_AT_LEAST_SIZE(xFreeColorsReq);
+ rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP,
+ client, DixRemoveAccess);
+ if (rc == Success) {
+ int count;
+
+ if (pcmp->flags & AllAllocated)
+ return BadAccess;
+ count = bytes_to_int32((client->req_len << 2) - sizeof(xFreeColorsReq));
+ return FreeColors(pcmp, client->index, count,
+ (Pixel *) &stuff[1], (Pixel) stuff->planeMask);
+ }
+ else {
+ client->errorValue = stuff->cmap;
+ return rc;
+ }
+}
+
+int
+ProcStoreColors(ClientPtr client)
+{
+ ColormapPtr pcmp;
+ int rc;
+
+ REQUEST(xStoreColorsReq);
+
+ REQUEST_AT_LEAST_SIZE(xStoreColorsReq);
+ rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP,
+ client, DixWriteAccess);
+ if (rc == Success) {
+ int count;
+
+ count = (client->req_len << 2) - sizeof(xStoreColorsReq);
+ if (count % sizeof(xColorItem))
+ return BadLength;
+ count /= sizeof(xColorItem);
+ return StoreColors(pcmp, count, (xColorItem *) &stuff[1], client);
+ }
+ else {
+ client->errorValue = stuff->cmap;
+ return rc;
+ }
+}
+
+int
+ProcStoreNamedColor(ClientPtr client)
+{
+ ColormapPtr pcmp;
+ int rc;
+
+ REQUEST(xStoreNamedColorReq);
+
+ REQUEST_FIXED_SIZE(xStoreNamedColorReq, stuff->nbytes);
+ rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP,
+ client, DixWriteAccess);
+ if (rc == Success) {
+ xColorItem def;
+
+ if (OsLookupColor(pcmp->pScreen->myNum, (char *) &stuff[1],
+ stuff->nbytes, &def.red, &def.green, &def.blue)) {
+ def.flags = stuff->flags;
+ def.pixel = stuff->pixel;
+ return StoreColors(pcmp, 1, &def, client);
+ }
+ return BadName;
+ }
+ else {
+ client->errorValue = stuff->cmap;
+ return rc;
+ }
+}
+
+int
+ProcQueryColors(ClientPtr client)
+{
+ ColormapPtr pcmp;
+ int rc;
+
+ REQUEST(xQueryColorsReq);
+
+ REQUEST_AT_LEAST_SIZE(xQueryColorsReq);
+ rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP,
+ client, DixReadAccess);
+ if (rc == Success) {
+ int count;
+ xrgb *prgbs;
+ xQueryColorsReply qcr;
+
+ count =
+ bytes_to_int32((client->req_len << 2) - sizeof(xQueryColorsReq));
+ prgbs = calloc(1, count * sizeof(xrgb));
+ if (!prgbs && count)
+ return BadAlloc;
+ if ((rc =
+ QueryColors(pcmp, count, (Pixel *) &stuff[1], prgbs, client))) {
+ free(prgbs);
+ return rc;
+ }
+ memset(&qcr, 0, sizeof(xQueryColorsReply));
+ qcr.type = X_Reply;
+ qcr.sequenceNumber = client->sequence;
+ qcr.length = bytes_to_int32(count * sizeof(xrgb));
+ qcr.nColors = count;
+
+ WriteReplyToClient(client, sizeof(xQueryColorsReply), &qcr);
+ if (count) {
+ client->pSwapReplyFunc = (ReplySwapPtr) SQColorsExtend;
+ WriteSwappedDataToClient(client, count * sizeof(xrgb), prgbs);
+ }
+ free(prgbs);
+ return Success;
+
+ }
+ else {
+ client->errorValue = stuff->cmap;
+ return rc;
+ }
+}
+
+int
+ProcLookupColor(ClientPtr client)
+{
+ ColormapPtr pcmp;
+ int rc;
+
+ REQUEST(xLookupColorReq);
+
+ REQUEST_FIXED_SIZE(xLookupColorReq, stuff->nbytes);
+ rc = dixLookupResourceByType((void **) &pcmp, stuff->cmap, RT_COLORMAP,
+ client, DixReadAccess);
+ if (rc == Success) {
+ CARD16 exactRed, exactGreen, exactBlue;
+
+ if (OsLookupColor
+ (pcmp->pScreen->myNum, (char *) &stuff[1], stuff->nbytes,
+ &exactRed, &exactGreen, &exactBlue)) {
+ xLookupColorReply lcr;
+ lcr.type = X_Reply;
+ lcr.sequenceNumber = client->sequence;
+ lcr.length = 0;
+ lcr.exactRed = exactRed;
+ lcr.exactGreen = exactGreen;
+ lcr.exactBlue = exactBlue;
+ lcr.screenRed = exactRed;
+ lcr.screenGreen = exactGreen;
+ lcr.screenBlue = exactBlue;
+
+ (*pcmp->pScreen->ResolveColor) (&lcr.screenRed,
+ &lcr.screenGreen,
+ &lcr.screenBlue, pcmp->pVisual);
+ WriteReplyToClient(client, sizeof(xLookupColorReply), &lcr);
+ return Success;
+ }
+ return BadName;
+ }
+ else {
+ client->errorValue = stuff->cmap;
+ return rc;
+ }
+}
+
+int
+ProcCreateCursor(ClientPtr client)
+{
+ CursorPtr pCursor;
+ PixmapPtr src;
+ PixmapPtr msk;
+ unsigned char *srcbits;
+ unsigned char *mskbits;
+ unsigned short width, height;
+ long n;
+ CursorMetricRec cm;
+ int rc;
+
+ REQUEST(xCreateCursorReq);
+
+ REQUEST_SIZE_MATCH(xCreateCursorReq);
+ LEGAL_NEW_RESOURCE(stuff->cid, client);
+
+ rc = dixLookupResourceByType((void **) &src, stuff->source, RT_PIXMAP,
+ client, DixReadAccess);
+ if (rc != Success) {
+ client->errorValue = stuff->source;
+ return rc;
+ }
+
+ if (src->drawable.depth != 1)
+ return (BadMatch);
+
+ /* Find and validate cursor mask pixmap, if one is provided */
+ if (stuff->mask != None) {
+ rc = dixLookupResourceByType((void **) &msk, stuff->mask, RT_PIXMAP,
+ client, DixReadAccess);
+ if (rc != Success) {
+ client->errorValue = stuff->mask;
+ return rc;
+ }
+
+ if (src->drawable.width != msk->drawable.width
+ || src->drawable.height != msk->drawable.height
+ || src->drawable.depth != 1 || msk->drawable.depth != 1)
+ return BadMatch;
+ }
+ else
+ msk = NULL;
+
+ width = src->drawable.width;
+ height = src->drawable.height;
+
+ if (stuff->x > width || stuff->y > height)
+ return BadMatch;
+
+ n = BitmapBytePad(width) * height;
+ srcbits = calloc(1, n);
+ if (!srcbits)
+ return BadAlloc;
+ mskbits = malloc(n);
+ if (!mskbits) {
+ free(srcbits);
+ return BadAlloc;
+ }
+
+ (*src->drawable.pScreen->GetImage) ((DrawablePtr) src, 0, 0, width, height,
+ XYPixmap, 1, (void *) srcbits);
+ if (msk == (PixmapPtr) NULL) {
+ unsigned char *bits = mskbits;
+
+ while (--n >= 0)
+ *bits++ = ~0;
+ }
+ else {
+ /* zeroing the (pad) bits helps some ddx cursor handling */
+ memset((char *) mskbits, 0, n);
+ (*msk->drawable.pScreen->GetImage) ((DrawablePtr) msk, 0, 0, width,
+ height, XYPixmap, 1,
+ (void *) mskbits);
+ }
+ cm.width = width;
+ cm.height = height;
+ cm.xhot = stuff->x;
+ cm.yhot = stuff->y;
+ rc = AllocARGBCursor(srcbits, mskbits, NULL, &cm,
+ stuff->foreRed, stuff->foreGreen, stuff->foreBlue,
+ stuff->backRed, stuff->backGreen, stuff->backBlue,
+ &pCursor, client, stuff->cid);
+
+ if (rc != Success)
+ goto bail;
+ if (!AddResource(stuff->cid, RT_CURSOR, (void *) pCursor)) {
+ rc = BadAlloc;
+ goto bail;
+ }
+
+ return Success;
+ bail:
+ free(srcbits);
+ free(mskbits);
+ return rc;
+}
+
+int
+ProcCreateGlyphCursor(ClientPtr client)
+{
+ CursorPtr pCursor;
+ int res;
+
+ REQUEST(xCreateGlyphCursorReq);
+
+ REQUEST_SIZE_MATCH(xCreateGlyphCursorReq);
+ LEGAL_NEW_RESOURCE(stuff->cid, client);
+
+ res = AllocGlyphCursor(stuff->source, stuff->sourceChar,
+ stuff->mask, stuff->maskChar,
+ stuff->foreRed, stuff->foreGreen, stuff->foreBlue,
+ stuff->backRed, stuff->backGreen, stuff->backBlue,
+ &pCursor, client, stuff->cid);
+ if (res != Success)
+ return res;
+ if (AddResource(stuff->cid, RT_CURSOR, (void *) pCursor))
+ return Success;
+ return BadAlloc;
+}
+
+int
+ProcFreeCursor(ClientPtr client)
+{
+ CursorPtr pCursor;
+ int rc;
+
+ REQUEST(xResourceReq);
+
+ REQUEST_SIZE_MATCH(xResourceReq);
+ rc = dixLookupResourceByType((void **) &pCursor, stuff->id, RT_CURSOR,
+ client, DixDestroyAccess);
+ if (rc == Success) {
+ FreeResource(stuff->id, RT_NONE);
+ return Success;
+ }
+ else {
+ client->errorValue = stuff->id;
+ return rc;
+ }
+}
+
+int
+ProcQueryBestSize(ClientPtr client)
+{
+ xQueryBestSizeReply reply;
+ DrawablePtr pDraw;
+ ScreenPtr pScreen;
+ int rc;
+
+ REQUEST(xQueryBestSizeReq);
+ REQUEST_SIZE_MATCH(xQueryBestSizeReq);
+
+ if ((stuff->class != CursorShape) &&
+ (stuff->class != TileShape) && (stuff->class != StippleShape)) {
+ client->errorValue = stuff->class;
+ return BadValue;
+ }
+
+ rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY,
+ DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+ if (stuff->class != CursorShape && pDraw->type == UNDRAWABLE_WINDOW)
+ return BadMatch;
+ pScreen = pDraw->pScreen;
+ rc = XaceHook(XACE_SCREEN_ACCESS, client, pScreen, DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+ (*pScreen->QueryBestSize) (stuff->class, &stuff->width,
+ &stuff->height, pScreen);
+ memset(&reply, 0, sizeof(xQueryBestSizeReply));
+ reply.type = X_Reply;
+ reply.sequenceNumber = client->sequence;
+ reply.length = 0;
+ reply.width = stuff->width;
+ reply.height = stuff->height;
+
+ WriteReplyToClient(client, sizeof(xQueryBestSizeReply), &reply);
+ return Success;
+}
+
+int
+ProcSetScreenSaver(ClientPtr client)
+{
+ int rc, i, blankingOption, exposureOption;
+
+ REQUEST(xSetScreenSaverReq);
+ REQUEST_SIZE_MATCH(xSetScreenSaverReq);
+
+ for (i = 0; i < screenInfo.numScreens; i++) {
+ rc = XaceHook(XACE_SCREENSAVER_ACCESS, client, screenInfo.screens[i],
+ DixSetAttrAccess);
+ if (rc != Success)
+ return rc;
+ }
+
+ blankingOption = stuff->preferBlank;
+ if ((blankingOption != DontPreferBlanking) &&
+ (blankingOption != PreferBlanking) &&
+ (blankingOption != DefaultBlanking)) {
+ client->errorValue = blankingOption;
+ return BadValue;
+ }
+ exposureOption = stuff->allowExpose;
+ if ((exposureOption != DontAllowExposures) &&
+ (exposureOption != AllowExposures) &&
+ (exposureOption != DefaultExposures)) {
+ client->errorValue = exposureOption;
+ return BadValue;
+ }
+ if (stuff->timeout < -1) {
+ client->errorValue = stuff->timeout;
+ return BadValue;
+ }
+ if (stuff->interval < -1) {
+ client->errorValue = stuff->interval;
+ return BadValue;
+ }
+
+ if (blankingOption == DefaultBlanking)
+ ScreenSaverBlanking = defaultScreenSaverBlanking;
+ else
+ ScreenSaverBlanking = blankingOption;
+ if (exposureOption == DefaultExposures)
+ ScreenSaverAllowExposures = defaultScreenSaverAllowExposures;
+ else
+ ScreenSaverAllowExposures = exposureOption;
+
+ if (stuff->timeout >= 0)
+ ScreenSaverTime = stuff->timeout * MILLI_PER_SECOND;
+ else
+ ScreenSaverTime = defaultScreenSaverTime;
+ if (stuff->interval >= 0)
+ ScreenSaverInterval = stuff->interval * MILLI_PER_SECOND;
+ else
+ ScreenSaverInterval = defaultScreenSaverInterval;
+
+ SetScreenSaverTimer();
+ return Success;
+}
+
+int
+ProcGetScreenSaver(ClientPtr client)
+{
+ xGetScreenSaverReply rep;
+ int rc, i;
+
+ REQUEST_SIZE_MATCH(xReq);
+
+ for (i = 0; i < screenInfo.numScreens; i++) {
+ rc = XaceHook(XACE_SCREENSAVER_ACCESS, client, screenInfo.screens[i],
+ DixGetAttrAccess);
+ if (rc != Success)
+ return rc;
+ }
+
+
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.length = 0;
+ rep.timeout = ScreenSaverTime / MILLI_PER_SECOND;
+ rep.interval = ScreenSaverInterval / MILLI_PER_SECOND;
+ rep.preferBlanking = ScreenSaverBlanking;
+ rep.allowExposures = ScreenSaverAllowExposures;
+
+ WriteReplyToClient(client, sizeof(xGetScreenSaverReply), &rep);
+ return Success;
+}
+
+int
+ProcChangeHosts(ClientPtr client)
+{
+ REQUEST(xChangeHostsReq);
+
+ REQUEST_FIXED_SIZE(xChangeHostsReq, stuff->hostLength);
+
+ if (stuff->mode == HostInsert)
+ return AddHost(client, (int) stuff->hostFamily,
+ stuff->hostLength, (void *) &stuff[1]);
+ if (stuff->mode == HostDelete)
+ return RemoveHost(client, (int) stuff->hostFamily,
+ stuff->hostLength, (void *) &stuff[1]);
+ client->errorValue = stuff->mode;
+ return BadValue;
+}
+
+int
+ProcListHosts(ClientPtr client)
+{
+ xListHostsReply reply;
+ int len, nHosts, result;
+ BOOL enabled;
+ void *pdata;
+
+ /* REQUEST(xListHostsReq); */
+
+ REQUEST_SIZE_MATCH(xListHostsReq);
+
+ /* untrusted clients can't list hosts */
+ result = XaceHook(XACE_SERVER_ACCESS, client, DixReadAccess);
+ if (result != Success)
+ return result;
+
+ result = GetHosts(&pdata, &nHosts, &len, &enabled);
+ if (result != Success)
+ return result;
+
+
+ reply.type = X_Reply;
+ reply.enabled = enabled;
+ reply.sequenceNumber = client->sequence;
+ reply.length = bytes_to_int32(len);
+ reply.nHosts = nHosts;
+
+ WriteReplyToClient(client, sizeof(xListHostsReply), &reply);
+ if (nHosts) {
+ client->pSwapReplyFunc = (ReplySwapPtr) SLHostsExtend;
+ WriteSwappedDataToClient(client, len, pdata);
+ }
+ free(pdata);
+ return Success;
+}
+
+int
+ProcChangeAccessControl(ClientPtr client)
+{
+ REQUEST(xSetAccessControlReq);
+
+ REQUEST_SIZE_MATCH(xSetAccessControlReq);
+ if ((stuff->mode != EnableAccess) && (stuff->mode != DisableAccess)) {
+ client->errorValue = stuff->mode;
+ return BadValue;
+ }
+ return ChangeAccessControl(client, stuff->mode == EnableAccess);
+}
+
+/*********************
+ * CloseDownRetainedResources
+ *
+ * Find all clients that are gone and have terminated in RetainTemporary
+ * and destroy their resources.
+ *********************/
+
+static void
+CloseDownRetainedResources(void)
+{
+ int i;
+ ClientPtr client;
+
+ for (i = 1; i < currentMaxClients; i++) {
+ client = clients[i];
+ if (client && (client->closeDownMode == RetainTemporary)
+ && (client->clientGone))
+ CloseDownClient(client);
+ }
+}
+
+int
+ProcKillClient(ClientPtr client)
+{
+ REQUEST(xResourceReq);
+ ClientPtr killclient;
+ int rc;
+
+ REQUEST_SIZE_MATCH(xResourceReq);
+ if (stuff->id == AllTemporary) {
+ CloseDownRetainedResources();
+ return Success;
+ }
+
+ rc = dixLookupClient(&killclient, stuff->id, client, DixDestroyAccess);
+ if (rc == Success) {
+ CloseDownClient(killclient);
+ if (client == killclient) {
+ /* force yield and return Success, so that Dispatch()
+ * doesn't try to touch client
+ */
+ isItTimeToYield = TRUE;
+ }
+ return Success;
+ }
+ else
+ return rc;
+}
+
+int
+ProcSetFontPath(ClientPtr client)
+{
+ unsigned char *ptr;
+ unsigned long nbytes, total;
+ long nfonts;
+ int n;
+
+ REQUEST(xSetFontPathReq);
+
+ REQUEST_AT_LEAST_SIZE(xSetFontPathReq);
+
+ nbytes = (client->req_len << 2) - sizeof(xSetFontPathReq);
+ total = nbytes;
+ ptr = (unsigned char *) &stuff[1];
+ nfonts = stuff->nFonts;
+ while (--nfonts >= 0) {
+ if ((total == 0) || (total < (n = (*ptr + 1))))
+ return BadLength;
+ total -= n;
+ ptr += n;
+ }
+ if (total >= 4)
+ return BadLength;
+ return SetFontPath(client, stuff->nFonts, (unsigned char *) &stuff[1]);
+}
+
+int
+ProcGetFontPath(ClientPtr client)
+{
+ xGetFontPathReply reply;
+ int rc, stringLens, numpaths;
+ unsigned char *bufferStart;
+
+ /* REQUEST (xReq); */
+
+ REQUEST_SIZE_MATCH(xReq);
+ rc = GetFontPath(client, &numpaths, &stringLens, &bufferStart);
+ if (rc != Success)
+ return rc;
+
+
+ reply.type = X_Reply;
+ reply.sequenceNumber = client->sequence;
+ reply.length = bytes_to_int32(stringLens + numpaths);
+ reply.nPaths = numpaths;
+
+ WriteReplyToClient(client, sizeof(xGetFontPathReply), &reply);
+ if (stringLens || numpaths)
+ WriteToClient(client, stringLens + numpaths, bufferStart);
+ return Success;
+}
+
+int
+ProcChangeCloseDownMode(ClientPtr client)
+{
+ int rc;
+
+ REQUEST(xSetCloseDownModeReq);
+ REQUEST_SIZE_MATCH(xSetCloseDownModeReq);
+
+ rc = XaceHook(XACE_CLIENT_ACCESS, client, client, DixManageAccess);
+ if (rc != Success)
+ return rc;
+
+ if ((stuff->mode == AllTemporary) ||
+ (stuff->mode == RetainPermanent) || (stuff->mode == RetainTemporary)) {
+ client->closeDownMode = stuff->mode;
+ return Success;
+ }
+ else {
+ client->errorValue = stuff->mode;
+ return BadValue;
+ }
+}
+
+int
+ProcForceScreenSaver(ClientPtr client)
+{
+ int rc;
+
+ REQUEST(xForceScreenSaverReq);
+
+ REQUEST_SIZE_MATCH(xForceScreenSaverReq);
+
+ if ((stuff->mode != ScreenSaverReset) && (stuff->mode != ScreenSaverActive)) {
+ client->errorValue = stuff->mode;
+ return BadValue;
+ }
+ rc = dixSaveScreens(client, SCREEN_SAVER_FORCER, (int) stuff->mode);
+ if (rc != Success)
+ return rc;
+ return Success;
+}
+
+int
+ProcNoOperation(ClientPtr client)
+{
+ REQUEST_AT_LEAST_SIZE(xReq);
+
+ /* noop -- don't do anything */
+ return Success;
+}
+
+/**********************
+ * CloseDownClient
+ *
+ * Client can either mark his resources destroy or retain. If retained and
+ * then killed again, the client is really destroyed.
+ *********************/
+
+char dispatchExceptionAtReset = DE_RESET;
+
+void
+CloseDownClient(ClientPtr client)
+{
+ Bool really_close_down = client->clientGone ||
+ client->closeDownMode == DestroyAll;
+
+ if (!client->clientGone) {
+ /* ungrab server if grabbing client dies */
+ if (grabState != GrabNone && grabClient == client) {
+ UngrabServer(client);
+ }
+ BITCLEAR(grabWaiters, client->index);
+ DeleteClientFromAnySelections(client);
+ ReleaseActiveGrabs(client);
+ DeleteClientFontStuff(client);
+ if (!really_close_down) {
+ /* This frees resources that should never be retained
+ * no matter what the close down mode is. Actually we
+ * could do this unconditionally, but it's probably
+ * better not to traverse all the client's resources
+ * twice (once here, once a few lines down in
+ * FreeClientResources) in the common case of
+ * really_close_down == TRUE.
+ */
+ FreeClientNeverRetainResources(client);
+ client->clientState = ClientStateRetained;
+ if (ClientStateCallback) {
+ NewClientInfoRec clientinfo;
+
+ clientinfo.client = client;
+ clientinfo.prefix = (xConnSetupPrefix *) NULL;
+ clientinfo.setup = (xConnSetup *) NULL;
+ CallCallbacks((&ClientStateCallback), (void *) &clientinfo);
+ }
+ }
+ client->clientGone = TRUE; /* so events aren't sent to client */
+ if (ClientIsAsleep(client))
+ ClientSignal(client);
+ ProcessWorkQueueZombies();
+ CloseDownConnection(client);
+
+ /* If the client made it to the Running stage, nClients has
+ * been incremented on its behalf, so we need to decrement it
+ * now. If it hasn't gotten to Running, nClients has *not*
+ * been incremented, so *don't* decrement it.
+ */
+ if (client->clientState != ClientStateInitial) {
+ --nClients;
+ }
+ }
+
+ if (really_close_down) {
+ if (client->clientState == ClientStateRunning && nClients == 0)
+ dispatchException |= dispatchExceptionAtReset;
+
+ client->clientState = ClientStateGone;
+ if (ClientStateCallback) {
+ NewClientInfoRec clientinfo;
+
+ clientinfo.client = client;
+ clientinfo.prefix = (xConnSetupPrefix *) NULL;
+ clientinfo.setup = (xConnSetup *) NULL;
+ CallCallbacks((&ClientStateCallback), (void *) &clientinfo);
+ }
+ TouchListenerGone(client->clientAsMask);
+ FreeClientResources(client);
+ /* Disable client ID tracking. This must be done after
+ * ClientStateCallback. */
+ ReleaseClientIds(client);
+#ifdef XSERVER_DTRACE
+ XSERVER_CLIENT_DISCONNECT(client->index);
+#endif
+ if (client->index < nextFreeClientID)
+ nextFreeClientID = client->index;
+ clients[client->index] = NullClient;
+ SmartLastClient = NullClient;
+ dixFreeObjectWithPrivates(client, PRIVATE_CLIENT);
+
+ while (!clients[currentMaxClients - 1])
+ currentMaxClients--;
+ }
+}
+
+static void
+KillAllClients(void)
+{
+ int i;
+
+ for (i = 1; i < currentMaxClients; i++)
+ if (clients[i]) {
+ /* Make sure Retained clients are released. */
+ clients[i]->closeDownMode = DestroyAll;
+ CloseDownClient(clients[i]);
+ }
+}
+
+void
+InitClient(ClientPtr client, int i, void *ospriv)
+{
+ client->index = i;
+ client->clientAsMask = ((Mask) i) << CLIENTOFFSET;
+ client->closeDownMode = i ? DestroyAll : RetainPermanent;
+ client->requestVector = InitialVector;
+ client->osPrivate = ospriv;
+ QueryMinMaxKeyCodes(&client->minKC, &client->maxKC);
+ client->smart_start_tick = SmartScheduleTime;
+ client->smart_stop_tick = SmartScheduleTime;
+ client->clientIds = NULL;
+}
+
+/************************
+ * int NextAvailableClient(ospriv)
+ *
+ * OS dependent portion can't assign client id's because of CloseDownModes.
+ * Returns NULL if there are no free clients.
+ *************************/
+
+ClientPtr
+NextAvailableClient(void *ospriv)
+{
+ int i;
+ ClientPtr client;
+ xReq data;
+
+ i = nextFreeClientID;
+ if (i == MAXCLIENTS)
+ return (ClientPtr) NULL;
+ clients[i] = client =
+ dixAllocateObjectWithPrivates(ClientRec, PRIVATE_CLIENT);
+ if (!client)
+ return (ClientPtr) NULL;
+ InitClient(client, i, ospriv);
+ if (!InitClientResources(client)) {
+ dixFreeObjectWithPrivates(client, PRIVATE_CLIENT);
+ return (ClientPtr) NULL;
+ }
+ data.reqType = 1;
+ data.length = bytes_to_int32(sz_xReq + sz_xConnClientPrefix);
+ if (!InsertFakeRequest(client, (char *) &data, sz_xReq)) {
+ FreeClientResources(client);
+ dixFreeObjectWithPrivates(client, PRIVATE_CLIENT);
+ return (ClientPtr) NULL;
+ }
+ if (i == currentMaxClients)
+ currentMaxClients++;
+ while ((nextFreeClientID < MAXCLIENTS) && clients[nextFreeClientID])
+ nextFreeClientID++;
+
+ /* Enable client ID tracking. This must be done before
+ * ClientStateCallback. */
+ ReserveClientIds(client);
+
+ if (ClientStateCallback) {
+ NewClientInfoRec clientinfo;
+
+ clientinfo.client = client;
+ clientinfo.prefix = (xConnSetupPrefix *) NULL;
+ clientinfo.setup = (xConnSetup *) NULL;
+ CallCallbacks((&ClientStateCallback), (void *) &clientinfo);
+ }
+ return client;
+}
+
+int
+ProcInitialConnection(ClientPtr client)
+{
+ REQUEST(xReq);
+ xConnClientPrefix *prefix;
+ int whichbyte = 1;
+ char order;
+
+ prefix = (xConnClientPrefix *) ((char *)stuff + sz_xReq);
+ order = prefix->byteOrder;
+ if (order != 'l' && order != 'B' && order != 'r' && order != 'R')
+ return client->noClientException = -1;
+ if (((*(char *) &whichbyte) && (order == 'B' || order == 'R')) ||
+ (!(*(char *) &whichbyte) && (order == 'l' || order == 'r'))) {
+ client->swapped = TRUE;
+ SwapConnClientPrefix(prefix);
+ }
+ stuff->reqType = 2;
+ stuff->length += bytes_to_int32(prefix->nbytesAuthProto) +
+ bytes_to_int32(prefix->nbytesAuthString);
+ if (client->swapped) {
+ swaps(&stuff->length);
+ }
+ if (order == 'r' || order == 'R') {
+ client->local = FALSE;
+ }
+ ResetCurrentRequest(client);
+ return Success;
+}
+
+static int
+SendConnSetup(ClientPtr client, const char *reason)
+{
+ xWindowRoot *root;
+ int i;
+ int numScreens;
+ char *lConnectionInfo;
+ xConnSetupPrefix *lconnSetupPrefix;
+
+ if (reason) {
+ xConnSetupPrefix csp;
+
+ csp.success = xFalse;
+ csp.lengthReason = strlen(reason);
+ csp.length = bytes_to_int32(csp.lengthReason);
+ csp.majorVersion = X_PROTOCOL;
+ csp.minorVersion = X_PROTOCOL_REVISION;
+ if (client->swapped)
+ WriteSConnSetupPrefix(client, &csp);
+ else
+ WriteToClient(client, sz_xConnSetupPrefix, &csp);
+ WriteToClient(client, (int) csp.lengthReason, reason);
+ return client->noClientException = -1;
+ }
+
+ numScreens = screenInfo.numScreens;
+ lConnectionInfo = ConnectionInfo;
+ lconnSetupPrefix = &connSetupPrefix;
+
+ /* We're about to start speaking X protocol back to the client by
+ * sending the connection setup info. This means the authorization
+ * step is complete, and we can count the client as an
+ * authorized one.
+ */
+ nClients++;
+
+ client->requestVector = client->swapped ? SwappedProcVector : ProcVector;
+ client->sequence = 0;
+ ((xConnSetup *) lConnectionInfo)->ridBase = client->clientAsMask;
+ ((xConnSetup *) lConnectionInfo)->ridMask = RESOURCE_ID_MASK;
+#ifdef MATCH_CLIENT_ENDIAN
+ ((xConnSetup *) lConnectionInfo)->imageByteOrder = ClientOrder(client);
+ ((xConnSetup *) lConnectionInfo)->bitmapBitOrder = ClientOrder(client);
+#endif
+ /* fill in the "currentInputMask" */
+ root = (xWindowRoot *) (lConnectionInfo + connBlockScreenStart);
+#ifdef PANORAMIX
+ if (noPanoramiXExtension)
+ numScreens = screenInfo.numScreens;
+ else
+ numScreens = ((xConnSetup *) ConnectionInfo)->numRoots;
+#endif
+
+ for (i = 0; i < numScreens; i++) {
+ unsigned int j;
+ xDepth *pDepth;
+ WindowPtr pRoot = screenInfo.screens[i]->root;
+
+ root->currentInputMask = pRoot->eventMask | wOtherEventMasks(pRoot);
+ pDepth = (xDepth *) (root + 1);
+ for (j = 0; j < root->nDepths; j++) {
+ pDepth = (xDepth *) (((char *) (pDepth + 1)) +
+ pDepth->nVisuals * sizeof(xVisualType));
+ }
+ root = (xWindowRoot *) pDepth;
+ }
+
+ if (client->swapped) {
+ WriteSConnSetupPrefix(client, lconnSetupPrefix);
+ WriteSConnectionInfo(client,
+ (unsigned long) (lconnSetupPrefix->length << 2),
+ lConnectionInfo);
+ }
+ else {
+ WriteToClient(client, sizeof(xConnSetupPrefix), lconnSetupPrefix);
+ WriteToClient(client, (int) (lconnSetupPrefix->length << 2),
+ lConnectionInfo);
+ }
+ client->clientState = ClientStateRunning;
+ if (ClientStateCallback) {
+ NewClientInfoRec clientinfo;
+
+ clientinfo.client = client;
+ clientinfo.prefix = lconnSetupPrefix;
+ clientinfo.setup = (xConnSetup *) lConnectionInfo;
+ CallCallbacks((&ClientStateCallback), (void *) &clientinfo);
+ }
+ return Success;
+}
+
+int
+ProcEstablishConnection(ClientPtr client)
+{
+ const char *reason;
+ char *auth_proto, *auth_string;
+ xConnClientPrefix *prefix;
+
+ REQUEST(xReq);
+
+ prefix = (xConnClientPrefix *) ((char *) stuff + sz_xReq);
+ auth_proto = (char *) prefix + sz_xConnClientPrefix;
+ auth_string = auth_proto + pad_to_int32(prefix->nbytesAuthProto);
+ if ((prefix->majorVersion != X_PROTOCOL) ||
+ (prefix->minorVersion != X_PROTOCOL_REVISION))
+ reason = "Protocol version mismatch";
+ else
+ reason = ClientAuthorized(client,
+ (unsigned short) prefix->nbytesAuthProto,
+ auth_proto,
+ (unsigned short) prefix->nbytesAuthString,
+ auth_string);
+
+ return (SendConnSetup(client, reason));
+}
+
+void
+SendErrorToClient(ClientPtr client, unsigned majorCode, unsigned minorCode,
+ XID resId, int errorCode)
+{
+ xError rep; memset(&rep, 0, sizeof(xError));
+ rep.type = X_Error;
+ rep.errorCode = errorCode;
+ rep.resourceID = resId;
+ rep.minorCode = minorCode;
+ rep.majorCode = majorCode;
+
+ WriteEventsToClient(client, 1, (xEvent *) &rep);
+}
+
+void
+MarkClientException(ClientPtr client)
+{
+ client->noClientException = -1;
+}
+
+/*
+ * This array encodes the answer to the question "what is the log base 2
+ * of the number of pixels that fit in a scanline pad unit?"
+ * Note that ~0 is an invalid entry (mostly for the benefit of the reader).
+ */
+static int answer[6][4] = {
+ /* pad pad pad pad */
+ /* 8 16 32 64 */
+
+ {3, 4, 5, 6}, /* 1 bit per pixel */
+ {1, 2, 3, 4}, /* 4 bits per pixel */
+ {0, 1, 2, 3}, /* 8 bits per pixel */
+ {~0, 0, 1, 2}, /* 16 bits per pixel */
+ {~0, ~0, 0, 1}, /* 24 bits per pixel */
+ {~0, ~0, 0, 1} /* 32 bits per pixel */
+};
+
+/*
+ * This array gives the answer to the question "what is the first index for
+ * the answer array above given the number of bits per pixel?"
+ * Note that ~0 is an invalid entry (mostly for the benefit of the reader).
+ */
+static int indexForBitsPerPixel[33] = {
+ ~0, 0, ~0, ~0, /* 1 bit per pixel */
+ 1, ~0, ~0, ~0, /* 4 bits per pixel */
+ 2, ~0, ~0, ~0, /* 8 bits per pixel */
+ ~0, ~0, ~0, ~0,
+ 3, ~0, ~0, ~0, /* 16 bits per pixel */
+ ~0, ~0, ~0, ~0,
+ 4, ~0, ~0, ~0, /* 24 bits per pixel */
+ ~0, ~0, ~0, ~0,
+ 5 /* 32 bits per pixel */
+};
+
+/*
+ * This array gives the bytesperPixel value for cases where the number
+ * of bits per pixel is a multiple of 8 but not a power of 2.
+ */
+static int answerBytesPerPixel[33] = {
+ ~0, 0, ~0, ~0, /* 1 bit per pixel */
+ 0, ~0, ~0, ~0, /* 4 bits per pixel */
+ 0, ~0, ~0, ~0, /* 8 bits per pixel */
+ ~0, ~0, ~0, ~0,
+ 0, ~0, ~0, ~0, /* 16 bits per pixel */
+ ~0, ~0, ~0, ~0,
+ 3, ~0, ~0, ~0, /* 24 bits per pixel */
+ ~0, ~0, ~0, ~0,
+ 0 /* 32 bits per pixel */
+};
+
+/*
+ * This array gives the answer to the question "what is the second index for
+ * the answer array above given the number of bits per scanline pad unit?"
+ * Note that ~0 is an invalid entry (mostly for the benefit of the reader).
+ */
+static int indexForScanlinePad[65] = {
+ ~0, ~0, ~0, ~0,
+ ~0, ~0, ~0, ~0,
+ 0, ~0, ~0, ~0, /* 8 bits per scanline pad unit */
+ ~0, ~0, ~0, ~0,
+ 1, ~0, ~0, ~0, /* 16 bits per scanline pad unit */
+ ~0, ~0, ~0, ~0,
+ ~0, ~0, ~0, ~0,
+ ~0, ~0, ~0, ~0,
+ 2, ~0, ~0, ~0, /* 32 bits per scanline pad unit */
+ ~0, ~0, ~0, ~0,
+ ~0, ~0, ~0, ~0,
+ ~0, ~0, ~0, ~0,
+ ~0, ~0, ~0, ~0,
+ ~0, ~0, ~0, ~0,
+ ~0, ~0, ~0, ~0,
+ ~0, ~0, ~0, ~0,
+ 3 /* 64 bits per scanline pad unit */
+};
+
+/*
+ grow the array of screenRecs if necessary.
+ call the device-supplied initialization procedure
+with its screen number, a pointer to its ScreenRec, argc, and argv.
+ return the number of successfully installed screens.
+
+*/
+
+static int init_screen(ScreenPtr pScreen, int i, Bool gpu)
+{
+ int scanlinepad, format, depth, bitsPerPixel, j, k;
+
+ dixInitScreenSpecificPrivates(pScreen);
+
+ if (!dixAllocatePrivates(&pScreen->devPrivates, PRIVATE_SCREEN)) {
+ return -1;
+ }
+ pScreen->myNum = i;
+ if (gpu) {
+ pScreen->myNum += GPU_SCREEN_OFFSET;
+ pScreen->isGPU = TRUE;
+ }
+ pScreen->totalPixmapSize = 0; /* computed in CreateScratchPixmapForScreen */
+ pScreen->ClipNotify = 0; /* for R4 ddx compatibility */
+ pScreen->CreateScreenResources = 0;
+
+ xorg_list_init(&pScreen->pixmap_dirty_list);
+ xorg_list_init(&pScreen->unattached_list);
+ xorg_list_init(&pScreen->output_slave_list);
+ xorg_list_init(&pScreen->offload_slave_list);
+
+ /*
+ * This loop gets run once for every Screen that gets added,
+ * but thats ok. If the ddx layer initializes the formats
+ * one at a time calling AddScreen() after each, then each
+ * iteration will make it a little more accurate. Worst case
+ * we do this loop N * numPixmapFormats where N is # of screens.
+ * Anyway, this must be called after InitOutput and before the
+ * screen init routine is called.
+ */
+ for (format = 0; format < screenInfo.numPixmapFormats; format++) {
+ depth = screenInfo.formats[format].depth;
+ bitsPerPixel = screenInfo.formats[format].bitsPerPixel;
+ scanlinepad = screenInfo.formats[format].scanlinePad;
+ j = indexForBitsPerPixel[bitsPerPixel];
+ k = indexForScanlinePad[scanlinepad];
+ PixmapWidthPaddingInfo[depth].padPixelsLog2 = answer[j][k];
+ PixmapWidthPaddingInfo[depth].padRoundUp =
+ (scanlinepad / bitsPerPixel) - 1;
+ j = indexForBitsPerPixel[8]; /* bits per byte */
+ PixmapWidthPaddingInfo[depth].padBytesLog2 = answer[j][k];
+ PixmapWidthPaddingInfo[depth].bitsPerPixel = bitsPerPixel;
+ if (answerBytesPerPixel[bitsPerPixel]) {
+ PixmapWidthPaddingInfo[depth].notPower2 = 1;
+ PixmapWidthPaddingInfo[depth].bytesPerPixel =
+ answerBytesPerPixel[bitsPerPixel];
+ }
+ else {
+ PixmapWidthPaddingInfo[depth].notPower2 = 0;
+ }
+ }
+ return 0;
+}
+
+int
+AddScreen(Bool (*pfnInit) (ScreenPtr /*pScreen */ ,
+ int /*argc */ ,
+ char ** /*argv */
+ ), int argc, char **argv)
+{
+
+ int i;
+ ScreenPtr pScreen;
+ Bool ret;
+
+ i = screenInfo.numScreens;
+ if (i == MAXSCREENS)
+ return -1;
+
+ pScreen = (ScreenPtr) calloc(1, sizeof(ScreenRec));
+ if (!pScreen)
+ return -1;
+
+ ret = init_screen(pScreen, i, FALSE);
+ if (ret != 0) {
+ free(pScreen);
+ return ret;
+ }
+ /* This is where screen specific stuff gets initialized. Load the
+ screen structure, call the hardware, whatever.
+ This is also where the default colormap should be allocated and
+ also pixel values for blackPixel, whitePixel, and the cursor
+ Note that InitScreen is NOT allowed to modify argc, argv, or
+ any of the strings pointed to by argv. They may be passed to
+ multiple screens.
+ */
+ screenInfo.screens[i] = pScreen;
+ screenInfo.numScreens++;
+ if (!(*pfnInit) (pScreen, argc, argv)) {
+ dixFreeScreenSpecificPrivates(pScreen);
+ dixFreePrivates(pScreen->devPrivates, PRIVATE_SCREEN);
+ free(pScreen);
+ screenInfo.numScreens--;
+ return -1;
+ }
+
+ update_desktop_dimensions();
+
+ dixRegisterScreenPrivateKey(&cursorScreenDevPriv, pScreen, PRIVATE_CURSOR,
+ 0);
+
+ return i;
+}
+
+int
+AddGPUScreen(Bool (*pfnInit) (ScreenPtr /*pScreen */ ,
+ int /*argc */ ,
+ char ** /*argv */
+ ),
+ int argc, char **argv)
+{
+ int i;
+ ScreenPtr pScreen;
+ Bool ret;
+
+ i = screenInfo.numGPUScreens;
+ if (i == MAXGPUSCREENS)
+ return -1;
+
+ pScreen = (ScreenPtr) calloc(1, sizeof(ScreenRec));
+ if (!pScreen)
+ return -1;
+
+ ret = init_screen(pScreen, i, TRUE);
+ if (ret != 0) {
+ free(pScreen);
+ return ret;
+ }
+
+ /* This is where screen specific stuff gets initialized. Load the
+ screen structure, call the hardware, whatever.
+ This is also where the default colormap should be allocated and
+ also pixel values for blackPixel, whitePixel, and the cursor
+ Note that InitScreen is NOT allowed to modify argc, argv, or
+ any of the strings pointed to by argv. They may be passed to
+ multiple screens.
+ */
+ screenInfo.gpuscreens[i] = pScreen;
+ screenInfo.numGPUScreens++;
+ if (!(*pfnInit) (pScreen, argc, argv)) {
+ dixFreePrivates(pScreen->devPrivates, PRIVATE_SCREEN);
+ free(pScreen);
+ screenInfo.numGPUScreens--;
+ return -1;
+ }
+
+ update_desktop_dimensions();
+
+ return i;
+}
+
+void
+RemoveGPUScreen(ScreenPtr pScreen)
+{
+ int idx, j;
+ if (!pScreen->isGPU)
+ return;
+
+ idx = pScreen->myNum - GPU_SCREEN_OFFSET;
+ for (j = idx; j < screenInfo.numGPUScreens - 1; j++) {
+ screenInfo.gpuscreens[j] = screenInfo.gpuscreens[j + 1];
+ screenInfo.gpuscreens[j]->myNum = j + GPU_SCREEN_OFFSET;
+ }
+ screenInfo.numGPUScreens--;
+
+ /* this gets freed later in the resource list, but without
+ * the screen existing it causes crashes - so remove it here */
+ if (pScreen->defColormap)
+ FreeResource(pScreen->defColormap, RT_COLORMAP);
+ free(pScreen);
+
+}
+
+void
+AttachUnboundGPU(ScreenPtr pScreen, ScreenPtr new)
+{
+ assert(new->isGPU);
+ assert(!new->current_master);
+ xorg_list_add(&new->unattached_head, &pScreen->unattached_list);
+ new->current_master = pScreen;
+}
+
+void
+DetachUnboundGPU(ScreenPtr slave)
+{
+ assert(slave->isGPU);
+ xorg_list_del(&slave->unattached_head);
+ slave->current_master = NULL;
+}
+
+void
+AttachOutputGPU(ScreenPtr pScreen, ScreenPtr new)
+{
+ assert(new->isGPU);
+ xorg_list_add(&new->output_head, &pScreen->output_slave_list);
+ new->current_master = pScreen;
+}
+
+void
+DetachOutputGPU(ScreenPtr slave)
+{
+ assert(slave->isGPU);
+ xorg_list_del(&slave->output_head);
+ slave->current_master = NULL;
+}
+
+void
+AttachOffloadGPU(ScreenPtr pScreen, ScreenPtr new)
+{
+ assert(new->isGPU);
+ xorg_list_add(&new->offload_head, &pScreen->offload_slave_list);
+ new->current_master = pScreen;
+}
+
+void
+DetachOffloadGPU(ScreenPtr slave)
+{
+ assert(slave->isGPU);
+ xorg_list_del(&slave->offload_head);
+ slave->current_master = NULL;
+}
+
|