From c38dead3ea7e177728d90cd815cf4eead0c9f534 Mon Sep 17 00:00:00 2001 From: marha Date: Sat, 15 May 2010 16:28:11 +0000 Subject: xserver git update 15/5/2010 --- xorg-server/Xext/bigreq.c | 160 +- xorg-server/Xext/dpms.c | 758 +++--- xorg-server/Xext/geext.c | 534 ++-- xorg-server/Xext/panoramiX.c | 2568 +++++++++---------- xorg-server/Xext/panoramiXprocs.c | 4893 ++++++++++++++++++------------------- xorg-server/Xext/saver.c | 3078 +++++++++++------------ xorg-server/Xext/security.c | 2305 +++++++++-------- xorg-server/Xext/shape.c | 2586 ++++++++++---------- xorg-server/Xext/shm.c | 2658 ++++++++++---------- xorg-server/Xext/sleepuntil.c | 450 ++-- xorg-server/Xext/sync.c | 4798 ++++++++++++++++++------------------ xorg-server/Xext/xace.c | 700 +++--- xorg-server/Xext/xcalibrate.c | 598 ++--- xorg-server/Xext/xcmisc.c | 434 ++-- xorg-server/Xext/xf86bigfont.c | 30 +- xorg-server/Xext/xres.c | 766 +++--- xorg-server/Xext/xselinux_ext.c | 1468 +++++------ xorg-server/Xext/xselinux_hooks.c | 1919 +++++++-------- xorg-server/Xext/xselinux_label.c | 748 +++--- xorg-server/Xext/xselinuxint.h | 1114 ++++----- xorg-server/Xext/xtest.c | 1426 +++++------ xorg-server/Xext/xvdisp.c | 3924 ++++++++++++++--------------- xorg-server/Xext/xvmain.c | 2378 +++++++++--------- xorg-server/Xext/xvmc.c | 1574 ++++++------ 24 files changed, 20905 insertions(+), 20962 deletions(-) (limited to 'xorg-server/Xext') diff --git a/xorg-server/Xext/bigreq.c b/xorg-server/Xext/bigreq.c index f9f15edc5..4ebc0d6b9 100644 --- a/xorg-server/Xext/bigreq.c +++ b/xorg-server/Xext/bigreq.c @@ -1,80 +1,80 @@ -/* - -Copyright 1992, 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. - -*/ - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include -#include -#include "misc.h" -#include "os.h" -#include "dixstruct.h" -#include "extnsionst.h" -#include -#include "opaque.h" -#include "modinit.h" - -static DISPATCH_PROC(ProcBigReqDispatch); - -void BigReqExtensionInit(INITARGS); - -void -BigReqExtensionInit(INITARGS) -{ - AddExtension(XBigReqExtensionName, 0, 0, - ProcBigReqDispatch, ProcBigReqDispatch, - NULL, StandardMinorOpcode); -} - -static int -ProcBigReqDispatch (ClientPtr client) -{ - REQUEST(xBigReqEnableReq); - xBigReqEnableReply rep; - int n; - - if (client->swapped) { - swaps(&stuff->length, n); - } - if (stuff->brReqType != X_BigReqEnable) - return BadRequest; - REQUEST_SIZE_MATCH(xBigReqEnableReq); - client->big_requests = TRUE; - memset(&rep, 0, sizeof(xBigReqEnableReply)); - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.max_request_size = maxBigRequestSize; - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.max_request_size, n); - } - WriteToClient(client, sizeof(xBigReqEnableReply), (char *)&rep); - return(client->noClientException); -} +/* + +Copyright 1992, 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. + +*/ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include +#include "opaque.h" +#include "modinit.h" + +static DISPATCH_PROC(ProcBigReqDispatch); + +void BigReqExtensionInit(INITARGS); + +void +BigReqExtensionInit(INITARGS) +{ + AddExtension(XBigReqExtensionName, 0, 0, + ProcBigReqDispatch, ProcBigReqDispatch, + NULL, StandardMinorOpcode); +} + +static int +ProcBigReqDispatch (ClientPtr client) +{ + REQUEST(xBigReqEnableReq); + xBigReqEnableReply rep; + int n; + + if (client->swapped) { + swaps(&stuff->length, n); + } + if (stuff->brReqType != X_BigReqEnable) + return BadRequest; + REQUEST_SIZE_MATCH(xBigReqEnableReq); + client->big_requests = TRUE; + memset(&rep, 0, sizeof(xBigReqEnableReply)); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.max_request_size = maxBigRequestSize; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.max_request_size, n); + } + WriteToClient(client, sizeof(xBigReqEnableReply), (char *)&rep); + return Success; +} diff --git a/xorg-server/Xext/dpms.c b/xorg-server/Xext/dpms.c index df63a8bf1..13854f704 100644 --- a/xorg-server/Xext/dpms.c +++ b/xorg-server/Xext/dpms.c @@ -1,379 +1,379 @@ -/***************************************************************** - -Copyright (c) 1996 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. - -******************************************************************/ - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include -#include -#include "misc.h" -#include "os.h" -#include "dixstruct.h" -#include "extnsionst.h" -#include "opaque.h" -#include -#include "dpmsproc.h" -#include "modinit.h" - -static int -ProcDPMSGetVersion(ClientPtr client) -{ - /* REQUEST(xDPMSGetVersionReq); */ - xDPMSGetVersionReply rep; - int n; - - REQUEST_SIZE_MATCH(xDPMSGetVersionReq); - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.majorVersion = DPMSMajorVersion; - rep.minorVersion = DPMSMinorVersion; - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - swaps(&rep.majorVersion, n); - swaps(&rep.minorVersion, n); - } - WriteToClient(client, sizeof(xDPMSGetVersionReply), (char *)&rep); - return(client->noClientException); -} - -static int -ProcDPMSCapable(ClientPtr client) -{ - /* REQUEST(xDPMSCapableReq); */ - xDPMSCapableReply rep; - int n; - - REQUEST_SIZE_MATCH(xDPMSCapableReq); - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.capable = DPMSCapableFlag; - - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - } - WriteToClient(client, sizeof(xDPMSCapableReply), (char *)&rep); - return(client->noClientException); -} - -static int -ProcDPMSGetTimeouts(ClientPtr client) -{ - /* REQUEST(xDPMSGetTimeoutsReq); */ - xDPMSGetTimeoutsReply rep; - int n; - - REQUEST_SIZE_MATCH(xDPMSGetTimeoutsReq); - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.standby = DPMSStandbyTime / MILLI_PER_SECOND; - rep.suspend = DPMSSuspendTime / MILLI_PER_SECOND; - rep.off = DPMSOffTime / MILLI_PER_SECOND; - - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - swaps(&rep.standby, n); - swaps(&rep.suspend, n); - swaps(&rep.off, n); - } - WriteToClient(client, sizeof(xDPMSGetTimeoutsReply), (char *)&rep); - return(client->noClientException); -} - -static int -ProcDPMSSetTimeouts(ClientPtr client) -{ - REQUEST(xDPMSSetTimeoutsReq); - - REQUEST_SIZE_MATCH(xDPMSSetTimeoutsReq); - - if ((stuff->off != 0)&&(stuff->off < stuff->suspend)) - { - client->errorValue = stuff->off; - return BadValue; - } - if ((stuff->suspend != 0)&&(stuff->suspend < stuff->standby)) - { - client->errorValue = stuff->suspend; - return BadValue; - } - - DPMSStandbyTime = stuff->standby * MILLI_PER_SECOND; - DPMSSuspendTime = stuff->suspend * MILLI_PER_SECOND; - DPMSOffTime = stuff->off * MILLI_PER_SECOND; - SetScreenSaverTimer(); - - return(client->noClientException); -} - -static int -ProcDPMSEnable(ClientPtr client) -{ - Bool was_enabled = DPMSEnabled; - - REQUEST_SIZE_MATCH(xDPMSEnableReq); - - if (DPMSCapableFlag) { - DPMSEnabled = TRUE; - if (!was_enabled) - SetScreenSaverTimer(); - } - - return(client->noClientException); -} - -static int -ProcDPMSDisable(ClientPtr client) -{ - /* REQUEST(xDPMSDisableReq); */ - - REQUEST_SIZE_MATCH(xDPMSDisableReq); - - DPMSSet(client, DPMSModeOn); - - DPMSEnabled = FALSE; - - return(client->noClientException); -} - -static int -ProcDPMSForceLevel(ClientPtr client) -{ - REQUEST(xDPMSForceLevelReq); - - REQUEST_SIZE_MATCH(xDPMSForceLevelReq); - - if (!DPMSEnabled) - return BadMatch; - - if (stuff->level != DPMSModeOn && - stuff->level != DPMSModeStandby && - stuff->level != DPMSModeSuspend && - stuff->level != DPMSModeOff) { - client->errorValue = stuff->level; - return BadValue; - } - - DPMSSet(client, stuff->level); - - return(client->noClientException); -} - -static int -ProcDPMSInfo(ClientPtr client) -{ - /* REQUEST(xDPMSInfoReq); */ - xDPMSInfoReply rep; - int n; - - REQUEST_SIZE_MATCH(xDPMSInfoReq); - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.power_level = DPMSPowerLevel; - rep.state = DPMSEnabled; - - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - swaps(&rep.power_level, n); - } - WriteToClient(client, sizeof(xDPMSInfoReply), (char *)&rep); - return(client->noClientException); -} - -static int -ProcDPMSDispatch (ClientPtr client) -{ - REQUEST(xReq); - - switch (stuff->data) - { - case X_DPMSGetVersion: - return ProcDPMSGetVersion(client); - case X_DPMSCapable: - return ProcDPMSCapable(client); - case X_DPMSGetTimeouts: - return ProcDPMSGetTimeouts(client); - case X_DPMSSetTimeouts: - return ProcDPMSSetTimeouts(client); - case X_DPMSEnable: - return ProcDPMSEnable(client); - case X_DPMSDisable: - return ProcDPMSDisable(client); - case X_DPMSForceLevel: - return ProcDPMSForceLevel(client); - case X_DPMSInfo: - return ProcDPMSInfo(client); - default: - return BadRequest; - } -} - -static int -SProcDPMSGetVersion(ClientPtr client) -{ - int n; - REQUEST(xDPMSGetVersionReq); - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH(xDPMSGetVersionReq); - swaps(&stuff->majorVersion, n); - swaps(&stuff->minorVersion, n); - return ProcDPMSGetVersion(client); -} - -static int -SProcDPMSCapable(ClientPtr client) -{ - REQUEST(xDPMSCapableReq); - int n; - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH(xDPMSCapableReq); - - return ProcDPMSCapable(client); -} - -static int -SProcDPMSGetTimeouts(ClientPtr client) -{ - REQUEST(xDPMSGetTimeoutsReq); - int n; - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH(xDPMSGetTimeoutsReq); - - return ProcDPMSGetTimeouts(client); -} - -static int -SProcDPMSSetTimeouts(ClientPtr client) -{ - REQUEST(xDPMSSetTimeoutsReq); - int n; - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH(xDPMSSetTimeoutsReq); - - swaps(&stuff->standby, n); - swaps(&stuff->suspend, n); - swaps(&stuff->off, n); - return ProcDPMSSetTimeouts(client); -} - -static int -SProcDPMSEnable(ClientPtr client) -{ - REQUEST(xDPMSEnableReq); - int n; - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH(xDPMSEnableReq); - - return ProcDPMSEnable(client); -} - -static int -SProcDPMSDisable(ClientPtr client) -{ - REQUEST(xDPMSDisableReq); - int n; - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH(xDPMSDisableReq); - - return ProcDPMSDisable(client); -} - -static int -SProcDPMSForceLevel(ClientPtr client) -{ - REQUEST(xDPMSForceLevelReq); - int n; - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH(xDPMSForceLevelReq); - - swaps(&stuff->level, n); - - return ProcDPMSForceLevel(client); -} - -static int -SProcDPMSInfo(ClientPtr client) -{ - REQUEST(xDPMSInfoReq); - int n; - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH(xDPMSInfoReq); - - return ProcDPMSInfo(client); -} - -static int -SProcDPMSDispatch (ClientPtr client) -{ - REQUEST(xReq); - switch (stuff->data) - { - case X_DPMSGetVersion: - return SProcDPMSGetVersion(client); - case X_DPMSCapable: - return SProcDPMSCapable(client); - case X_DPMSGetTimeouts: - return SProcDPMSGetTimeouts(client); - case X_DPMSSetTimeouts: - return SProcDPMSSetTimeouts(client); - case X_DPMSEnable: - return SProcDPMSEnable(client); - case X_DPMSDisable: - return SProcDPMSDisable(client); - case X_DPMSForceLevel: - return SProcDPMSForceLevel(client); - case X_DPMSInfo: - return SProcDPMSInfo(client); - default: - return BadRequest; - } -} - -void -DPMSExtensionInit(INITARGS) -{ - AddExtension(DPMSExtensionName, 0, 0, - ProcDPMSDispatch, SProcDPMSDispatch, - NULL, StandardMinorOpcode); -} +/***************************************************************** + +Copyright (c) 1996 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. + +******************************************************************/ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "opaque.h" +#include +#include "dpmsproc.h" +#include "modinit.h" + +static int +ProcDPMSGetVersion(ClientPtr client) +{ + /* REQUEST(xDPMSGetVersionReq); */ + xDPMSGetVersionReply rep; + int n; + + REQUEST_SIZE_MATCH(xDPMSGetVersionReq); + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = DPMSMajorVersion; + rep.minorVersion = DPMSMinorVersion; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swaps(&rep.majorVersion, n); + swaps(&rep.minorVersion, n); + } + WriteToClient(client, sizeof(xDPMSGetVersionReply), (char *)&rep); + return Success; +} + +static int +ProcDPMSCapable(ClientPtr client) +{ + /* REQUEST(xDPMSCapableReq); */ + xDPMSCapableReply rep; + int n; + + REQUEST_SIZE_MATCH(xDPMSCapableReq); + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.capable = DPMSCapableFlag; + + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + } + WriteToClient(client, sizeof(xDPMSCapableReply), (char *)&rep); + return Success; +} + +static int +ProcDPMSGetTimeouts(ClientPtr client) +{ + /* REQUEST(xDPMSGetTimeoutsReq); */ + xDPMSGetTimeoutsReply rep; + int n; + + REQUEST_SIZE_MATCH(xDPMSGetTimeoutsReq); + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.standby = DPMSStandbyTime / MILLI_PER_SECOND; + rep.suspend = DPMSSuspendTime / MILLI_PER_SECOND; + rep.off = DPMSOffTime / MILLI_PER_SECOND; + + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swaps(&rep.standby, n); + swaps(&rep.suspend, n); + swaps(&rep.off, n); + } + WriteToClient(client, sizeof(xDPMSGetTimeoutsReply), (char *)&rep); + return Success; +} + +static int +ProcDPMSSetTimeouts(ClientPtr client) +{ + REQUEST(xDPMSSetTimeoutsReq); + + REQUEST_SIZE_MATCH(xDPMSSetTimeoutsReq); + + if ((stuff->off != 0)&&(stuff->off < stuff->suspend)) + { + client->errorValue = stuff->off; + return BadValue; + } + if ((stuff->suspend != 0)&&(stuff->suspend < stuff->standby)) + { + client->errorValue = stuff->suspend; + return BadValue; + } + + DPMSStandbyTime = stuff->standby * MILLI_PER_SECOND; + DPMSSuspendTime = stuff->suspend * MILLI_PER_SECOND; + DPMSOffTime = stuff->off * MILLI_PER_SECOND; + SetScreenSaverTimer(); + + return Success; +} + +static int +ProcDPMSEnable(ClientPtr client) +{ + Bool was_enabled = DPMSEnabled; + + REQUEST_SIZE_MATCH(xDPMSEnableReq); + + if (DPMSCapableFlag) { + DPMSEnabled = TRUE; + if (!was_enabled) + SetScreenSaverTimer(); + } + + return Success; +} + +static int +ProcDPMSDisable(ClientPtr client) +{ + /* REQUEST(xDPMSDisableReq); */ + + REQUEST_SIZE_MATCH(xDPMSDisableReq); + + DPMSSet(client, DPMSModeOn); + + DPMSEnabled = FALSE; + + return Success; +} + +static int +ProcDPMSForceLevel(ClientPtr client) +{ + REQUEST(xDPMSForceLevelReq); + + REQUEST_SIZE_MATCH(xDPMSForceLevelReq); + + if (!DPMSEnabled) + return BadMatch; + + if (stuff->level != DPMSModeOn && + stuff->level != DPMSModeStandby && + stuff->level != DPMSModeSuspend && + stuff->level != DPMSModeOff) { + client->errorValue = stuff->level; + return BadValue; + } + + DPMSSet(client, stuff->level); + + return Success; +} + +static int +ProcDPMSInfo(ClientPtr client) +{ + /* REQUEST(xDPMSInfoReq); */ + xDPMSInfoReply rep; + int n; + + REQUEST_SIZE_MATCH(xDPMSInfoReq); + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.power_level = DPMSPowerLevel; + rep.state = DPMSEnabled; + + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swaps(&rep.power_level, n); + } + WriteToClient(client, sizeof(xDPMSInfoReply), (char *)&rep); + return Success; +} + +static int +ProcDPMSDispatch (ClientPtr client) +{ + REQUEST(xReq); + + switch (stuff->data) + { + case X_DPMSGetVersion: + return ProcDPMSGetVersion(client); + case X_DPMSCapable: + return ProcDPMSCapable(client); + case X_DPMSGetTimeouts: + return ProcDPMSGetTimeouts(client); + case X_DPMSSetTimeouts: + return ProcDPMSSetTimeouts(client); + case X_DPMSEnable: + return ProcDPMSEnable(client); + case X_DPMSDisable: + return ProcDPMSDisable(client); + case X_DPMSForceLevel: + return ProcDPMSForceLevel(client); + case X_DPMSInfo: + return ProcDPMSInfo(client); + default: + return BadRequest; + } +} + +static int +SProcDPMSGetVersion(ClientPtr client) +{ + int n; + REQUEST(xDPMSGetVersionReq); + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xDPMSGetVersionReq); + swaps(&stuff->majorVersion, n); + swaps(&stuff->minorVersion, n); + return ProcDPMSGetVersion(client); +} + +static int +SProcDPMSCapable(ClientPtr client) +{ + REQUEST(xDPMSCapableReq); + int n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xDPMSCapableReq); + + return ProcDPMSCapable(client); +} + +static int +SProcDPMSGetTimeouts(ClientPtr client) +{ + REQUEST(xDPMSGetTimeoutsReq); + int n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xDPMSGetTimeoutsReq); + + return ProcDPMSGetTimeouts(client); +} + +static int +SProcDPMSSetTimeouts(ClientPtr client) +{ + REQUEST(xDPMSSetTimeoutsReq); + int n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xDPMSSetTimeoutsReq); + + swaps(&stuff->standby, n); + swaps(&stuff->suspend, n); + swaps(&stuff->off, n); + return ProcDPMSSetTimeouts(client); +} + +static int +SProcDPMSEnable(ClientPtr client) +{ + REQUEST(xDPMSEnableReq); + int n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xDPMSEnableReq); + + return ProcDPMSEnable(client); +} + +static int +SProcDPMSDisable(ClientPtr client) +{ + REQUEST(xDPMSDisableReq); + int n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xDPMSDisableReq); + + return ProcDPMSDisable(client); +} + +static int +SProcDPMSForceLevel(ClientPtr client) +{ + REQUEST(xDPMSForceLevelReq); + int n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xDPMSForceLevelReq); + + swaps(&stuff->level, n); + + return ProcDPMSForceLevel(client); +} + +static int +SProcDPMSInfo(ClientPtr client) +{ + REQUEST(xDPMSInfoReq); + int n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xDPMSInfoReq); + + return ProcDPMSInfo(client); +} + +static int +SProcDPMSDispatch (ClientPtr client) +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_DPMSGetVersion: + return SProcDPMSGetVersion(client); + case X_DPMSCapable: + return SProcDPMSCapable(client); + case X_DPMSGetTimeouts: + return SProcDPMSGetTimeouts(client); + case X_DPMSSetTimeouts: + return SProcDPMSSetTimeouts(client); + case X_DPMSEnable: + return SProcDPMSEnable(client); + case X_DPMSDisable: + return SProcDPMSDisable(client); + case X_DPMSForceLevel: + return SProcDPMSForceLevel(client); + case X_DPMSInfo: + return SProcDPMSInfo(client); + default: + return BadRequest; + } +} + +void +DPMSExtensionInit(INITARGS) +{ + AddExtension(DPMSExtensionName, 0, 0, + ProcDPMSDispatch, SProcDPMSDispatch, + NULL, StandardMinorOpcode); +} diff --git a/xorg-server/Xext/geext.c b/xorg-server/Xext/geext.c index f0a3d8778..253c87bc9 100644 --- a/xorg-server/Xext/geext.c +++ b/xorg-server/Xext/geext.c @@ -1,267 +1,267 @@ -/* - * Copyright 2007-2008 Peter Hutterer - * - * 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. - * - * Author: Peter Hutterer, University of South Australia, NICTA - */ - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif -#include "windowstr.h" -#include -#include "registry.h" - -#include "geint.h" -#include "geext.h" -#include "protocol-versions.h" - -#define rClient(obj) (clients[CLIENT_ID((obj)->resource)]) - -static int GEClientPrivateKeyIndex; -DevPrivateKey GEClientPrivateKey = &GEClientPrivateKeyIndex; - -int RT_GECLIENT = 0; - - -GEExtension GEExtensions[MAXEXTENSIONS]; - -/* Major available requests */ -static const int version_requests[] = { - X_GEQueryVersion, /* before client sends QueryVersion */ - X_GEQueryVersion, /* must be set to last request in version 1 */ -}; - -/* Forward declarations */ -static void SGEGenericEvent(xEvent* from, xEvent* to); - -#define NUM_VERSION_REQUESTS (sizeof (version_requests) / sizeof (version_requests[0])) - -/************************************************************/ -/* request handlers */ -/************************************************************/ - -static int -ProcGEQueryVersion(ClientPtr client) -{ - int n; - GEClientInfoPtr pGEClient = GEGetClient(client); - xGEQueryVersionReply rep; - REQUEST(xGEQueryVersionReq); - - REQUEST_SIZE_MATCH(xGEQueryVersionReq); - - rep.repType = X_Reply; - rep.RepType = X_GEQueryVersion; - rep.length = 0; - rep.sequenceNumber = client->sequence; - - /* return the supported version by the server */ - rep.majorVersion = SERVER_GE_MAJOR_VERSION; - rep.minorVersion = SERVER_GE_MINOR_VERSION; - - /* Remember version the client requested */ - pGEClient->major_version = stuff->majorVersion; - pGEClient->minor_version = stuff->minorVersion; - - if (client->swapped) - { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swaps(&rep.majorVersion, n); - swaps(&rep.minorVersion, n); - } - - WriteToClient(client, sizeof(xGEQueryVersionReply), (char*)&rep); - return(client->noClientException); -} - -int (*ProcGEVector[GENumberRequests])(ClientPtr) = { - /* Version 1.0 */ - ProcGEQueryVersion -}; - -/************************************************************/ -/* swapped request handlers */ -/************************************************************/ -static int -SProcGEQueryVersion(ClientPtr client) -{ - int n; - REQUEST(xGEQueryVersionReq); - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH(xGEQueryVersionReq); - swaps(&stuff->majorVersion, n); - swaps(&stuff->minorVersion, n); - return(*ProcGEVector[stuff->ReqType])(client); -} - -int (*SProcGEVector[GENumberRequests])(ClientPtr) = { - /* Version 1.0 */ - SProcGEQueryVersion -}; - - -/************************************************************/ -/* callbacks */ -/************************************************************/ - -/* dispatch requests */ -static int -ProcGEDispatch(ClientPtr client) -{ - GEClientInfoPtr pGEClient = GEGetClient(client); - REQUEST(xGEReq); - - if (pGEClient->major_version >= NUM_VERSION_REQUESTS) - return BadRequest; - if (stuff->ReqType > version_requests[pGEClient->major_version]) - return BadRequest; - - return (ProcGEVector[stuff->ReqType])(client); -} - -/* dispatch swapped requests */ -static int -SProcGEDispatch(ClientPtr client) -{ - REQUEST(xGEReq); - if (stuff->ReqType >= GENumberRequests) - return BadRequest; - return (*SProcGEVector[stuff->ReqType])(client); -} - -/** - * Called when a new client inits a connection to the X server. - * - * We alloc a simple struct to store the client's major/minor version. Can be - * used in the furture for versioning support. - */ -static void -GEClientCallback(CallbackListPtr *list, - pointer closure, - pointer data) -{ - NewClientInfoRec *clientinfo = (NewClientInfoRec *) data; - ClientPtr pClient = clientinfo->client; - GEClientInfoPtr pGEClient = GEGetClient(pClient); - - pGEClient->major_version = 0; - pGEClient->minor_version = 0; -} - -/* Reset extension. Called on server shutdown. */ -static void -GEResetProc(ExtensionEntry *extEntry) -{ - DeleteCallback(&ClientStateCallback, GEClientCallback, 0); - EventSwapVector[GenericEvent] = NotImplemented; -} - -/* Calls the registered event swap function for the extension. - * - * Each extension can register a swap function to handle GenericEvents being - * swapped properly. The server calls SGEGenericEvent() before the event is - * written on the wire, this one calls the registered swap function to do the - * work. - */ -static void -SGEGenericEvent(xEvent* from, xEvent* to) -{ - xGenericEvent* gefrom = (xGenericEvent*)from; - xGenericEvent* geto = (xGenericEvent*)to; - - if (gefrom->extension > MAXEXTENSIONS) - { - ErrorF("GE: Invalid extension offset for event.\n"); - return; - } - - if (GEExtensions[gefrom->extension & 0x7F].evswap) - GEExtensions[gefrom->extension & 0x7F].evswap(gefrom, geto); -} - -/* Init extension, register at server. - * Since other extensions may rely on XGE (XInput does already), it is a good - * idea to init XGE first, before any other extension. - */ -void -GEExtensionInit(void) -{ - ExtensionEntry *extEntry; - - if (!dixRequestPrivate(GEClientPrivateKey, sizeof(GEClientInfoRec))) - FatalError("GEExtensionInit: GE private request failed.\n"); - - if(!AddCallback(&ClientStateCallback, GEClientCallback, 0)) - { - FatalError("GEExtensionInit: register client callback failed.\n"); - } - - if((extEntry = AddExtension(GE_NAME, - 0, GENumberErrors, - ProcGEDispatch, SProcGEDispatch, - GEResetProc, StandardMinorOpcode)) != 0) - { - memset(GEExtensions, 0, sizeof(GEExtensions)); - - EventSwapVector[GenericEvent] = (EventSwapPtr) SGEGenericEvent; - } else { - FatalError("GEInit: AddExtensions failed.\n"); - } - -} - -/************************************************************/ -/* interface for extensions */ -/************************************************************/ - -/* Register an extension with GE. The given swap function will be called each - * time an event is sent to a client with different byte order. - * @param extension The extensions major opcode - * @param ev_swap The event swap function. - * @param ev_fill Called for an event before delivery. The extension now has - * the chance to fill in necessary fields for the event. - */ -void -GERegisterExtension(int extension, - void (*ev_swap)(xGenericEvent* from, xGenericEvent* to)) -{ - if ((extension & 0x7F) >= MAXEXTENSIONS) - FatalError("GE: extension > MAXEXTENSIONS. This should not happen.\n"); - - /* extension opcodes are > 128, might as well save some space here */ - GEExtensions[extension & 0x7f].evswap = ev_swap; -} - - -/* Sets type and extension field for a generic event. This is just an - * auxiliary function, extensions could do it manually too. - */ -void -GEInitEvent(xGenericEvent* ev, int extension) -{ - ev->type = GenericEvent; - ev->extension = extension; - ev->length = 0; -} - +/* + * Copyright 2007-2008 Peter Hutterer + * + * 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. + * + * Author: Peter Hutterer, University of South Australia, NICTA + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif +#include "windowstr.h" +#include +#include "registry.h" + +#include "geint.h" +#include "geext.h" +#include "protocol-versions.h" + +#define rClient(obj) (clients[CLIENT_ID((obj)->resource)]) + +static int GEClientPrivateKeyIndex; +DevPrivateKey GEClientPrivateKey = &GEClientPrivateKeyIndex; + +int RT_GECLIENT = 0; + + +GEExtension GEExtensions[MAXEXTENSIONS]; + +/* Major available requests */ +static const int version_requests[] = { + X_GEQueryVersion, /* before client sends QueryVersion */ + X_GEQueryVersion, /* must be set to last request in version 1 */ +}; + +/* Forward declarations */ +static void SGEGenericEvent(xEvent* from, xEvent* to); + +#define NUM_VERSION_REQUESTS (sizeof (version_requests) / sizeof (version_requests[0])) + +/************************************************************/ +/* request handlers */ +/************************************************************/ + +static int +ProcGEQueryVersion(ClientPtr client) +{ + int n; + GEClientInfoPtr pGEClient = GEGetClient(client); + xGEQueryVersionReply rep; + REQUEST(xGEQueryVersionReq); + + REQUEST_SIZE_MATCH(xGEQueryVersionReq); + + rep.repType = X_Reply; + rep.RepType = X_GEQueryVersion; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + /* return the supported version by the server */ + rep.majorVersion = SERVER_GE_MAJOR_VERSION; + rep.minorVersion = SERVER_GE_MINOR_VERSION; + + /* Remember version the client requested */ + pGEClient->major_version = stuff->majorVersion; + pGEClient->minor_version = stuff->minorVersion; + + if (client->swapped) + { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.majorVersion, n); + swaps(&rep.minorVersion, n); + } + + WriteToClient(client, sizeof(xGEQueryVersionReply), (char*)&rep); + return Success; +} + +int (*ProcGEVector[GENumberRequests])(ClientPtr) = { + /* Version 1.0 */ + ProcGEQueryVersion +}; + +/************************************************************/ +/* swapped request handlers */ +/************************************************************/ +static int +SProcGEQueryVersion(ClientPtr client) +{ + int n; + REQUEST(xGEQueryVersionReq); + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xGEQueryVersionReq); + swaps(&stuff->majorVersion, n); + swaps(&stuff->minorVersion, n); + return(*ProcGEVector[stuff->ReqType])(client); +} + +int (*SProcGEVector[GENumberRequests])(ClientPtr) = { + /* Version 1.0 */ + SProcGEQueryVersion +}; + + +/************************************************************/ +/* callbacks */ +/************************************************************/ + +/* dispatch requests */ +static int +ProcGEDispatch(ClientPtr client) +{ + GEClientInfoPtr pGEClient = GEGetClient(client); + REQUEST(xGEReq); + + if (pGEClient->major_version >= NUM_VERSION_REQUESTS) + return BadRequest; + if (stuff->ReqType > version_requests[pGEClient->major_version]) + return BadRequest; + + return (ProcGEVector[stuff->ReqType])(client); +} + +/* dispatch swapped requests */ +static int +SProcGEDispatch(ClientPtr client) +{ + REQUEST(xGEReq); + if (stuff->ReqType >= GENumberRequests) + return BadRequest; + return (*SProcGEVector[stuff->ReqType])(client); +} + +/** + * Called when a new client inits a connection to the X server. + * + * We alloc a simple struct to store the client's major/minor version. Can be + * used in the furture for versioning support. + */ +static void +GEClientCallback(CallbackListPtr *list, + pointer closure, + pointer data) +{ + NewClientInfoRec *clientinfo = (NewClientInfoRec *) data; + ClientPtr pClient = clientinfo->client; + GEClientInfoPtr pGEClient = GEGetClient(pClient); + + pGEClient->major_version = 0; + pGEClient->minor_version = 0; +} + +/* Reset extension. Called on server shutdown. */ +static void +GEResetProc(ExtensionEntry *extEntry) +{ + DeleteCallback(&ClientStateCallback, GEClientCallback, 0); + EventSwapVector[GenericEvent] = NotImplemented; +} + +/* Calls the registered event swap function for the extension. + * + * Each extension can register a swap function to handle GenericEvents being + * swapped properly. The server calls SGEGenericEvent() before the event is + * written on the wire, this one calls the registered swap function to do the + * work. + */ +static void +SGEGenericEvent(xEvent* from, xEvent* to) +{ + xGenericEvent* gefrom = (xGenericEvent*)from; + xGenericEvent* geto = (xGenericEvent*)to; + + if (gefrom->extension > MAXEXTENSIONS) + { + ErrorF("GE: Invalid extension offset for event.\n"); + return; + } + + if (GEExtensions[gefrom->extension & 0x7F].evswap) + GEExtensions[gefrom->extension & 0x7F].evswap(gefrom, geto); +} + +/* Init extension, register at server. + * Since other extensions may rely on XGE (XInput does already), it is a good + * idea to init XGE first, before any other extension. + */ +void +GEExtensionInit(void) +{ + ExtensionEntry *extEntry; + + if (!dixRequestPrivate(GEClientPrivateKey, sizeof(GEClientInfoRec))) + FatalError("GEExtensionInit: GE private request failed.\n"); + + if(!AddCallback(&ClientStateCallback, GEClientCallback, 0)) + { + FatalError("GEExtensionInit: register client callback failed.\n"); + } + + if((extEntry = AddExtension(GE_NAME, + 0, GENumberErrors, + ProcGEDispatch, SProcGEDispatch, + GEResetProc, StandardMinorOpcode)) != 0) + { + memset(GEExtensions, 0, sizeof(GEExtensions)); + + EventSwapVector[GenericEvent] = (EventSwapPtr) SGEGenericEvent; + } else { + FatalError("GEInit: AddExtensions failed.\n"); + } + +} + +/************************************************************/ +/* interface for extensions */ +/************************************************************/ + +/* Register an extension with GE. The given swap function will be called each + * time an event is sent to a client with different byte order. + * @param extension The extensions major opcode + * @param ev_swap The event swap function. + * @param ev_fill Called for an event before delivery. The extension now has + * the chance to fill in necessary fields for the event. + */ +void +GERegisterExtension(int extension, + void (*ev_swap)(xGenericEvent* from, xGenericEvent* to)) +{ + if ((extension & 0x7F) >= MAXEXTENSIONS) + FatalError("GE: extension > MAXEXTENSIONS. This should not happen.\n"); + + /* extension opcodes are > 128, might as well save some space here */ + GEExtensions[extension & 0x7f].evswap = ev_swap; +} + + +/* Sets type and extension field for a generic event. This is just an + * auxiliary function, extensions could do it manually too. + */ +void +GEInitEvent(xGenericEvent* ev, int extension) +{ + ev->type = GenericEvent; + ev->extension = extension; + ev->length = 0; +} + diff --git a/xorg-server/Xext/panoramiX.c b/xorg-server/Xext/panoramiX.c index d5965c2d0..e26aadc95 100644 --- a/xorg-server/Xext/panoramiX.c +++ b/xorg-server/Xext/panoramiX.c @@ -1,1284 +1,1284 @@ -/***************************************************************** -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. -******************************************************************/ - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#ifdef HAVE_DMX_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include "misc.h" -#include "cursor.h" -#include "cursorstr.h" -#include "extnsionst.h" -#include "dixstruct.h" -#include "gc.h" -#include "gcstruct.h" -#include "scrnintstr.h" -#include "window.h" -#include "windowstr.h" -#include "pixmapstr.h" -#include "panoramiX.h" -#include -#include "panoramiXsrv.h" -#include "globals.h" -#include "servermd.h" -#include "resource.h" -#include "picturestr.h" -#include "modinit.h" -#include "protocol-versions.h" - -#ifdef GLXPROXY -extern VisualPtr glxMatchVisual(ScreenPtr pScreen, - VisualPtr pVisual, - ScreenPtr pMatchScreen); -#endif - -/* - * PanoramiX data declarations - */ - -int PanoramiXPixWidth = 0; -int PanoramiXPixHeight = 0; -int PanoramiXNumScreens = 0; - -PanoramiXData *panoramiXdataPtr = NULL; -static RegionRec PanoramiXScreenRegion = {{0, 0, 0, 0}, NULL}; - -static int PanoramiXNumDepths; -static DepthPtr PanoramiXDepths; -static int PanoramiXNumVisuals; -static VisualPtr PanoramiXVisuals; - -unsigned long XRC_DRAWABLE; -unsigned long XRT_WINDOW; -unsigned long XRT_PIXMAP; -unsigned long XRT_GC; -unsigned long XRT_COLORMAP; - -static Bool VisualsEqual(VisualPtr, ScreenPtr, VisualPtr); -XineramaVisualsEqualProcPtr XineramaVisualsEqualPtr = &VisualsEqual; - -/* - * Function prototypes - */ - -static int panoramiXGeneration; -static int ProcPanoramiXDispatch(ClientPtr client); - -static void PanoramiXResetProc(ExtensionEntry*); - -/* - * External references for functions and data variables - */ - -#include "panoramiXh.h" - -int (* SavedProcVector[256]) (ClientPtr client) = { NULL, }; - -static int PanoramiXGCKeyIndex; -static DevPrivateKey PanoramiXGCKey = &PanoramiXGCKeyIndex; -static int PanoramiXScreenKeyIndex; -static DevPrivateKey PanoramiXScreenKey = &PanoramiXScreenKeyIndex; - -typedef struct { - DDXPointRec clipOrg; - DDXPointRec patOrg; - GCFuncs *wrapFuncs; -} PanoramiXGCRec, *PanoramiXGCPtr; - -typedef struct { - CreateGCProcPtr CreateGC; - CloseScreenProcPtr CloseScreen; -} PanoramiXScreenRec, *PanoramiXScreenPtr; - -RegionRec XineramaScreenRegions[MAXSCREENS]; - -static void XineramaValidateGC(GCPtr, unsigned long, DrawablePtr); -static void XineramaChangeGC(GCPtr, unsigned long); -static void XineramaCopyGC(GCPtr, unsigned long, GCPtr); -static void XineramaDestroyGC(GCPtr); -static void XineramaChangeClip(GCPtr, int, pointer, int); -static void XineramaDestroyClip(GCPtr); -static void XineramaCopyClip(GCPtr, GCPtr); - -static GCFuncs XineramaGCFuncs = { - XineramaValidateGC, XineramaChangeGC, XineramaCopyGC, XineramaDestroyGC, - XineramaChangeClip, XineramaDestroyClip, XineramaCopyClip -}; - -#define Xinerama_GC_FUNC_PROLOGUE(pGC)\ - PanoramiXGCPtr pGCPriv = (PanoramiXGCPtr) \ - dixLookupPrivate(&(pGC)->devPrivates, PanoramiXGCKey); \ - (pGC)->funcs = pGCPriv->wrapFuncs; - -#define Xinerama_GC_FUNC_EPILOGUE(pGC)\ - pGCPriv->wrapFuncs = (pGC)->funcs;\ - (pGC)->funcs = &XineramaGCFuncs; - - -static Bool -XineramaCloseScreen (int i, ScreenPtr pScreen) -{ - PanoramiXScreenPtr pScreenPriv = (PanoramiXScreenPtr) - dixLookupPrivate(&pScreen->devPrivates, PanoramiXScreenKey); - - pScreen->CloseScreen = pScreenPriv->CloseScreen; - pScreen->CreateGC = pScreenPriv->CreateGC; - - REGION_UNINIT(pScreen, &XineramaScreenRegions[pScreen->myNum]); - if (pScreen->myNum == 0) - REGION_UNINIT(pScreen, &PanoramiXScreenRegion); - - xfree ((pointer) pScreenPriv); - - return (*pScreen->CloseScreen) (i, pScreen); -} - -static Bool -XineramaCreateGC(GCPtr pGC) -{ - ScreenPtr pScreen = pGC->pScreen; - PanoramiXScreenPtr pScreenPriv = (PanoramiXScreenPtr) - dixLookupPrivate(&pScreen->devPrivates, PanoramiXScreenKey); - Bool ret; - - pScreen->CreateGC = pScreenPriv->CreateGC; - if((ret = (*pScreen->CreateGC)(pGC))) { - PanoramiXGCPtr pGCPriv = (PanoramiXGCPtr) - dixLookupPrivate(&pGC->devPrivates, PanoramiXGCKey); - - pGCPriv->wrapFuncs = pGC->funcs; - pGC->funcs = &XineramaGCFuncs; - - pGCPriv->clipOrg.x = pGC->clipOrg.x; - pGCPriv->clipOrg.y = pGC->clipOrg.y; - pGCPriv->patOrg.x = pGC->patOrg.x; - pGCPriv->patOrg.y = pGC->patOrg.y; - } - pScreen->CreateGC = XineramaCreateGC; - - return ret; -} - -static void -XineramaValidateGC( - GCPtr pGC, - unsigned long changes, - DrawablePtr pDraw -){ - Xinerama_GC_FUNC_PROLOGUE (pGC); - - if((pDraw->type == DRAWABLE_WINDOW) && !(((WindowPtr)pDraw)->parent)) { - /* the root window */ - int x_off = panoramiXdataPtr[pGC->pScreen->myNum].x; - int y_off = panoramiXdataPtr[pGC->pScreen->myNum].y; - int new_val; - - new_val = pGCPriv->clipOrg.x - x_off; - if(pGC->clipOrg.x != new_val) { - pGC->clipOrg.x = new_val; - changes |= GCClipXOrigin; - } - new_val = pGCPriv->clipOrg.y - y_off; - if(pGC->clipOrg.y != new_val) { - pGC->clipOrg.y = new_val; - changes |= GCClipYOrigin; - } - new_val = pGCPriv->patOrg.x - x_off; - if(pGC->patOrg.x != new_val) { - pGC->patOrg.x = new_val; - changes |= GCTileStipXOrigin; - } - new_val = pGCPriv->patOrg.y - y_off; - if(pGC->patOrg.y != new_val) { - pGC->patOrg.y = new_val; - changes |= GCTileStipYOrigin; - } - } else { - if(pGC->clipOrg.x != pGCPriv->clipOrg.x) { - pGC->clipOrg.x = pGCPriv->clipOrg.x; - changes |= GCClipXOrigin; - } - if(pGC->clipOrg.y != pGCPriv->clipOrg.y) { - pGC->clipOrg.y = pGCPriv->clipOrg.y; - changes |= GCClipYOrigin; - } - if(pGC->patOrg.x != pGCPriv->patOrg.x) { - pGC->patOrg.x = pGCPriv->patOrg.x; - changes |= GCTileStipXOrigin; - } - if(pGC->patOrg.y != pGCPriv->patOrg.y) { - pGC->patOrg.y = pGCPriv->patOrg.y; - changes |= GCTileStipYOrigin; - } - } - - (*pGC->funcs->ValidateGC)(pGC, changes, pDraw); - Xinerama_GC_FUNC_EPILOGUE (pGC); -} - -static void -XineramaDestroyGC(GCPtr pGC) -{ - Xinerama_GC_FUNC_PROLOGUE (pGC); - (*pGC->funcs->DestroyGC)(pGC); - Xinerama_GC_FUNC_EPILOGUE (pGC); -} - -static void -XineramaChangeGC ( - GCPtr pGC, - unsigned long mask -){ - Xinerama_GC_FUNC_PROLOGUE (pGC); - - if(mask & GCTileStipXOrigin) - pGCPriv->patOrg.x = pGC->patOrg.x; - if(mask & GCTileStipYOrigin) - pGCPriv->patOrg.y = pGC->patOrg.y; - if(mask & GCClipXOrigin) - pGCPriv->clipOrg.x = pGC->clipOrg.x; - if(mask & GCClipYOrigin) - pGCPriv->clipOrg.y = pGC->clipOrg.y; - - (*pGC->funcs->ChangeGC) (pGC, mask); - Xinerama_GC_FUNC_EPILOGUE (pGC); -} - -static void -XineramaCopyGC ( - GCPtr pGCSrc, - unsigned long mask, - GCPtr pGCDst -){ - PanoramiXGCPtr pSrcPriv = (PanoramiXGCPtr) - dixLookupPrivate(&pGCSrc->devPrivates, PanoramiXGCKey); - Xinerama_GC_FUNC_PROLOGUE (pGCDst); - - if(mask & GCTileStipXOrigin) - pGCPriv->patOrg.x = pSrcPriv->patOrg.x; - if(mask & GCTileStipYOrigin) - pGCPriv->patOrg.y = pSrcPriv->patOrg.y; - if(mask & GCClipXOrigin) - pGCPriv->clipOrg.x = pSrcPriv->clipOrg.x; - if(mask & GCClipYOrigin) - pGCPriv->clipOrg.y = pSrcPriv->clipOrg.y; - - (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst); - Xinerama_GC_FUNC_EPILOGUE (pGCDst); -} - -static void -XineramaChangeClip ( - GCPtr pGC, - int type, - pointer pvalue, - int nrects -){ - Xinerama_GC_FUNC_PROLOGUE (pGC); - (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects); - Xinerama_GC_FUNC_EPILOGUE (pGC); -} - -static void -XineramaCopyClip(GCPtr pgcDst, GCPtr pgcSrc) -{ - Xinerama_GC_FUNC_PROLOGUE (pgcDst); - (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc); - Xinerama_GC_FUNC_EPILOGUE (pgcDst); -} - -static void -XineramaDestroyClip(GCPtr pGC) -{ - Xinerama_GC_FUNC_PROLOGUE (pGC); - (* pGC->funcs->DestroyClip)(pGC); - Xinerama_GC_FUNC_EPILOGUE (pGC); -} - -int -XineramaDeleteResource(pointer data, XID id) -{ - xfree(data); - return 1; -} - -typedef struct { - int screen; - int id; -} PanoramiXSearchData; - -static Bool -XineramaFindIDByScrnum(pointer resource, XID id, pointer privdata) -{ - PanoramiXRes *res = (PanoramiXRes*)resource; - PanoramiXSearchData *data = (PanoramiXSearchData*)privdata; - - return (res->info[data->screen].id == data->id); -} - -PanoramiXRes * -PanoramiXFindIDByScrnum(RESTYPE type, XID id, int screen) -{ - PanoramiXSearchData data; - pointer val; - - if(!screen) { - dixLookupResourceByType(&val, id, type, serverClient, DixReadAccess); - return val; - } - - data.screen = screen; - data.id = id; - - return LookupClientResourceComplex(clients[CLIENT_ID(id)], type, - XineramaFindIDByScrnum, &data); -} - -typedef struct _connect_callback_list { - void (*func)(void); - struct _connect_callback_list *next; -} XineramaConnectionCallbackList; - -static XineramaConnectionCallbackList *ConnectionCallbackList = NULL; - -Bool -XineramaRegisterConnectionBlockCallback(void (*func)(void)) -{ - XineramaConnectionCallbackList *newlist; - - if(!(newlist = xalloc(sizeof(XineramaConnectionCallbackList)))) - return FALSE; - - newlist->next = ConnectionCallbackList; - newlist->func = func; - ConnectionCallbackList = newlist; - - return TRUE; -} - -static void XineramaInitData(ScreenPtr pScreen) -{ - int i, w, h; - - REGION_NULL(pScreen, &PanoramiXScreenRegion) - for (i = 0; i < PanoramiXNumScreens; i++) { - BoxRec TheBox; - - pScreen = screenInfo.screens[i]; - - panoramiXdataPtr[i].x = dixScreenOrigins[i].x; - panoramiXdataPtr[i].y = dixScreenOrigins[i].y; - panoramiXdataPtr[i].width = pScreen->width; - panoramiXdataPtr[i].height = pScreen->height; - - TheBox.x1 = panoramiXdataPtr[i].x; - TheBox.x2 = TheBox.x1 + panoramiXdataPtr[i].width; - TheBox.y1 = panoramiXdataPtr[i].y; - TheBox.y2 = TheBox.y1 + panoramiXdataPtr[i].height; - - REGION_INIT(pScreen, &XineramaScreenRegions[i], &TheBox, 1); - REGION_UNION(pScreen, &PanoramiXScreenRegion, &PanoramiXScreenRegion, - &XineramaScreenRegions[i]); - } - - PanoramiXPixWidth = panoramiXdataPtr[0].x + panoramiXdataPtr[0].width; - PanoramiXPixHeight = panoramiXdataPtr[0].y + panoramiXdataPtr[0].height; - - for (i = 1; i < PanoramiXNumScreens; i++) { - w = panoramiXdataPtr[i].x + panoramiXdataPtr[i].width; - h = panoramiXdataPtr[i].y + panoramiXdataPtr[i].height; - - if (PanoramiXPixWidth < w) - PanoramiXPixWidth = w; - if (PanoramiXPixHeight < h) - PanoramiXPixHeight = h; - } -} - -void XineramaReinitData(ScreenPtr pScreen) -{ - int i; - - REGION_UNINIT(pScreen, &PanoramiXScreenRegion); - for (i = 0; i < PanoramiXNumScreens; i++) - REGION_UNINIT(pScreen, &XineramaScreenRegions[i]); - - XineramaInitData(pScreen); -} - -/* - * PanoramiXExtensionInit(): - * Called from InitExtensions in main(). - * Register PanoramiXeen Extension - * Initialize global variables. - */ - -void PanoramiXExtensionInit(int argc, char *argv[]) -{ - int i; - Bool success = FALSE; - ExtensionEntry *extEntry; - ScreenPtr pScreen = screenInfo.screens[0]; - PanoramiXScreenPtr pScreenPriv; - - if (noPanoramiXExtension) - return; - - PanoramiXNumScreens = screenInfo.numScreens; - if (PanoramiXNumScreens == 1) { /* Only 1 screen */ - noPanoramiXExtension = TRUE; - return; - } - - while (panoramiXGeneration != serverGeneration) { - extEntry = AddExtension(PANORAMIX_PROTOCOL_NAME, 0,0, - ProcPanoramiXDispatch, - SProcPanoramiXDispatch, PanoramiXResetProc, - StandardMinorOpcode); - if (!extEntry) - break; - - /* - * First make sure all the basic allocations succeed. If not, - * run in non-PanoramiXeen mode. - */ - - panoramiXdataPtr = (PanoramiXData *) - xcalloc(PanoramiXNumScreens, sizeof(PanoramiXData)); - - if (!panoramiXdataPtr) - break; - - if (!dixRequestPrivate(PanoramiXGCKey, sizeof(PanoramiXGCRec))) { - noPanoramiXExtension = TRUE; - return; - } - - for (i = 0; i < PanoramiXNumScreens; i++) { - pScreen = screenInfo.screens[i]; - pScreenPriv = xalloc(sizeof(PanoramiXScreenRec)); - dixSetPrivate(&pScreen->devPrivates, PanoramiXScreenKey, - pScreenPriv); - if(!pScreenPriv) { - noPanoramiXExtension = TRUE; - return; - } - - pScreenPriv->CreateGC = pScreen->CreateGC; - pScreenPriv->CloseScreen = pScreen->CloseScreen; - - pScreen->CreateGC = XineramaCreateGC; - pScreen->CloseScreen = XineramaCloseScreen; - } - - XRC_DRAWABLE = CreateNewResourceClass(); - XRT_WINDOW = CreateNewResourceType(XineramaDeleteResource, - "XineramaWindow"); - if (XRT_WINDOW) - XRT_WINDOW |= XRC_DRAWABLE; - XRT_PIXMAP = CreateNewResourceType(XineramaDeleteResource, - "XineramaPixmap"); - if (XRT_PIXMAP) - XRT_PIXMAP |= XRC_DRAWABLE; - XRT_GC = CreateNewResourceType(XineramaDeleteResource, - "XineramaGC"); - XRT_COLORMAP = CreateNewResourceType(XineramaDeleteResource, - "XineramaColormap"); - - if (XRT_WINDOW && XRT_PIXMAP && XRT_GC && XRT_COLORMAP) { - panoramiXGeneration = serverGeneration; - success = TRUE; - } - } - - if (!success) { - noPanoramiXExtension = TRUE; - ErrorF(PANORAMIX_PROTOCOL_NAME " extension failed to initialize\n"); - return; - } - - XineramaInitData(pScreen); - - /* - * Put our processes into the ProcVector - */ - - for (i = 256; i--; ) - SavedProcVector[i] = ProcVector[i]; - - ProcVector[X_CreateWindow] = PanoramiXCreateWindow; - ProcVector[X_ChangeWindowAttributes] = PanoramiXChangeWindowAttributes; - ProcVector[X_DestroyWindow] = PanoramiXDestroyWindow; - ProcVector[X_DestroySubwindows] = PanoramiXDestroySubwindows; - ProcVector[X_ChangeSaveSet] = PanoramiXChangeSaveSet; - ProcVector[X_ReparentWindow] = PanoramiXReparentWindow; - ProcVector[X_MapWindow] = PanoramiXMapWindow; - ProcVector[X_MapSubwindows] = PanoramiXMapSubwindows; - ProcVector[X_UnmapWindow] = PanoramiXUnmapWindow; - ProcVector[X_UnmapSubwindows] = PanoramiXUnmapSubwindows; - ProcVector[X_ConfigureWindow] = PanoramiXConfigureWindow; - ProcVector[X_CirculateWindow] = PanoramiXCirculateWindow; - ProcVector[X_GetGeometry] = PanoramiXGetGeometry; - ProcVector[X_TranslateCoords] = PanoramiXTranslateCoords; - ProcVector[X_CreatePixmap] = PanoramiXCreatePixmap; - ProcVector[X_FreePixmap] = PanoramiXFreePixmap; - ProcVector[X_CreateGC] = PanoramiXCreateGC; - ProcVector[X_ChangeGC] = PanoramiXChangeGC; - ProcVector[X_CopyGC] = PanoramiXCopyGC; - ProcVector[X_SetDashes] = PanoramiXSetDashes; - ProcVector[X_SetClipRectangles] = PanoramiXSetClipRectangles; - ProcVector[X_FreeGC] = PanoramiXFreeGC; - ProcVector[X_ClearArea] = PanoramiXClearToBackground; - ProcVector[X_CopyArea] = PanoramiXCopyArea; - ProcVector[X_CopyPlane] = PanoramiXCopyPlane; - ProcVector[X_PolyPoint] = PanoramiXPolyPoint; - ProcVector[X_PolyLine] = PanoramiXPolyLine; - ProcVector[X_PolySegment] = PanoramiXPolySegment; - ProcVector[X_PolyRectangle] = PanoramiXPolyRectangle; - ProcVector[X_PolyArc] = PanoramiXPolyArc; - ProcVector[X_FillPoly] = PanoramiXFillPoly; - ProcVector[X_PolyFillRectangle] = PanoramiXPolyFillRectangle; - ProcVector[X_PolyFillArc] = PanoramiXPolyFillArc; - ProcVector[X_PutImage] = PanoramiXPutImage; - ProcVector[X_GetImage] = PanoramiXGetImage; - ProcVector[X_PolyText8] = PanoramiXPolyText8; - ProcVector[X_PolyText16] = PanoramiXPolyText16; - ProcVector[X_ImageText8] = PanoramiXImageText8; - ProcVector[X_ImageText16] = PanoramiXImageText16; - ProcVector[X_CreateColormap] = PanoramiXCreateColormap; - ProcVector[X_FreeColormap] = PanoramiXFreeColormap; - ProcVector[X_CopyColormapAndFree] = PanoramiXCopyColormapAndFree; - ProcVector[X_InstallColormap] = PanoramiXInstallColormap; - ProcVector[X_UninstallColormap] = PanoramiXUninstallColormap; - ProcVector[X_AllocColor] = PanoramiXAllocColor; - ProcVector[X_AllocNamedColor] = PanoramiXAllocNamedColor; - ProcVector[X_AllocColorCells] = PanoramiXAllocColorCells; - ProcVector[X_AllocColorPlanes] = PanoramiXAllocColorPlanes; - ProcVector[X_FreeColors] = PanoramiXFreeColors; - ProcVector[X_StoreColors] = PanoramiXStoreColors; - ProcVector[X_StoreNamedColor] = PanoramiXStoreNamedColor; - - PanoramiXRenderInit (); -} - -extern Bool CreateConnectionBlock(void); - -Bool PanoramiXCreateConnectionBlock(void) -{ - int i, j, length; - Bool disableBackingStore = FALSE; - int old_width, old_height; - float width_mult, height_mult; - xWindowRoot *root; - xVisualType *visual; - xDepth *depth; - VisualPtr pVisual; - ScreenPtr pScreen; - - /* - * Do normal CreateConnectionBlock but faking it for only one screen - */ - - if(!PanoramiXNumDepths) { - ErrorF("Xinerama error: No common visuals\n"); - return FALSE; - } - - for(i = 1; i < screenInfo.numScreens; i++) { - pScreen = screenInfo.screens[i]; - if(pScreen->rootDepth != screenInfo.screens[0]->rootDepth) { - ErrorF("Xinerama error: Root window depths differ\n"); - return FALSE; - } - if(pScreen->backingStoreSupport != screenInfo.screens[0]->backingStoreSupport) - disableBackingStore = TRUE; - } - - if (disableBackingStore) { - for (i = 0; i < screenInfo.numScreens; i++) { - pScreen = screenInfo.screens[i]; - pScreen->backingStoreSupport = NotUseful; - } - } - - i = screenInfo.numScreens; - screenInfo.numScreens = 1; - if (!CreateConnectionBlock()) { - screenInfo.numScreens = i; - return FALSE; - } - - screenInfo.numScreens = i; - - root = (xWindowRoot *) (ConnectionInfo + connBlockScreenStart); - length = connBlockScreenStart + sizeof(xWindowRoot); - - /* overwrite the connection block */ - root->nDepths = PanoramiXNumDepths; - - for (i = 0; i < PanoramiXNumDepths; i++) { - depth = (xDepth *) (ConnectionInfo + length); - depth->depth = PanoramiXDepths[i].depth; - depth->nVisuals = PanoramiXDepths[i].numVids; - length += sizeof(xDepth); - visual = (xVisualType *)(ConnectionInfo + length); - - for (j = 0; j < depth->nVisuals; j++, visual++) { - visual->visualID = PanoramiXDepths[i].vids[j]; - - for (pVisual = PanoramiXVisuals; - pVisual->vid != visual->visualID; - pVisual++) - ; - - visual->class = pVisual->class; - visual->bitsPerRGB = pVisual->bitsPerRGBValue; - visual->colormapEntries = pVisual->ColormapEntries; - visual->redMask = pVisual->redMask; - visual->greenMask = pVisual->greenMask; - visual->blueMask = pVisual->blueMask; - } - - length += (depth->nVisuals * sizeof(xVisualType)); - } - - connSetupPrefix.length = bytes_to_int32(length); - - for (i = 0; i < PanoramiXNumDepths; i++) - xfree(PanoramiXDepths[i].vids); - xfree(PanoramiXDepths); - PanoramiXDepths = NULL; - - /* - * OK, change some dimensions so it looks as if it were one big screen - */ - - old_width = root->pixWidth; - old_height = root->pixHeight; - - root->pixWidth = PanoramiXPixWidth; - root->pixHeight = PanoramiXPixHeight; - width_mult = (1.0 * root->pixWidth) / old_width; - height_mult = (1.0 * root->pixHeight) / old_height; - root->mmWidth *= width_mult; - root->mmHeight *= height_mult; - - while(ConnectionCallbackList) { - pointer tmp; - - tmp = (pointer)ConnectionCallbackList; - (*ConnectionCallbackList->func)(); - ConnectionCallbackList = ConnectionCallbackList->next; - xfree(tmp); - } - - return TRUE; -} - -/* - * This isn't just memcmp(), bitsPerRGBValue is skipped. markv made that - * change way back before xf86 4.0, but the comment for _why_ is a bit - * opaque, so I'm not going to question it for now. - * - * This is probably better done as a screen hook so DBE/EVI/GLX can add - * their own tests, and adding privates to VisualRec so they don't have to - * do their own back-mapping. - */ -static Bool -VisualsEqual(VisualPtr a, ScreenPtr pScreenB, VisualPtr b) -{ - return ((a->class == b->class) && - (a->ColormapEntries == b->ColormapEntries) && - (a->nplanes == b->nplanes) && - (a->redMask == b->redMask) && - (a->greenMask == b->greenMask) && - (a->blueMask == b->blueMask) && - (a->offsetRed == b->offsetRed) && - (a->offsetGreen == b->offsetGreen) && - (a->offsetBlue == b->offsetBlue)); -} - -static void -PanoramiXMaybeAddDepth(DepthPtr pDepth) -{ - ScreenPtr pScreen; - int j, k; - Bool found = FALSE; - - for (j = 1; j < PanoramiXNumScreens; j++) { - pScreen = screenInfo.screens[j]; - for (k = 0; k < pScreen->numDepths; k++) { - if (pScreen->allowedDepths[k].depth == pDepth->depth) { - found = TRUE; - break; - } - } - } - - if (!found) - return; - - j = PanoramiXNumDepths; - PanoramiXNumDepths++; - PanoramiXDepths = xrealloc(PanoramiXDepths, - PanoramiXNumDepths * sizeof(DepthRec)); - PanoramiXDepths[j].depth = pDepth->depth; - PanoramiXDepths[j].numVids = 0; - /* XXX suboptimal, should grow these dynamically */ - if(pDepth->numVids) - PanoramiXDepths[j].vids = xalloc(sizeof(VisualID) * pDepth->numVids); - else - PanoramiXDepths[j].vids = NULL; -} - -static void -PanoramiXMaybeAddVisual(VisualPtr pVisual) -{ - ScreenPtr pScreen; - int j, k; - Bool found = FALSE; - - for (j = 1; j < PanoramiXNumScreens; j++) { - pScreen = screenInfo.screens[j]; - found = FALSE; - - for (k = 0; k < pScreen->numVisuals; k++) { - VisualPtr candidate = &pScreen->visuals[k]; - - if ((*XineramaVisualsEqualPtr)(pVisual, pScreen, candidate) -#ifdef GLXPROXY - && glxMatchVisual(screenInfo.screens[0], pVisual, pScreen) -#endif - ) { - found = TRUE; - break; - } - } - - if (!found) - return; - } - - /* found a matching visual on all screens, add it to the subset list */ - j = PanoramiXNumVisuals; - PanoramiXNumVisuals++; - PanoramiXVisuals = xrealloc(PanoramiXVisuals, - PanoramiXNumVisuals * sizeof(VisualRec)); - - memcpy(&PanoramiXVisuals[j], pVisual, sizeof(VisualRec)); - - for (k = 0; k < PanoramiXNumDepths; k++) { - if (PanoramiXDepths[k].depth == pVisual->nplanes) { - PanoramiXDepths[k].vids[PanoramiXDepths[k].numVids] = pVisual->vid; - PanoramiXDepths[k].numVids++; - break; - } - } -} - -extern void -PanoramiXConsolidate(void) -{ - int i; - PanoramiXRes *root, *defmap, *saver; - ScreenPtr pScreen = screenInfo.screens[0]; - DepthPtr pDepth = pScreen->allowedDepths; - VisualPtr pVisual = pScreen->visuals; - - PanoramiXNumDepths = 0; - PanoramiXNumVisuals = 0; - - for (i = 0; i < pScreen->numDepths; i++) - PanoramiXMaybeAddDepth(pDepth++); - - for (i = 0; i < pScreen->numVisuals; i++) - PanoramiXMaybeAddVisual(pVisual++); - - root = xalloc(sizeof(PanoramiXRes)); - root->type = XRT_WINDOW; - defmap = xalloc(sizeof(PanoramiXRes)); - defmap->type = XRT_COLORMAP; - saver = xalloc(sizeof(PanoramiXRes)); - saver->type = XRT_WINDOW; - - for (i = 0; i < PanoramiXNumScreens; i++) { - root->info[i].id = WindowTable[i]->drawable.id; - root->u.win.class = InputOutput; - root->u.win.root = TRUE; - saver->info[i].id = savedScreenInfo[i].wid; - saver->u.win.class = InputOutput; - saver->u.win.root = TRUE; - defmap->info[i].id = (screenInfo.screens[i])->defColormap; - } - - AddResource(root->info[0].id, XRT_WINDOW, root); - AddResource(saver->info[0].id, XRT_WINDOW, saver); - AddResource(defmap->info[0].id, XRT_COLORMAP, defmap); -} - -VisualID -PanoramiXTranslateVisualID(int screen, VisualID orig) -{ - ScreenPtr pOtherScreen = screenInfo.screens[screen]; - VisualPtr pVisual = NULL; - int i; - - for (i = 0; i < PanoramiXNumVisuals; i++) { - if (orig == PanoramiXVisuals[i].vid) { - pVisual = &PanoramiXVisuals[i]; - break; - } - } - - if (!pVisual) - return 0; - - /* if screen is 0, orig is already the correct visual ID */ - if (screen == 0) - return orig; - - /* found the original, now translate it relative to the backend screen */ - for (i = 0; i < pOtherScreen->numVisuals; i++) { - VisualPtr pOtherVisual = &pOtherScreen->visuals[i]; - - if ((*XineramaVisualsEqualPtr)(pVisual, pOtherScreen, pOtherVisual)) - return pOtherVisual->vid; - } - - return 0; -} - - -/* - * PanoramiXResetProc() - * Exit, deallocating as needed. - */ - -static void PanoramiXResetProc(ExtensionEntry* extEntry) -{ - int i; - - PanoramiXRenderReset (); - screenInfo.numScreens = PanoramiXNumScreens; - for (i = 256; i--; ) - ProcVector[i] = SavedProcVector[i]; - - Xfree(panoramiXdataPtr); -} - - -int -ProcPanoramiXQueryVersion (ClientPtr client) -{ - /* REQUEST(xPanoramiXQueryVersionReq); */ - xPanoramiXQueryVersionReply rep; - register int n; - - REQUEST_SIZE_MATCH (xPanoramiXQueryVersionReq); - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.majorVersion = SERVER_PANORAMIX_MAJOR_VERSION; - rep.minorVersion = SERVER_PANORAMIX_MINOR_VERSION; - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swaps(&rep.majorVersion, n); - swaps(&rep.minorVersion, n); - } - WriteToClient(client, sizeof (xPanoramiXQueryVersionReply), (char *)&rep); - return (client->noClientException); -} - -int -ProcPanoramiXGetState(ClientPtr client) -{ - REQUEST(xPanoramiXGetStateReq); - WindowPtr pWin; - xPanoramiXGetStateReply rep; - int n, rc; - - REQUEST_SIZE_MATCH(xPanoramiXGetStateReq); - rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); - if (rc != Success) - return rc; - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.state = !noPanoramiXExtension; - rep.window = stuff->window; - if (client->swapped) { - swaps (&rep.sequenceNumber, n); - swapl (&rep.length, n); - swapl (&rep.window, n); - } - WriteToClient (client, sizeof (xPanoramiXGetStateReply), (char *) &rep); - return client->noClientException; - -} - -int -ProcPanoramiXGetScreenCount(ClientPtr client) -{ - REQUEST(xPanoramiXGetScreenCountReq); - WindowPtr pWin; - xPanoramiXGetScreenCountReply rep; - int n, rc; - - REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq); - rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); - if (rc != Success) - return rc; - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.ScreenCount = PanoramiXNumScreens; - rep.window = stuff->window; - if (client->swapped) { - swaps (&rep.sequenceNumber, n); - swapl (&rep.length, n); - swapl (&rep.window, n); - } - WriteToClient (client, sizeof (xPanoramiXGetScreenCountReply), (char *) &rep); - return client->noClientException; -} - -int -ProcPanoramiXGetScreenSize(ClientPtr client) -{ - REQUEST(xPanoramiXGetScreenSizeReq); - WindowPtr pWin; - xPanoramiXGetScreenSizeReply rep; - int n, rc; - - if (stuff->screen >= PanoramiXNumScreens) - return BadMatch; - - REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq); - rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); - if (rc != Success) - return rc; - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - /* screen dimensions */ - rep.width = panoramiXdataPtr[stuff->screen].width; - rep.height = panoramiXdataPtr[stuff->screen].height; - rep.window = stuff->window; - rep.screen = stuff->screen; - if (client->swapped) { - swaps (&rep.sequenceNumber, n); - swapl (&rep.length, n); - swapl (&rep.width, n); - swapl (&rep.height, n); - swapl (&rep.window, n); - swapl (&rep.screen, n); - } - WriteToClient (client, sizeof (xPanoramiXGetScreenSizeReply), (char *) &rep); - return client->noClientException; -} - - -int -ProcXineramaIsActive(ClientPtr client) -{ - /* REQUEST(xXineramaIsActiveReq); */ - xXineramaIsActiveReply rep; - - REQUEST_SIZE_MATCH(xXineramaIsActiveReq); - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; -#if 1 - { - /* The following hack fools clients into thinking that Xinerama - * is disabled even though it is not. */ - rep.state = !noPanoramiXExtension && !PanoramiXExtensionDisabledHack; - } -#else - rep.state = !noPanoramiXExtension; -#endif - if (client->swapped) { - int n; - swaps (&rep.sequenceNumber, n); - swapl (&rep.length, n); - swapl (&rep.state, n); - } - WriteToClient (client, sizeof (xXineramaIsActiveReply), (char *) &rep); - return client->noClientException; -} - - -int -ProcXineramaQueryScreens(ClientPtr client) -{ - /* REQUEST(xXineramaQueryScreensReq); */ - xXineramaQueryScreensReply rep; - - REQUEST_SIZE_MATCH(xXineramaQueryScreensReq); - - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.number = (noPanoramiXExtension) ? 0 : PanoramiXNumScreens; - rep.length = bytes_to_int32(rep.number * sz_XineramaScreenInfo); - if (client->swapped) { - int n; - swaps (&rep.sequenceNumber, n); - swapl (&rep.length, n); - swapl (&rep.number, n); - } - WriteToClient (client, sizeof (xXineramaQueryScreensReply), (char *) &rep); - - if(!noPanoramiXExtension) { - xXineramaScreenInfo scratch; - int i; - - for(i = 0; i < PanoramiXNumScreens; i++) { - scratch.x_org = panoramiXdataPtr[i].x; - scratch.y_org = panoramiXdataPtr[i].y; - scratch.width = panoramiXdataPtr[i].width; - scratch.height = panoramiXdataPtr[i].height; - - if(client->swapped) { - int n; - swaps (&scratch.x_org, n); - swaps (&scratch.y_org, n); - swaps (&scratch.width, n); - swaps (&scratch.height, n); - } - WriteToClient (client, sz_XineramaScreenInfo, (char *) &scratch); - } - } - - return client->noClientException; -} - - -static int -ProcPanoramiXDispatch (ClientPtr client) -{ REQUEST(xReq); - switch (stuff->data) - { - case X_PanoramiXQueryVersion: - return ProcPanoramiXQueryVersion(client); - case X_PanoramiXGetState: - return ProcPanoramiXGetState(client); - case X_PanoramiXGetScreenCount: - return ProcPanoramiXGetScreenCount(client); - case X_PanoramiXGetScreenSize: - return ProcPanoramiXGetScreenSize(client); - case X_XineramaIsActive: - return ProcXineramaIsActive(client); - case X_XineramaQueryScreens: - return ProcXineramaQueryScreens(client); - } - return BadRequest; -} - - -#if X_BYTE_ORDER == X_LITTLE_ENDIAN -#define SHIFT_L(v,s) (v) << (s) -#define SHIFT_R(v,s) (v) >> (s) -#else -#define SHIFT_L(v,s) (v) >> (s) -#define SHIFT_R(v,s) (v) << (s) -#endif - -static void -CopyBits(char *dst, int shiftL, char *src, int bytes) -{ - /* Just get it to work. Worry about speed later */ - int shiftR = 8 - shiftL; - - while(bytes--) { - *dst |= SHIFT_L(*src, shiftL); - *(dst + 1) |= SHIFT_R(*src, shiftR); - dst++; src++; - } -} - - -/* Caution. This doesn't support 2 and 4 bpp formats. We expect - 1 bpp and planar data to be already cleared when presented - to this function */ - -void -XineramaGetImageData( - DrawablePtr *pDrawables, - int left, - int top, - int width, - int height, - unsigned int format, - unsigned long planemask, - char *data, - int pitch, - Bool isRoot -){ - RegionRec SrcRegion, GrabRegion; - BoxRec SrcBox, *pbox; - int x, y, w, h, i, j, nbox, size, sizeNeeded, ScratchPitch, inOut, depth; - DrawablePtr pDraw = pDrawables[0]; - char *ScratchMem = NULL; - - size = 0; - - /* find box in logical screen space */ - SrcBox.x1 = left; - SrcBox.y1 = top; - if(!isRoot) { - SrcBox.x1 += pDraw->x + panoramiXdataPtr[0].x; - SrcBox.y1 += pDraw->y + panoramiXdataPtr[0].y; - } - SrcBox.x2 = SrcBox.x1 + width; - SrcBox.y2 = SrcBox.y1 + height; - - REGION_INIT(pScreen, &SrcRegion, &SrcBox, 1); - REGION_NULL(pScreen, &GrabRegion); - - depth = (format == XYPixmap) ? 1 : pDraw->depth; - - for(i = 0; i < PanoramiXNumScreens; i++) { - pDraw = pDrawables[i]; - - inOut = RECT_IN_REGION(pScreen,&XineramaScreenRegions[i],&SrcBox); - - if(inOut == rgnIN) { - (*pDraw->pScreen->GetImage)(pDraw, - SrcBox.x1 - pDraw->x - panoramiXdataPtr[i].x, - SrcBox.y1 - pDraw->y - panoramiXdataPtr[i].y, - width, height, format, planemask, data); - break; - } else if (inOut == rgnOUT) - continue; - - REGION_INTERSECT(pScreen, &GrabRegion, &SrcRegion, - &XineramaScreenRegions[i]); - - nbox = REGION_NUM_RECTS(&GrabRegion); - - if(nbox) { - pbox = REGION_RECTS(&GrabRegion); - - while(nbox--) { - w = pbox->x2 - pbox->x1; - h = pbox->y2 - pbox->y1; - ScratchPitch = PixmapBytePad(w, depth); - sizeNeeded = ScratchPitch * h; - - if(sizeNeeded > size) { - char *tmpdata = ScratchMem; - ScratchMem = xrealloc(ScratchMem, sizeNeeded); - if(ScratchMem) - size = sizeNeeded; - else { - ScratchMem = tmpdata; - break; - } - } - - x = pbox->x1 - pDraw->x - panoramiXdataPtr[i].x; - y = pbox->y1 - pDraw->y - panoramiXdataPtr[i].y; - - (*pDraw->pScreen->GetImage)(pDraw, x, y, w, h, - format, planemask, ScratchMem); - - /* copy the memory over */ - - if(depth == 1) { - int k, shift, leftover, index, index2; - - x = pbox->x1 - SrcBox.x1; - y = pbox->y1 - SrcBox.y1; - shift = x & 7; - x >>= 3; - leftover = w & 7; - w >>= 3; - - /* clean up the edge */ - if(leftover) { - int mask = (1 << leftover) - 1; - for(j = h, k = w; j--; k += ScratchPitch) - ScratchMem[k] &= mask; - } - - for(j = 0, index = (pitch * y) + x, index2 = 0; j < h; - j++, index += pitch, index2 += ScratchPitch) - { - if(w) { - if(!shift) - memcpy(data + index, ScratchMem + index2, w); - else - CopyBits(data + index, shift, - ScratchMem + index2, w); - } - - if(leftover) { - data[index + w] |= - SHIFT_L(ScratchMem[index2 + w], shift); - if((shift + leftover) > 8) - data[index + w + 1] |= - SHIFT_R(ScratchMem[index2 + w],(8 - shift)); - } - } - } else { - j = BitsPerPixel(depth) >> 3; - x = (pbox->x1 - SrcBox.x1) * j; - y = pbox->y1 - SrcBox.y1; - w *= j; - - for(j = 0; j < h; j++) { - memcpy(data + (pitch * (y + j)) + x, - ScratchMem + (ScratchPitch * j), w); - } - } - pbox++; - } - - REGION_SUBTRACT(pScreen, &SrcRegion, &SrcRegion, &GrabRegion); - if(!REGION_NOTEMPTY(pScreen, &SrcRegion)) - break; - } - - } - - if(ScratchMem) - xfree(ScratchMem); - - REGION_UNINIT(pScreen, &SrcRegion); - REGION_UNINIT(pScreen, &GrabRegion); -} +/***************************************************************** +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. +******************************************************************/ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#ifdef HAVE_DMX_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include "misc.h" +#include "cursor.h" +#include "cursorstr.h" +#include "extnsionst.h" +#include "dixstruct.h" +#include "gc.h" +#include "gcstruct.h" +#include "scrnintstr.h" +#include "window.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "panoramiX.h" +#include +#include "panoramiXsrv.h" +#include "globals.h" +#include "servermd.h" +#include "resource.h" +#include "picturestr.h" +#include "modinit.h" +#include "protocol-versions.h" + +#ifdef GLXPROXY +extern VisualPtr glxMatchVisual(ScreenPtr pScreen, + VisualPtr pVisual, + ScreenPtr pMatchScreen); +#endif + +/* + * PanoramiX data declarations + */ + +int PanoramiXPixWidth = 0; +int PanoramiXPixHeight = 0; +int PanoramiXNumScreens = 0; + +PanoramiXData *panoramiXdataPtr = NULL; +static RegionRec PanoramiXScreenRegion = {{0, 0, 0, 0}, NULL}; + +static int PanoramiXNumDepths; +static DepthPtr PanoramiXDepths; +static int PanoramiXNumVisuals; +static VisualPtr PanoramiXVisuals; + +unsigned long XRC_DRAWABLE; +unsigned long XRT_WINDOW; +unsigned long XRT_PIXMAP; +unsigned long XRT_GC; +unsigned long XRT_COLORMAP; + +static Bool VisualsEqual(VisualPtr, ScreenPtr, VisualPtr); +XineramaVisualsEqualProcPtr XineramaVisualsEqualPtr = &VisualsEqual; + +/* + * Function prototypes + */ + +static int panoramiXGeneration; +static int ProcPanoramiXDispatch(ClientPtr client); + +static void PanoramiXResetProc(ExtensionEntry*); + +/* + * External references for functions and data variables + */ + +#include "panoramiXh.h" + +int (* SavedProcVector[256]) (ClientPtr client) = { NULL, }; + +static int PanoramiXGCKeyIndex; +static DevPrivateKey PanoramiXGCKey = &PanoramiXGCKeyIndex; +static int PanoramiXScreenKeyIndex; +static DevPrivateKey PanoramiXScreenKey = &PanoramiXScreenKeyIndex; + +typedef struct { + DDXPointRec clipOrg; + DDXPointRec patOrg; + GCFuncs *wrapFuncs; +} PanoramiXGCRec, *PanoramiXGCPtr; + +typedef struct { + CreateGCProcPtr CreateGC; + CloseScreenProcPtr CloseScreen; +} PanoramiXScreenRec, *PanoramiXScreenPtr; + +RegionRec XineramaScreenRegions[MAXSCREENS]; + +static void XineramaValidateGC(GCPtr, unsigned long, DrawablePtr); +static void XineramaChangeGC(GCPtr, unsigned long); +static void XineramaCopyGC(GCPtr, unsigned long, GCPtr); +static void XineramaDestroyGC(GCPtr); +static void XineramaChangeClip(GCPtr, int, pointer, int); +static void XineramaDestroyClip(GCPtr); +static void XineramaCopyClip(GCPtr, GCPtr); + +static GCFuncs XineramaGCFuncs = { + XineramaValidateGC, XineramaChangeGC, XineramaCopyGC, XineramaDestroyGC, + XineramaChangeClip, XineramaDestroyClip, XineramaCopyClip +}; + +#define Xinerama_GC_FUNC_PROLOGUE(pGC)\ + PanoramiXGCPtr pGCPriv = (PanoramiXGCPtr) \ + dixLookupPrivate(&(pGC)->devPrivates, PanoramiXGCKey); \ + (pGC)->funcs = pGCPriv->wrapFuncs; + +#define Xinerama_GC_FUNC_EPILOGUE(pGC)\ + pGCPriv->wrapFuncs = (pGC)->funcs;\ + (pGC)->funcs = &XineramaGCFuncs; + + +static Bool +XineramaCloseScreen (int i, ScreenPtr pScreen) +{ + PanoramiXScreenPtr pScreenPriv = (PanoramiXScreenPtr) + dixLookupPrivate(&pScreen->devPrivates, PanoramiXScreenKey); + + pScreen->CloseScreen = pScreenPriv->CloseScreen; + pScreen->CreateGC = pScreenPriv->CreateGC; + + REGION_UNINIT(pScreen, &XineramaScreenRegions[pScreen->myNum]); + if (pScreen->myNum == 0) + REGION_UNINIT(pScreen, &PanoramiXScreenRegion); + + free((pointer) pScreenPriv); + + return (*pScreen->CloseScreen) (i, pScreen); +} + +static Bool +XineramaCreateGC(GCPtr pGC) +{ + ScreenPtr pScreen = pGC->pScreen; + PanoramiXScreenPtr pScreenPriv = (PanoramiXScreenPtr) + dixLookupPrivate(&pScreen->devPrivates, PanoramiXScreenKey); + Bool ret; + + pScreen->CreateGC = pScreenPriv->CreateGC; + if((ret = (*pScreen->CreateGC)(pGC))) { + PanoramiXGCPtr pGCPriv = (PanoramiXGCPtr) + dixLookupPrivate(&pGC->devPrivates, PanoramiXGCKey); + + pGCPriv->wrapFuncs = pGC->funcs; + pGC->funcs = &XineramaGCFuncs; + + pGCPriv->clipOrg.x = pGC->clipOrg.x; + pGCPriv->clipOrg.y = pGC->clipOrg.y; + pGCPriv->patOrg.x = pGC->patOrg.x; + pGCPriv->patOrg.y = pGC->patOrg.y; + } + pScreen->CreateGC = XineramaCreateGC; + + return ret; +} + +static void +XineramaValidateGC( + GCPtr pGC, + unsigned long changes, + DrawablePtr pDraw +){ + Xinerama_GC_FUNC_PROLOGUE (pGC); + + if((pDraw->type == DRAWABLE_WINDOW) && !(((WindowPtr)pDraw)->parent)) { + /* the root window */ + int x_off = panoramiXdataPtr[pGC->pScreen->myNum].x; + int y_off = panoramiXdataPtr[pGC->pScreen->myNum].y; + int new_val; + + new_val = pGCPriv->clipOrg.x - x_off; + if(pGC->clipOrg.x != new_val) { + pGC->clipOrg.x = new_val; + changes |= GCClipXOrigin; + } + new_val = pGCPriv->clipOrg.y - y_off; + if(pGC->clipOrg.y != new_val) { + pGC->clipOrg.y = new_val; + changes |= GCClipYOrigin; + } + new_val = pGCPriv->patOrg.x - x_off; + if(pGC->patOrg.x != new_val) { + pGC->patOrg.x = new_val; + changes |= GCTileStipXOrigin; + } + new_val = pGCPriv->patOrg.y - y_off; + if(pGC->patOrg.y != new_val) { + pGC->patOrg.y = new_val; + changes |= GCTileStipYOrigin; + } + } else { + if(pGC->clipOrg.x != pGCPriv->clipOrg.x) { + pGC->clipOrg.x = pGCPriv->clipOrg.x; + changes |= GCClipXOrigin; + } + if(pGC->clipOrg.y != pGCPriv->clipOrg.y) { + pGC->clipOrg.y = pGCPriv->clipOrg.y; + changes |= GCClipYOrigin; + } + if(pGC->patOrg.x != pGCPriv->patOrg.x) { + pGC->patOrg.x = pGCPriv->patOrg.x; + changes |= GCTileStipXOrigin; + } + if(pGC->patOrg.y != pGCPriv->patOrg.y) { + pGC->patOrg.y = pGCPriv->patOrg.y; + changes |= GCTileStipYOrigin; + } + } + + (*pGC->funcs->ValidateGC)(pGC, changes, pDraw); + Xinerama_GC_FUNC_EPILOGUE (pGC); +} + +static void +XineramaDestroyGC(GCPtr pGC) +{ + Xinerama_GC_FUNC_PROLOGUE (pGC); + (*pGC->funcs->DestroyGC)(pGC); + Xinerama_GC_FUNC_EPILOGUE (pGC); +} + +static void +XineramaChangeGC ( + GCPtr pGC, + unsigned long mask +){ + Xinerama_GC_FUNC_PROLOGUE (pGC); + + if(mask & GCTileStipXOrigin) + pGCPriv->patOrg.x = pGC->patOrg.x; + if(mask & GCTileStipYOrigin) + pGCPriv->patOrg.y = pGC->patOrg.y; + if(mask & GCClipXOrigin) + pGCPriv->clipOrg.x = pGC->clipOrg.x; + if(mask & GCClipYOrigin) + pGCPriv->clipOrg.y = pGC->clipOrg.y; + + (*pGC->funcs->ChangeGC) (pGC, mask); + Xinerama_GC_FUNC_EPILOGUE (pGC); +} + +static void +XineramaCopyGC ( + GCPtr pGCSrc, + unsigned long mask, + GCPtr pGCDst +){ + PanoramiXGCPtr pSrcPriv = (PanoramiXGCPtr) + dixLookupPrivate(&pGCSrc->devPrivates, PanoramiXGCKey); + Xinerama_GC_FUNC_PROLOGUE (pGCDst); + + if(mask & GCTileStipXOrigin) + pGCPriv->patOrg.x = pSrcPriv->patOrg.x; + if(mask & GCTileStipYOrigin) + pGCPriv->patOrg.y = pSrcPriv->patOrg.y; + if(mask & GCClipXOrigin) + pGCPriv->clipOrg.x = pSrcPriv->clipOrg.x; + if(mask & GCClipYOrigin) + pGCPriv->clipOrg.y = pSrcPriv->clipOrg.y; + + (*pGCDst->funcs->CopyGC) (pGCSrc, mask, pGCDst); + Xinerama_GC_FUNC_EPILOGUE (pGCDst); +} + +static void +XineramaChangeClip ( + GCPtr pGC, + int type, + pointer pvalue, + int nrects +){ + Xinerama_GC_FUNC_PROLOGUE (pGC); + (*pGC->funcs->ChangeClip) (pGC, type, pvalue, nrects); + Xinerama_GC_FUNC_EPILOGUE (pGC); +} + +static void +XineramaCopyClip(GCPtr pgcDst, GCPtr pgcSrc) +{ + Xinerama_GC_FUNC_PROLOGUE (pgcDst); + (* pgcDst->funcs->CopyClip)(pgcDst, pgcSrc); + Xinerama_GC_FUNC_EPILOGUE (pgcDst); +} + +static void +XineramaDestroyClip(GCPtr pGC) +{ + Xinerama_GC_FUNC_PROLOGUE (pGC); + (* pGC->funcs->DestroyClip)(pGC); + Xinerama_GC_FUNC_EPILOGUE (pGC); +} + +int +XineramaDeleteResource(pointer data, XID id) +{ + free(data); + return 1; +} + +typedef struct { + int screen; + int id; +} PanoramiXSearchData; + +static Bool +XineramaFindIDByScrnum(pointer resource, XID id, pointer privdata) +{ + PanoramiXRes *res = (PanoramiXRes*)resource; + PanoramiXSearchData *data = (PanoramiXSearchData*)privdata; + + return (res->info[data->screen].id == data->id); +} + +PanoramiXRes * +PanoramiXFindIDByScrnum(RESTYPE type, XID id, int screen) +{ + PanoramiXSearchData data; + pointer val; + + if(!screen) { + dixLookupResourceByType(&val, id, type, serverClient, DixReadAccess); + return val; + } + + data.screen = screen; + data.id = id; + + return LookupClientResourceComplex(clients[CLIENT_ID(id)], type, + XineramaFindIDByScrnum, &data); +} + +typedef struct _connect_callback_list { + void (*func)(void); + struct _connect_callback_list *next; +} XineramaConnectionCallbackList; + +static XineramaConnectionCallbackList *ConnectionCallbackList = NULL; + +Bool +XineramaRegisterConnectionBlockCallback(void (*func)(void)) +{ + XineramaConnectionCallbackList *newlist; + + if(!(newlist = malloc(sizeof(XineramaConnectionCallbackList)))) + return FALSE; + + newlist->next = ConnectionCallbackList; + newlist->func = func; + ConnectionCallbackList = newlist; + + return TRUE; +} + +static void XineramaInitData(ScreenPtr pScreen) +{ + int i, w, h; + + REGION_NULL(pScreen, &PanoramiXScreenRegion) + for (i = 0; i < PanoramiXNumScreens; i++) { + BoxRec TheBox; + + pScreen = screenInfo.screens[i]; + + panoramiXdataPtr[i].x = dixScreenOrigins[i].x; + panoramiXdataPtr[i].y = dixScreenOrigins[i].y; + panoramiXdataPtr[i].width = pScreen->width; + panoramiXdataPtr[i].height = pScreen->height; + + TheBox.x1 = panoramiXdataPtr[i].x; + TheBox.x2 = TheBox.x1 + panoramiXdataPtr[i].width; + TheBox.y1 = panoramiXdataPtr[i].y; + TheBox.y2 = TheBox.y1 + panoramiXdataPtr[i].height; + + REGION_INIT(pScreen, &XineramaScreenRegions[i], &TheBox, 1); + REGION_UNION(pScreen, &PanoramiXScreenRegion, &PanoramiXScreenRegion, + &XineramaScreenRegions[i]); + } + + PanoramiXPixWidth = panoramiXdataPtr[0].x + panoramiXdataPtr[0].width; + PanoramiXPixHeight = panoramiXdataPtr[0].y + panoramiXdataPtr[0].height; + + for (i = 1; i < PanoramiXNumScreens; i++) { + w = panoramiXdataPtr[i].x + panoramiXdataPtr[i].width; + h = panoramiXdataPtr[i].y + panoramiXdataPtr[i].height; + + if (PanoramiXPixWidth < w) + PanoramiXPixWidth = w; + if (PanoramiXPixHeight < h) + PanoramiXPixHeight = h; + } +} + +void XineramaReinitData(ScreenPtr pScreen) +{ + int i; + + REGION_UNINIT(pScreen, &PanoramiXScreenRegion); + for (i = 0; i < PanoramiXNumScreens; i++) + REGION_UNINIT(pScreen, &XineramaScreenRegions[i]); + + XineramaInitData(pScreen); +} + +/* + * PanoramiXExtensionInit(): + * Called from InitExtensions in main(). + * Register PanoramiXeen Extension + * Initialize global variables. + */ + +void PanoramiXExtensionInit(int argc, char *argv[]) +{ + int i; + Bool success = FALSE; + ExtensionEntry *extEntry; + ScreenPtr pScreen = screenInfo.screens[0]; + PanoramiXScreenPtr pScreenPriv; + + if (noPanoramiXExtension) + return; + + PanoramiXNumScreens = screenInfo.numScreens; + if (PanoramiXNumScreens == 1) { /* Only 1 screen */ + noPanoramiXExtension = TRUE; + return; + } + + while (panoramiXGeneration != serverGeneration) { + extEntry = AddExtension(PANORAMIX_PROTOCOL_NAME, 0,0, + ProcPanoramiXDispatch, + SProcPanoramiXDispatch, PanoramiXResetProc, + StandardMinorOpcode); + if (!extEntry) + break; + + /* + * First make sure all the basic allocations succeed. If not, + * run in non-PanoramiXeen mode. + */ + + panoramiXdataPtr = (PanoramiXData *) + calloc(PanoramiXNumScreens, sizeof(PanoramiXData)); + + if (!panoramiXdataPtr) + break; + + if (!dixRequestPrivate(PanoramiXGCKey, sizeof(PanoramiXGCRec))) { + noPanoramiXExtension = TRUE; + return; + } + + for (i = 0; i < PanoramiXNumScreens; i++) { + pScreen = screenInfo.screens[i]; + pScreenPriv = malloc(sizeof(PanoramiXScreenRec)); + dixSetPrivate(&pScreen->devPrivates, PanoramiXScreenKey, + pScreenPriv); + if(!pScreenPriv) { + noPanoramiXExtension = TRUE; + return; + } + + pScreenPriv->CreateGC = pScreen->CreateGC; + pScreenPriv->CloseScreen = pScreen->CloseScreen; + + pScreen->CreateGC = XineramaCreateGC; + pScreen->CloseScreen = XineramaCloseScreen; + } + + XRC_DRAWABLE = CreateNewResourceClass(); + XRT_WINDOW = CreateNewResourceType(XineramaDeleteResource, + "XineramaWindow"); + if (XRT_WINDOW) + XRT_WINDOW |= XRC_DRAWABLE; + XRT_PIXMAP = CreateNewResourceType(XineramaDeleteResource, + "XineramaPixmap"); + if (XRT_PIXMAP) + XRT_PIXMAP |= XRC_DRAWABLE; + XRT_GC = CreateNewResourceType(XineramaDeleteResource, + "XineramaGC"); + XRT_COLORMAP = CreateNewResourceType(XineramaDeleteResource, + "XineramaColormap"); + + if (XRT_WINDOW && XRT_PIXMAP && XRT_GC && XRT_COLORMAP) { + panoramiXGeneration = serverGeneration; + success = TRUE; + } + } + + if (!success) { + noPanoramiXExtension = TRUE; + ErrorF(PANORAMIX_PROTOCOL_NAME " extension failed to initialize\n"); + return; + } + + XineramaInitData(pScreen); + + /* + * Put our processes into the ProcVector + */ + + for (i = 256; i--; ) + SavedProcVector[i] = ProcVector[i]; + + ProcVector[X_CreateWindow] = PanoramiXCreateWindow; + ProcVector[X_ChangeWindowAttributes] = PanoramiXChangeWindowAttributes; + ProcVector[X_DestroyWindow] = PanoramiXDestroyWindow; + ProcVector[X_DestroySubwindows] = PanoramiXDestroySubwindows; + ProcVector[X_ChangeSaveSet] = PanoramiXChangeSaveSet; + ProcVector[X_ReparentWindow] = PanoramiXReparentWindow; + ProcVector[X_MapWindow] = PanoramiXMapWindow; + ProcVector[X_MapSubwindows] = PanoramiXMapSubwindows; + ProcVector[X_UnmapWindow] = PanoramiXUnmapWindow; + ProcVector[X_UnmapSubwindows] = PanoramiXUnmapSubwindows; + ProcVector[X_ConfigureWindow] = PanoramiXConfigureWindow; + ProcVector[X_CirculateWindow] = PanoramiXCirculateWindow; + ProcVector[X_GetGeometry] = PanoramiXGetGeometry; + ProcVector[X_TranslateCoords] = PanoramiXTranslateCoords; + ProcVector[X_CreatePixmap] = PanoramiXCreatePixmap; + ProcVector[X_FreePixmap] = PanoramiXFreePixmap; + ProcVector[X_CreateGC] = PanoramiXCreateGC; + ProcVector[X_ChangeGC] = PanoramiXChangeGC; + ProcVector[X_CopyGC] = PanoramiXCopyGC; + ProcVector[X_SetDashes] = PanoramiXSetDashes; + ProcVector[X_SetClipRectangles] = PanoramiXSetClipRectangles; + ProcVector[X_FreeGC] = PanoramiXFreeGC; + ProcVector[X_ClearArea] = PanoramiXClearToBackground; + ProcVector[X_CopyArea] = PanoramiXCopyArea; + ProcVector[X_CopyPlane] = PanoramiXCopyPlane; + ProcVector[X_PolyPoint] = PanoramiXPolyPoint; + ProcVector[X_PolyLine] = PanoramiXPolyLine; + ProcVector[X_PolySegment] = PanoramiXPolySegment; + ProcVector[X_PolyRectangle] = PanoramiXPolyRectangle; + ProcVector[X_PolyArc] = PanoramiXPolyArc; + ProcVector[X_FillPoly] = PanoramiXFillPoly; + ProcVector[X_PolyFillRectangle] = PanoramiXPolyFillRectangle; + ProcVector[X_PolyFillArc] = PanoramiXPolyFillArc; + ProcVector[X_PutImage] = PanoramiXPutImage; + ProcVector[X_GetImage] = PanoramiXGetImage; + ProcVector[X_PolyText8] = PanoramiXPolyText8; + ProcVector[X_PolyText16] = PanoramiXPolyText16; + ProcVector[X_ImageText8] = PanoramiXImageText8; + ProcVector[X_ImageText16] = PanoramiXImageText16; + ProcVector[X_CreateColormap] = PanoramiXCreateColormap; + ProcVector[X_FreeColormap] = PanoramiXFreeColormap; + ProcVector[X_CopyColormapAndFree] = PanoramiXCopyColormapAndFree; + ProcVector[X_InstallColormap] = PanoramiXInstallColormap; + ProcVector[X_UninstallColormap] = PanoramiXUninstallColormap; + ProcVector[X_AllocColor] = PanoramiXAllocColor; + ProcVector[X_AllocNamedColor] = PanoramiXAllocNamedColor; + ProcVector[X_AllocColorCells] = PanoramiXAllocColorCells; + ProcVector[X_AllocColorPlanes] = PanoramiXAllocColorPlanes; + ProcVector[X_FreeColors] = PanoramiXFreeColors; + ProcVector[X_StoreColors] = PanoramiXStoreColors; + ProcVector[X_StoreNamedColor] = PanoramiXStoreNamedColor; + + PanoramiXRenderInit (); +} + +extern Bool CreateConnectionBlock(void); + +Bool PanoramiXCreateConnectionBlock(void) +{ + int i, j, length; + Bool disableBackingStore = FALSE; + int old_width, old_height; + float width_mult, height_mult; + xWindowRoot *root; + xVisualType *visual; + xDepth *depth; + VisualPtr pVisual; + ScreenPtr pScreen; + + /* + * Do normal CreateConnectionBlock but faking it for only one screen + */ + + if(!PanoramiXNumDepths) { + ErrorF("Xinerama error: No common visuals\n"); + return FALSE; + } + + for(i = 1; i < screenInfo.numScreens; i++) { + pScreen = screenInfo.screens[i]; + if(pScreen->rootDepth != screenInfo.screens[0]->rootDepth) { + ErrorF("Xinerama error: Root window depths differ\n"); + return FALSE; + } + if(pScreen->backingStoreSupport != screenInfo.screens[0]->backingStoreSupport) + disableBackingStore = TRUE; + } + + if (disableBackingStore) { + for (i = 0; i < screenInfo.numScreens; i++) { + pScreen = screenInfo.screens[i]; + pScreen->backingStoreSupport = NotUseful; + } + } + + i = screenInfo.numScreens; + screenInfo.numScreens = 1; + if (!CreateConnectionBlock()) { + screenInfo.numScreens = i; + return FALSE; + } + + screenInfo.numScreens = i; + + root = (xWindowRoot *) (ConnectionInfo + connBlockScreenStart); + length = connBlockScreenStart + sizeof(xWindowRoot); + + /* overwrite the connection block */ + root->nDepths = PanoramiXNumDepths; + + for (i = 0; i < PanoramiXNumDepths; i++) { + depth = (xDepth *) (ConnectionInfo + length); + depth->depth = PanoramiXDepths[i].depth; + depth->nVisuals = PanoramiXDepths[i].numVids; + length += sizeof(xDepth); + visual = (xVisualType *)(ConnectionInfo + length); + + for (j = 0; j < depth->nVisuals; j++, visual++) { + visual->visualID = PanoramiXDepths[i].vids[j]; + + for (pVisual = PanoramiXVisuals; + pVisual->vid != visual->visualID; + pVisual++) + ; + + visual->class = pVisual->class; + visual->bitsPerRGB = pVisual->bitsPerRGBValue; + visual->colormapEntries = pVisual->ColormapEntries; + visual->redMask = pVisual->redMask; + visual->greenMask = pVisual->greenMask; + visual->blueMask = pVisual->blueMask; + } + + length += (depth->nVisuals * sizeof(xVisualType)); + } + + connSetupPrefix.length = bytes_to_int32(length); + + for (i = 0; i < PanoramiXNumDepths; i++) + free(PanoramiXDepths[i].vids); + free(PanoramiXDepths); + PanoramiXDepths = NULL; + + /* + * OK, change some dimensions so it looks as if it were one big screen + */ + + old_width = root->pixWidth; + old_height = root->pixHeight; + + root->pixWidth = PanoramiXPixWidth; + root->pixHeight = PanoramiXPixHeight; + width_mult = (1.0 * root->pixWidth) / old_width; + height_mult = (1.0 * root->pixHeight) / old_height; + root->mmWidth *= width_mult; + root->mmHeight *= height_mult; + + while(ConnectionCallbackList) { + pointer tmp; + + tmp = (pointer)ConnectionCallbackList; + (*ConnectionCallbackList->func)(); + ConnectionCallbackList = ConnectionCallbackList->next; + free(tmp); + } + + return TRUE; +} + +/* + * This isn't just memcmp(), bitsPerRGBValue is skipped. markv made that + * change way back before xf86 4.0, but the comment for _why_ is a bit + * opaque, so I'm not going to question it for now. + * + * This is probably better done as a screen hook so DBE/EVI/GLX can add + * their own tests, and adding privates to VisualRec so they don't have to + * do their own back-mapping. + */ +static Bool +VisualsEqual(VisualPtr a, ScreenPtr pScreenB, VisualPtr b) +{ + return ((a->class == b->class) && + (a->ColormapEntries == b->ColormapEntries) && + (a->nplanes == b->nplanes) && + (a->redMask == b->redMask) && + (a->greenMask == b->greenMask) && + (a->blueMask == b->blueMask) && + (a->offsetRed == b->offsetRed) && + (a->offsetGreen == b->offsetGreen) && + (a->offsetBlue == b->offsetBlue)); +} + +static void +PanoramiXMaybeAddDepth(DepthPtr pDepth) +{ + ScreenPtr pScreen; + int j, k; + Bool found = FALSE; + + for (j = 1; j < PanoramiXNumScreens; j++) { + pScreen = screenInfo.screens[j]; + for (k = 0; k < pScreen->numDepths; k++) { + if (pScreen->allowedDepths[k].depth == pDepth->depth) { + found = TRUE; + break; + } + } + } + + if (!found) + return; + + j = PanoramiXNumDepths; + PanoramiXNumDepths++; + PanoramiXDepths = realloc(PanoramiXDepths, + PanoramiXNumDepths * sizeof(DepthRec)); + PanoramiXDepths[j].depth = pDepth->depth; + PanoramiXDepths[j].numVids = 0; + /* XXX suboptimal, should grow these dynamically */ + if(pDepth->numVids) + PanoramiXDepths[j].vids = malloc(sizeof(VisualID) * pDepth->numVids); + else + PanoramiXDepths[j].vids = NULL; +} + +static void +PanoramiXMaybeAddVisual(VisualPtr pVisual) +{ + ScreenPtr pScreen; + int j, k; + Bool found = FALSE; + + for (j = 1; j < PanoramiXNumScreens; j++) { + pScreen = screenInfo.screens[j]; + found = FALSE; + + for (k = 0; k < pScreen->numVisuals; k++) { + VisualPtr candidate = &pScreen->visuals[k]; + + if ((*XineramaVisualsEqualPtr)(pVisual, pScreen, candidate) +#ifdef GLXPROXY + && glxMatchVisual(screenInfo.screens[0], pVisual, pScreen) +#endif + ) { + found = TRUE; + break; + } + } + + if (!found) + return; + } + + /* found a matching visual on all screens, add it to the subset list */ + j = PanoramiXNumVisuals; + PanoramiXNumVisuals++; + PanoramiXVisuals = realloc(PanoramiXVisuals, + PanoramiXNumVisuals * sizeof(VisualRec)); + + memcpy(&PanoramiXVisuals[j], pVisual, sizeof(VisualRec)); + + for (k = 0; k < PanoramiXNumDepths; k++) { + if (PanoramiXDepths[k].depth == pVisual->nplanes) { + PanoramiXDepths[k].vids[PanoramiXDepths[k].numVids] = pVisual->vid; + PanoramiXDepths[k].numVids++; + break; + } + } +} + +extern void +PanoramiXConsolidate(void) +{ + int i; + PanoramiXRes *root, *defmap, *saver; + ScreenPtr pScreen = screenInfo.screens[0]; + DepthPtr pDepth = pScreen->allowedDepths; + VisualPtr pVisual = pScreen->visuals; + + PanoramiXNumDepths = 0; + PanoramiXNumVisuals = 0; + + for (i = 0; i < pScreen->numDepths; i++) + PanoramiXMaybeAddDepth(pDepth++); + + for (i = 0; i < pScreen->numVisuals; i++) + PanoramiXMaybeAddVisual(pVisual++); + + root = malloc(sizeof(PanoramiXRes)); + root->type = XRT_WINDOW; + defmap = malloc(sizeof(PanoramiXRes)); + defmap->type = XRT_COLORMAP; + saver = malloc(sizeof(PanoramiXRes)); + saver->type = XRT_WINDOW; + + for (i = 0; i < PanoramiXNumScreens; i++) { + root->info[i].id = WindowTable[i]->drawable.id; + root->u.win.class = InputOutput; + root->u.win.root = TRUE; + saver->info[i].id = savedScreenInfo[i].wid; + saver->u.win.class = InputOutput; + saver->u.win.root = TRUE; + defmap->info[i].id = (screenInfo.screens[i])->defColormap; + } + + AddResource(root->info[0].id, XRT_WINDOW, root); + AddResource(saver->info[0].id, XRT_WINDOW, saver); + AddResource(defmap->info[0].id, XRT_COLORMAP, defmap); +} + +VisualID +PanoramiXTranslateVisualID(int screen, VisualID orig) +{ + ScreenPtr pOtherScreen = screenInfo.screens[screen]; + VisualPtr pVisual = NULL; + int i; + + for (i = 0; i < PanoramiXNumVisuals; i++) { + if (orig == PanoramiXVisuals[i].vid) { + pVisual = &PanoramiXVisuals[i]; + break; + } + } + + if (!pVisual) + return 0; + + /* if screen is 0, orig is already the correct visual ID */ + if (screen == 0) + return orig; + + /* found the original, now translate it relative to the backend screen */ + for (i = 0; i < pOtherScreen->numVisuals; i++) { + VisualPtr pOtherVisual = &pOtherScreen->visuals[i]; + + if ((*XineramaVisualsEqualPtr)(pVisual, pOtherScreen, pOtherVisual)) + return pOtherVisual->vid; + } + + return 0; +} + + +/* + * PanoramiXResetProc() + * Exit, deallocating as needed. + */ + +static void PanoramiXResetProc(ExtensionEntry* extEntry) +{ + int i; + + PanoramiXRenderReset (); + screenInfo.numScreens = PanoramiXNumScreens; + for (i = 256; i--; ) + ProcVector[i] = SavedProcVector[i]; + + free(panoramiXdataPtr); +} + + +int +ProcPanoramiXQueryVersion (ClientPtr client) +{ + /* REQUEST(xPanoramiXQueryVersionReq); */ + xPanoramiXQueryVersionReply rep; + register int n; + + REQUEST_SIZE_MATCH (xPanoramiXQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = SERVER_PANORAMIX_MAJOR_VERSION; + rep.minorVersion = SERVER_PANORAMIX_MINOR_VERSION; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.majorVersion, n); + swaps(&rep.minorVersion, n); + } + WriteToClient(client, sizeof (xPanoramiXQueryVersionReply), (char *)&rep); + return Success; +} + +int +ProcPanoramiXGetState(ClientPtr client) +{ + REQUEST(xPanoramiXGetStateReq); + WindowPtr pWin; + xPanoramiXGetStateReply rep; + int n, rc; + + REQUEST_SIZE_MATCH(xPanoramiXGetStateReq); + rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); + if (rc != Success) + return rc; + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.state = !noPanoramiXExtension; + rep.window = stuff->window; + if (client->swapped) { + swaps (&rep.sequenceNumber, n); + swapl (&rep.length, n); + swapl (&rep.window, n); + } + WriteToClient (client, sizeof (xPanoramiXGetStateReply), (char *) &rep); + return Success; + +} + +int +ProcPanoramiXGetScreenCount(ClientPtr client) +{ + REQUEST(xPanoramiXGetScreenCountReq); + WindowPtr pWin; + xPanoramiXGetScreenCountReply rep; + int n, rc; + + REQUEST_SIZE_MATCH(xPanoramiXGetScreenCountReq); + rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); + if (rc != Success) + return rc; + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.ScreenCount = PanoramiXNumScreens; + rep.window = stuff->window; + if (client->swapped) { + swaps (&rep.sequenceNumber, n); + swapl (&rep.length, n); + swapl (&rep.window, n); + } + WriteToClient (client, sizeof (xPanoramiXGetScreenCountReply), (char *) &rep); + return Success; +} + +int +ProcPanoramiXGetScreenSize(ClientPtr client) +{ + REQUEST(xPanoramiXGetScreenSizeReq); + WindowPtr pWin; + xPanoramiXGetScreenSizeReply rep; + int n, rc; + + if (stuff->screen >= PanoramiXNumScreens) + return BadMatch; + + REQUEST_SIZE_MATCH(xPanoramiXGetScreenSizeReq); + rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); + if (rc != Success) + return rc; + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + /* screen dimensions */ + rep.width = panoramiXdataPtr[stuff->screen].width; + rep.height = panoramiXdataPtr[stuff->screen].height; + rep.window = stuff->window; + rep.screen = stuff->screen; + if (client->swapped) { + swaps (&rep.sequenceNumber, n); + swapl (&rep.length, n); + swapl (&rep.width, n); + swapl (&rep.height, n); + swapl (&rep.window, n); + swapl (&rep.screen, n); + } + WriteToClient (client, sizeof (xPanoramiXGetScreenSizeReply), (char *) &rep); + return Success; +} + + +int +ProcXineramaIsActive(ClientPtr client) +{ + /* REQUEST(xXineramaIsActiveReq); */ + xXineramaIsActiveReply rep; + + REQUEST_SIZE_MATCH(xXineramaIsActiveReq); + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; +#if 1 + { + /* The following hack fools clients into thinking that Xinerama + * is disabled even though it is not. */ + rep.state = !noPanoramiXExtension && !PanoramiXExtensionDisabledHack; + } +#else + rep.state = !noPanoramiXExtension; +#endif + if (client->swapped) { + int n; + swaps (&rep.sequenceNumber, n); + swapl (&rep.length, n); + swapl (&rep.state, n); + } + WriteToClient (client, sizeof (xXineramaIsActiveReply), (char *) &rep); + return Success; +} + + +int +ProcXineramaQueryScreens(ClientPtr client) +{ + /* REQUEST(xXineramaQueryScreensReq); */ + xXineramaQueryScreensReply rep; + + REQUEST_SIZE_MATCH(xXineramaQueryScreensReq); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.number = (noPanoramiXExtension) ? 0 : PanoramiXNumScreens; + rep.length = bytes_to_int32(rep.number * sz_XineramaScreenInfo); + if (client->swapped) { + int n; + swaps (&rep.sequenceNumber, n); + swapl (&rep.length, n); + swapl (&rep.number, n); + } + WriteToClient (client, sizeof (xXineramaQueryScreensReply), (char *) &rep); + + if(!noPanoramiXExtension) { + xXineramaScreenInfo scratch; + int i; + + for(i = 0; i < PanoramiXNumScreens; i++) { + scratch.x_org = panoramiXdataPtr[i].x; + scratch.y_org = panoramiXdataPtr[i].y; + scratch.width = panoramiXdataPtr[i].width; + scratch.height = panoramiXdataPtr[i].height; + + if(client->swapped) { + int n; + swaps (&scratch.x_org, n); + swaps (&scratch.y_org, n); + swaps (&scratch.width, n); + swaps (&scratch.height, n); + } + WriteToClient (client, sz_XineramaScreenInfo, (char *) &scratch); + } + } + + return Success; +} + + +static int +ProcPanoramiXDispatch (ClientPtr client) +{ REQUEST(xReq); + switch (stuff->data) + { + case X_PanoramiXQueryVersion: + return ProcPanoramiXQueryVersion(client); + case X_PanoramiXGetState: + return ProcPanoramiXGetState(client); + case X_PanoramiXGetScreenCount: + return ProcPanoramiXGetScreenCount(client); + case X_PanoramiXGetScreenSize: + return ProcPanoramiXGetScreenSize(client); + case X_XineramaIsActive: + return ProcXineramaIsActive(client); + case X_XineramaQueryScreens: + return ProcXineramaQueryScreens(client); + } + return BadRequest; +} + + +#if X_BYTE_ORDER == X_LITTLE_ENDIAN +#define SHIFT_L(v,s) (v) << (s) +#define SHIFT_R(v,s) (v) >> (s) +#else +#define SHIFT_L(v,s) (v) >> (s) +#define SHIFT_R(v,s) (v) << (s) +#endif + +static void +CopyBits(char *dst, int shiftL, char *src, int bytes) +{ + /* Just get it to work. Worry about speed later */ + int shiftR = 8 - shiftL; + + while(bytes--) { + *dst |= SHIFT_L(*src, shiftL); + *(dst + 1) |= SHIFT_R(*src, shiftR); + dst++; src++; + } +} + + +/* Caution. This doesn't support 2 and 4 bpp formats. We expect + 1 bpp and planar data to be already cleared when presented + to this function */ + +void +XineramaGetImageData( + DrawablePtr *pDrawables, + int left, + int top, + int width, + int height, + unsigned int format, + unsigned long planemask, + char *data, + int pitch, + Bool isRoot +){ + RegionRec SrcRegion, GrabRegion; + BoxRec SrcBox, *pbox; + int x, y, w, h, i, j, nbox, size, sizeNeeded, ScratchPitch, inOut, depth; + DrawablePtr pDraw = pDrawables[0]; + char *ScratchMem = NULL; + + size = 0; + + /* find box in logical screen space */ + SrcBox.x1 = left; + SrcBox.y1 = top; + if(!isRoot) { + SrcBox.x1 += pDraw->x + panoramiXdataPtr[0].x; + SrcBox.y1 += pDraw->y + panoramiXdataPtr[0].y; + } + SrcBox.x2 = SrcBox.x1 + width; + SrcBox.y2 = SrcBox.y1 + height; + + REGION_INIT(pScreen, &SrcRegion, &SrcBox, 1); + REGION_NULL(pScreen, &GrabRegion); + + depth = (format == XYPixmap) ? 1 : pDraw->depth; + + for(i = 0; i < PanoramiXNumScreens; i++) { + pDraw = pDrawables[i]; + + inOut = RECT_IN_REGION(pScreen,&XineramaScreenRegions[i],&SrcBox); + + if(inOut == rgnIN) { + (*pDraw->pScreen->GetImage)(pDraw, + SrcBox.x1 - pDraw->x - panoramiXdataPtr[i].x, + SrcBox.y1 - pDraw->y - panoramiXdataPtr[i].y, + width, height, format, planemask, data); + break; + } else if (inOut == rgnOUT) + continue; + + REGION_INTERSECT(pScreen, &GrabRegion, &SrcRegion, + &XineramaScreenRegions[i]); + + nbox = REGION_NUM_RECTS(&GrabRegion); + + if(nbox) { + pbox = REGION_RECTS(&GrabRegion); + + while(nbox--) { + w = pbox->x2 - pbox->x1; + h = pbox->y2 - pbox->y1; + ScratchPitch = PixmapBytePad(w, depth); + sizeNeeded = ScratchPitch * h; + + if(sizeNeeded > size) { + char *tmpdata = ScratchMem; + ScratchMem = realloc(ScratchMem, sizeNeeded); + if(ScratchMem) + size = sizeNeeded; + else { + ScratchMem = tmpdata; + break; + } + } + + x = pbox->x1 - pDraw->x - panoramiXdataPtr[i].x; + y = pbox->y1 - pDraw->y - panoramiXdataPtr[i].y; + + (*pDraw->pScreen->GetImage)(pDraw, x, y, w, h, + format, planemask, ScratchMem); + + /* copy the memory over */ + + if(depth == 1) { + int k, shift, leftover, index, index2; + + x = pbox->x1 - SrcBox.x1; + y = pbox->y1 - SrcBox.y1; + shift = x & 7; + x >>= 3; + leftover = w & 7; + w >>= 3; + + /* clean up the edge */ + if(leftover) { + int mask = (1 << leftover) - 1; + for(j = h, k = w; j--; k += ScratchPitch) + ScratchMem[k] &= mask; + } + + for(j = 0, index = (pitch * y) + x, index2 = 0; j < h; + j++, index += pitch, index2 += ScratchPitch) + { + if(w) { + if(!shift) + memcpy(data + index, ScratchMem + index2, w); + else + CopyBits(data + index, shift, + ScratchMem + index2, w); + } + + if(leftover) { + data[index + w] |= + SHIFT_L(ScratchMem[index2 + w], shift); + if((shift + leftover) > 8) + data[index + w + 1] |= + SHIFT_R(ScratchMem[index2 + w],(8 - shift)); + } + } + } else { + j = BitsPerPixel(depth) >> 3; + x = (pbox->x1 - SrcBox.x1) * j; + y = pbox->y1 - SrcBox.y1; + w *= j; + + for(j = 0; j < h; j++) { + memcpy(data + (pitch * (y + j)) + x, + ScratchMem + (ScratchPitch * j), w); + } + } + pbox++; + } + + REGION_SUBTRACT(pScreen, &SrcRegion, &SrcRegion, &GrabRegion); + if(!REGION_NOTEMPTY(pScreen, &SrcRegion)) + break; + } + + } + + if(ScratchMem) + free(ScratchMem); + + REGION_UNINIT(pScreen, &SrcRegion); + REGION_UNINIT(pScreen, &GrabRegion); +} diff --git a/xorg-server/Xext/panoramiXprocs.c b/xorg-server/Xext/panoramiXprocs.c index 6635db905..369744c8c 100644 --- a/xorg-server/Xext/panoramiXprocs.c +++ b/xorg-server/Xext/panoramiXprocs.c @@ -1,2452 +1,2441 @@ -/***************************************************************** -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. -******************************************************************/ - -/* Massively rewritten by Mark Vojkovich */ - - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include -#include -#include -#include "windowstr.h" -#include "dixfontstr.h" -#include "gcstruct.h" -#include "colormapst.h" -#include "scrnintstr.h" -#include "opaque.h" -#include "inputstr.h" -#include "migc.h" -#include "misc.h" -#include "dixstruct.h" -#include "panoramiX.h" -#include "panoramiXsrv.h" -#include "resource.h" -#include "panoramiXh.h" - -#define XINERAMA_IMAGE_BUFSIZE (256*1024) -#define INPUTONLY_LEGAL_MASK (CWWinGravity | CWEventMask | \ - CWDontPropagate | CWOverrideRedirect | CWCursor ) - -/* Various of the DIX function interfaces were not designed to allow - * the client->errorValue to be set on BadValue and other errors. - * Rather than changing interfaces and breaking untold code we introduce - * a new global that dispatch can use. - */ -extern XID clientErrorValue; /* XXX this is a kludge */ - -int PanoramiXCreateWindow(ClientPtr client) -{ - PanoramiXRes *parent, *newWin; - PanoramiXRes *backPix = NULL; - PanoramiXRes *bordPix = NULL; - PanoramiXRes *cmap = NULL; - REQUEST(xCreateWindowReq); - int pback_offset = 0, pbord_offset = 0, cmap_offset = 0; - int result, len, j; - int orig_x, orig_y; - XID orig_visual, tmp; - Bool parentIsRoot; - - REQUEST_AT_LEAST_SIZE(xCreateWindowReq); - - len = client->req_len - bytes_to_int32(sizeof(xCreateWindowReq)); - if (Ones(stuff->mask) != len) - return BadLength; - - result = dixLookupResourceByType((pointer *)&parent, stuff->parent, - XRT_WINDOW, client, DixWriteAccess); - if (result != Success) - return (result == BadValue) ? BadWindow : result; - - if(stuff->class == CopyFromParent) - stuff->class = parent->u.win.class; - - if((stuff->class == InputOnly) && (stuff->mask & (~INPUTONLY_LEGAL_MASK))) - return BadMatch; - - if ((Mask)stuff->mask & CWBackPixmap) { - pback_offset = Ones((Mask)stuff->mask & (CWBackPixmap - 1)); - tmp = *((CARD32 *) &stuff[1] + pback_offset); - if ((tmp != None) && (tmp != ParentRelative)) { - result = dixLookupResourceByType((pointer *)&backPix, tmp, - XRT_PIXMAP, client, DixReadAccess); - if (result != Success) - return (result == BadValue) ? BadPixmap : result; - } - } - if ((Mask)stuff->mask & CWBorderPixmap) { - pbord_offset = Ones((Mask)stuff->mask & (CWBorderPixmap - 1)); - tmp = *((CARD32 *) &stuff[1] + pbord_offset); - if (tmp != CopyFromParent) { - result = dixLookupResourceByType((pointer *)&bordPix, tmp, - XRT_PIXMAP, client, DixReadAccess); - if (result != Success) - return (result == BadValue) ? BadPixmap : result; - } - } - if ((Mask)stuff->mask & CWColormap) { - cmap_offset = Ones((Mask)stuff->mask & (CWColormap - 1)); - tmp = *((CARD32 *) &stuff[1] + cmap_offset); - if ((tmp != CopyFromParent) && (tmp != None)) { - result = dixLookupResourceByType((pointer *)&cmap, tmp, - XRT_COLORMAP, client, DixReadAccess); - if (result != Success) - return (result == BadValue) ? BadColor : result; - } - } - - if(!(newWin = xalloc(sizeof(PanoramiXRes)))) - return BadAlloc; - - newWin->type = XRT_WINDOW; - newWin->u.win.visibility = VisibilityNotViewable; - newWin->u.win.class = stuff->class; - newWin->u.win.root = FALSE; - newWin->info[0].id = stuff->wid; - for(j = 1; j < PanoramiXNumScreens; j++) - newWin->info[j].id = FakeClientID(client->index); - - if (stuff->class == InputOnly) - stuff->visual = CopyFromParent; - orig_visual = stuff->visual; - orig_x = stuff->x; - orig_y = stuff->y; - parentIsRoot = (stuff->parent == WindowTable[0]->drawable.id) || - (stuff->parent == savedScreenInfo[0].wid); - FOR_NSCREENS_BACKWARD(j) { - stuff->wid = newWin->info[j].id; - stuff->parent = parent->info[j].id; - if (parentIsRoot) { - stuff->x = orig_x - panoramiXdataPtr[j].x; - stuff->y = orig_y - panoramiXdataPtr[j].y; - } - if (backPix) - *((CARD32 *) &stuff[1] + pback_offset) = backPix->info[j].id; - if (bordPix) - *((CARD32 *) &stuff[1] + pbord_offset) = bordPix->info[j].id; - if (cmap) - *((CARD32 *) &stuff[1] + cmap_offset) = cmap->info[j].id; - if ( orig_visual != CopyFromParent ) - stuff->visual = PanoramiXTranslateVisualID(j, orig_visual); - result = (*SavedProcVector[X_CreateWindow])(client); - if(result != Success) break; - } - - if (result == Success) - AddResource(newWin->info[0].id, XRT_WINDOW, newWin); - else - xfree(newWin); - - return (result); -} - - -int PanoramiXChangeWindowAttributes(ClientPtr client) -{ - PanoramiXRes *win; - PanoramiXRes *backPix = NULL; - PanoramiXRes *bordPix = NULL; - PanoramiXRes *cmap = NULL; - REQUEST(xChangeWindowAttributesReq); - int pback_offset = 0, pbord_offset = 0, cmap_offset = 0; - int result, len, j; - XID tmp; - - REQUEST_AT_LEAST_SIZE(xChangeWindowAttributesReq); - - len = client->req_len - bytes_to_int32(sizeof(xChangeWindowAttributesReq)); - if (Ones(stuff->valueMask) != len) - return BadLength; - - result = dixLookupResourceByType((pointer *)&win, stuff->window, - XRT_WINDOW, client, DixWriteAccess); - if (result != Success) - return (result == BadValue) ? BadWindow : result; - - if((win->u.win.class == InputOnly) && - (stuff->valueMask & (~INPUTONLY_LEGAL_MASK))) - return BadMatch; - - if ((Mask)stuff->valueMask & CWBackPixmap) { - pback_offset = Ones((Mask)stuff->valueMask & (CWBackPixmap - 1)); - tmp = *((CARD32 *) &stuff[1] + pback_offset); - if ((tmp != None) && (tmp != ParentRelative)) { - result = dixLookupResourceByType((pointer *)&backPix, tmp, - XRT_PIXMAP, client, DixReadAccess); - if (result != Success) - return (result == BadValue) ? BadPixmap : result; - } - } - if ((Mask)stuff->valueMask & CWBorderPixmap) { - pbord_offset = Ones((Mask)stuff->valueMask & (CWBorderPixmap - 1)); - tmp = *((CARD32 *) &stuff[1] + pbord_offset); - if (tmp != CopyFromParent) { - result = dixLookupResourceByType((pointer *)&bordPix, tmp, - XRT_PIXMAP, client, DixReadAccess); - if (result != Success) - return (result == BadValue) ? BadPixmap : result; - } - } - if ((Mask)stuff->valueMask & CWColormap) { - cmap_offset = Ones((Mask)stuff->valueMask & (CWColormap - 1)); - tmp = *((CARD32 *) &stuff[1] + cmap_offset); - if ((tmp != CopyFromParent) && (tmp != None)) { - result = dixLookupResourceByType((pointer *)&cmap, tmp, - XRT_COLORMAP, client, DixReadAccess); - if (result != Success) - return (result == BadValue) ? BadColor : result; - } - } - - FOR_NSCREENS_BACKWARD(j) { - stuff->window = win->info[j].id; - if (backPix) - *((CARD32 *) &stuff[1] + pback_offset) = backPix->info[j].id; - if (bordPix) - *((CARD32 *) &stuff[1] + pbord_offset) = bordPix->info[j].id; - if (cmap) - *((CARD32 *) &stuff[1] + cmap_offset) = cmap->info[j].id; - result = (*SavedProcVector[X_ChangeWindowAttributes])(client); - } - - return (result); -} - - -int PanoramiXDestroyWindow(ClientPtr client) -{ - PanoramiXRes *win; - int result, j; - REQUEST(xResourceReq); - - REQUEST_SIZE_MATCH(xResourceReq); - - result = dixLookupResourceByType((pointer *)&win, stuff->id, XRT_WINDOW, - client, DixDestroyAccess); - if (result != Success) - return (result == BadValue) ? BadWindow : result; - - FOR_NSCREENS_BACKWARD(j) { - stuff->id = win->info[j].id; - result = (*SavedProcVector[X_DestroyWindow])(client); - if(result != Success) break; - } - - /* Since ProcDestroyWindow is using FreeResource, it will free - our resource for us on the last pass through the loop above */ - - return (result); -} - - -int PanoramiXDestroySubwindows(ClientPtr client) -{ - PanoramiXRes *win; - int result, j; - REQUEST(xResourceReq); - - REQUEST_SIZE_MATCH(xResourceReq); - - result = dixLookupResourceByType((pointer *)&win, stuff->id, XRT_WINDOW, - client, DixDestroyAccess); - if (result != Success) - return (result == BadValue) ? BadWindow : result; - - FOR_NSCREENS_BACKWARD(j) { - stuff->id = win->info[j].id; - result = (*SavedProcVector[X_DestroySubwindows])(client); - if(result != Success) break; - } - - /* DestroySubwindows is using FreeResource which will free - our resources for us on the last pass through the loop above */ - - return (result); -} - - -int PanoramiXChangeSaveSet(ClientPtr client) -{ - PanoramiXRes *win; - int result, j; - REQUEST(xChangeSaveSetReq); - - REQUEST_SIZE_MATCH(xChangeSaveSetReq); - - result = dixLookupResourceByType((pointer *)&win, stuff->window, - XRT_WINDOW, client, DixReadAccess); - if (result != Success) - return (result == BadValue) ? BadWindow : result; - - FOR_NSCREENS_BACKWARD(j) { - stuff->window = win->info[j].id; - result = (*SavedProcVector[X_ChangeSaveSet])(client); - if(result != Success) break; - } - - return (result); -} - - -int PanoramiXReparentWindow(ClientPtr client) -{ - PanoramiXRes *win, *parent; - int result, j; - int x, y; - Bool parentIsRoot; - REQUEST(xReparentWindowReq); - - REQUEST_SIZE_MATCH(xReparentWindowReq); - - result = dixLookupResourceByType((pointer *)&win, stuff->window, - XRT_WINDOW, client, DixWriteAccess); - if (result != Success) - return (result == BadValue) ? BadWindow : result; - - result = dixLookupResourceByType((pointer *)&parent, stuff->parent, - XRT_WINDOW, client, DixWriteAccess); - if (result != Success) - return (result == BadValue) ? BadWindow : result; - - x = stuff->x; - y = stuff->y; - parentIsRoot = (stuff->parent == WindowTable[0]->drawable.id) || - (stuff->parent == savedScreenInfo[0].wid); - FOR_NSCREENS_BACKWARD(j) { - stuff->window = win->info[j].id; - stuff->parent = parent->info[j].id; - if(parentIsRoot) { - stuff->x = x - panoramiXdataPtr[j].x; - stuff->y = y - panoramiXdataPtr[j].y; - } - result = (*SavedProcVector[X_ReparentWindow])(client); - if(result != Success) break; - } - - return (result); -} - - -int PanoramiXMapWindow(ClientPtr client) -{ - PanoramiXRes *win; - int result, j; - REQUEST(xResourceReq); - - REQUEST_SIZE_MATCH(xResourceReq); - - result = dixLookupResourceByType((pointer *)&win, stuff->id, - XRT_WINDOW, client, DixReadAccess); - if (result != Success) - return (result == BadValue) ? BadWindow : result; - - FOR_NSCREENS_FORWARD(j) { - stuff->id = win->info[j].id; - result = (*SavedProcVector[X_MapWindow])(client); - if(result != Success) break; - } - - return (result); -} - - -int PanoramiXMapSubwindows(ClientPtr client) -{ - PanoramiXRes *win; - int result, j; - REQUEST(xResourceReq); - - REQUEST_SIZE_MATCH(xResourceReq); - - result = dixLookupResourceByType((pointer *)&win, stuff->id, - XRT_WINDOW, client, DixReadAccess); - if (result != Success) - return (result == BadValue) ? BadWindow : result; - - FOR_NSCREENS_FORWARD(j) { - stuff->id = win->info[j].id; - result = (*SavedProcVector[X_MapSubwindows])(client); - if(result != Success) break; - } - - return (result); -} - - -int PanoramiXUnmapWindow(ClientPtr client) -{ - PanoramiXRes *win; - int result, j; - REQUEST(xResourceReq); - - REQUEST_SIZE_MATCH(xResourceReq); - - result = dixLookupResourceByType((pointer *)&win, stuff->id, - XRT_WINDOW, client, DixReadAccess); - if (result != Success) - return (result == BadValue) ? BadWindow : result; - - FOR_NSCREENS_FORWARD(j) { - stuff->id = win->info[j].id; - result = (*SavedProcVector[X_UnmapWindow])(client); - if(result != Success) break; - } - - return (result); -} - - -int PanoramiXUnmapSubwindows(ClientPtr client) -{ - PanoramiXRes *win; - int result, j; - REQUEST(xResourceReq); - - REQUEST_SIZE_MATCH(xResourceReq); - - result = dixLookupResourceByType((pointer *)&win, stuff->id, - XRT_WINDOW, client, DixReadAccess); - if (result != Success) - return (result == BadValue) ? BadWindow : result; - - FOR_NSCREENS_FORWARD(j) { - stuff->id = win->info[j].id; - result = (*SavedProcVector[X_UnmapSubwindows])(client); - if(result != Success) break; - } - - return (result); -} - - -int PanoramiXConfigureWindow(ClientPtr client) -{ - PanoramiXRes *win; - PanoramiXRes *sib = NULL; - WindowPtr pWin; - int result, j, len, sib_offset = 0, x = 0, y = 0; - int x_offset = -1; - int y_offset = -1; - REQUEST(xConfigureWindowReq); - - REQUEST_AT_LEAST_SIZE(xConfigureWindowReq); - - len = client->req_len - bytes_to_int32(sizeof(xConfigureWindowReq)); - if (Ones(stuff->mask) != len) - return BadLength; - - /* because we need the parent */ - result = dixLookupResourceByType((pointer *)&pWin, stuff->window, - RT_WINDOW, client, DixWriteAccess); - if (result != Success) - return (result == BadValue) ? BadWindow : result; - - result = dixLookupResourceByType((pointer *)&win, stuff->window, - XRT_WINDOW, client, DixWriteAccess); - if (result != Success) - return (result == BadValue) ? BadWindow : result; - - if ((Mask)stuff->mask & CWSibling) { - XID tmp; - sib_offset = Ones((Mask)stuff->mask & (CWSibling - 1)); - if ((tmp = *((CARD32 *) &stuff[1] + sib_offset))) { - result = dixLookupResourceByType((pointer *)&sib, tmp, XRT_WINDOW, - client, DixReadAccess); - if (result != Success) - return (result == BadValue) ? BadWindow : result; - } - } - - if(pWin->parent && ((pWin->parent == WindowTable[0]) || - (pWin->parent->drawable.id == savedScreenInfo[0].wid))) - { - if ((Mask)stuff->mask & CWX) { - x_offset = 0; - x = *((CARD32 *)&stuff[1]); - } - if ((Mask)stuff->mask & CWY) { - y_offset = (x_offset == -1) ? 0 : 1; - y = *((CARD32 *) &stuff[1] + y_offset); - } - } - - /* have to go forward or you get expose events before - ConfigureNotify events */ - FOR_NSCREENS_FORWARD(j) { - stuff->window = win->info[j].id; - if(sib) - *((CARD32 *) &stuff[1] + sib_offset) = sib->info[j].id; - if(x_offset >= 0) - *((CARD32 *) &stuff[1] + x_offset) = x - panoramiXdataPtr[j].x; - if(y_offset >= 0) - *((CARD32 *) &stuff[1] + y_offset) = y - panoramiXdataPtr[j].y; - result = (*SavedProcVector[X_ConfigureWindow])(client); - if(result != Success) break; - } - - return (result); -} - - -int PanoramiXCirculateWindow(ClientPtr client) -{ - PanoramiXRes *win; - int result, j; - REQUEST(xCirculateWindowReq); - - REQUEST_SIZE_MATCH(xCirculateWindowReq); - - result = dixLookupResourceByType((pointer *)&win, stuff->window, - XRT_WINDOW, client, DixWriteAccess); - if (result != Success) - return (result == BadValue) ? BadWindow : result; - - FOR_NSCREENS_FORWARD(j) { - stuff->window = win->info[j].id; - result = (*SavedProcVector[X_CirculateWindow])(client); - if(result != Success) break; - } - - return (result); -} - - -int PanoramiXGetGeometry(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 = WindowTable[0]->drawable.id; - rep.depth = pDraw->depth; - rep.width = pDraw->width; - rep.height = pDraw->height; - rep.x = rep.y = rep.borderWidth = 0; - - if (stuff->id == rep.root) { - xWindowRoot *root = (xWindowRoot *) - (ConnectionInfo + connBlockScreenStart); - - rep.width = root->pixWidth; - rep.height = root->pixHeight; - } else - if ((pDraw->type == UNDRAWABLE_WINDOW) || (pDraw->type == DRAWABLE_WINDOW)) - { - WindowPtr pWin = (WindowPtr)pDraw; - rep.x = pWin->origin.x - wBorderWidth (pWin); - rep.y = pWin->origin.y - wBorderWidth (pWin); - if((pWin->parent == WindowTable[0]) || - (pWin->parent->drawable.id == savedScreenInfo[0].wid)) - { - rep.x += panoramiXdataPtr[0].x; - rep.y += panoramiXdataPtr[0].y; - } - rep.borderWidth = pWin->borderWidth; - } - - WriteReplyToClient(client, sizeof(xGetGeometryReply), &rep); - return (client->noClientException); -} - -int PanoramiXTranslateCoords(ClientPtr client) -{ - INT16 x, y; - REQUEST(xTranslateCoordsReq); - int rc; - WindowPtr pWin, pDst; - xTranslateCoordsReply rep; - - REQUEST_SIZE_MATCH(xTranslateCoordsReq); - rc = dixLookupWindow(&pWin, stuff->srcWid, client, DixReadAccess); - if (rc != Success) - return rc; - rc = dixLookupWindow(&pDst, stuff->dstWid, client, DixReadAccess); - if (rc != Success) - return rc; - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.sameScreen = xTrue; - rep.child = None; - - if((pWin == WindowTable[0]) || - (pWin->drawable.id == savedScreenInfo[0].wid)) - { - x = stuff->srcX - panoramiXdataPtr[0].x; - y = stuff->srcY - panoramiXdataPtr[0].y; - } else { - 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) || - POINT_IN_REGION(pWin->drawable.pScreen, - wBoundingShape(pWin), - x - pWin->drawable.x, - y - pWin->drawable.y, &box)) - ) - { - rep.child = pWin->drawable.id; - pWin = (WindowPtr) NULL; - } - else - pWin = pWin->nextSib; - } - rep.dstX = x - pDst->drawable.x; - rep.dstY = y - pDst->drawable.y; - if((pDst == WindowTable[0]) || - (pDst->drawable.id == savedScreenInfo[0].wid)) - { - rep.dstX += panoramiXdataPtr[0].x; - rep.dstY += panoramiXdataPtr[0].y; - } - - WriteReplyToClient(client, sizeof(xTranslateCoordsReply), &rep); - return(client->noClientException); -} - -int PanoramiXCreatePixmap(ClientPtr client) -{ - PanoramiXRes *refDraw, *newPix; - int result, j; - REQUEST(xCreatePixmapReq); - - REQUEST_SIZE_MATCH(xCreatePixmapReq); - client->errorValue = stuff->pid; - - result = dixLookupResourceByClass((pointer *)&refDraw, stuff->drawable, - XRC_DRAWABLE, client, DixReadAccess); - if (result != Success) - return (result == BadValue) ? BadDrawable : result; - - if(!(newPix = xalloc(sizeof(PanoramiXRes)))) - return BadAlloc; - - newPix->type = XRT_PIXMAP; - newPix->u.pix.shared = FALSE; - newPix->info[0].id = stuff->pid; - for(j = 1; j < PanoramiXNumScreens; j++) - newPix->info[j].id = FakeClientID(client->index); - - FOR_NSCREENS_BACKWARD(j) { - stuff->pid = newPix->info[j].id; - stuff->drawable = refDraw->info[j].id; - result = (*SavedProcVector[X_CreatePixmap])(client); - if(result != Success) break; - } - - if (result == Success) - AddResource(newPix->info[0].id, XRT_PIXMAP, newPix); - else - xfree(newPix); - - return (result); -} - - -int PanoramiXFreePixmap(ClientPtr client) -{ - PanoramiXRes *pix; - int result, j; - REQUEST(xResourceReq); - - REQUEST_SIZE_MATCH(xResourceReq); - - client->errorValue = stuff->id; - - result = dixLookupResourceByType((pointer *)&pix, stuff->id, XRT_PIXMAP, - client, DixDestroyAccess); - if (result != Success) - return (result == BadValue) ? BadPixmap : result; - - FOR_NSCREENS_BACKWARD(j) { - stuff->id = pix->info[j].id; - result = (*SavedProcVector[X_FreePixmap])(client); - if(result != Success) break; - } - - /* Since ProcFreePixmap is using FreeResource, it will free - our resource for us on the last pass through the loop above */ - - return (result); -} - - -int PanoramiXCreateGC(ClientPtr client) -{ - PanoramiXRes *refDraw; - PanoramiXRes *newGC; - PanoramiXRes *stip = NULL; - PanoramiXRes *tile = NULL; - PanoramiXRes *clip = NULL; - REQUEST(xCreateGCReq); - int tile_offset = 0, stip_offset = 0, clip_offset = 0; - int result, len, j; - XID tmp; - - REQUEST_AT_LEAST_SIZE(xCreateGCReq); - - client->errorValue = stuff->gc; - len = client->req_len - bytes_to_int32(sizeof(xCreateGCReq)); - if (Ones(stuff->mask) != len) - return BadLength; - - result = dixLookupResourceByClass((pointer *)&refDraw, stuff->drawable, - XRC_DRAWABLE, client, DixReadAccess); - if (result != Success) - return (result == BadValue) ? BadDrawable : result; - - if ((Mask)stuff->mask & GCTile) { - tile_offset = Ones((Mask)stuff->mask & (GCTile - 1)); - if ((tmp = *((CARD32 *) &stuff[1] + tile_offset))) { - result = dixLookupResourceByType((pointer *)&tile, tmp, XRT_PIXMAP, - client, DixReadAccess); - if (result != Success) - return (result == BadValue) ? BadPixmap : result; - } - } - if ((Mask)stuff->mask & GCStipple) { - stip_offset = Ones((Mask)stuff->mask & (GCStipple - 1)); - if ((tmp = *((CARD32 *) &stuff[1] + stip_offset))) { - result = dixLookupResourceByType((pointer *)&stip, tmp, XRT_PIXMAP, - client, DixReadAccess); - if (result != Success) - return (result == BadValue) ? BadPixmap : result; - } - } - if ((Mask)stuff->mask & GCClipMask) { - clip_offset = Ones((Mask)stuff->mask & (GCClipMask - 1)); - if ((tmp = *((CARD32 *) &stuff[1] + clip_offset))) { - result = dixLookupResourceByType((pointer *)&clip, tmp, XRT_PIXMAP, - client, DixReadAccess); - if (result != Success) - return (result == BadValue) ? BadPixmap : result; - } - } - - if(!(newGC = xalloc(sizeof(PanoramiXRes)))) - return BadAlloc; - - newGC->type = XRT_GC; - newGC->info[0].id = stuff->gc; - for(j = 1; j < PanoramiXNumScreens; j++) - newGC->info[j].id = FakeClientID(client->index); - - FOR_NSCREENS_BACKWARD(j) { - stuff->gc = newGC->info[j].id; - stuff->drawable = refDraw->info[j].id; - if (tile) - *((CARD32 *) &stuff[1] + tile_offset) = tile->info[j].id; - if (stip) - *((CARD32 *) &stuff[1] + stip_offset) = stip->info[j].id; - if (clip) - *((CARD32 *) &stuff[1] + clip_offset) = clip->info[j].id; - result = (*SavedProcVector[X_CreateGC])(client); - if(result != Success) break; - } - - if (result == Success) - AddResource(newGC->info[0].id, XRT_GC, newGC); - else - xfree(newGC); - - return (result); -} - -int PanoramiXChangeGC(ClientPtr client) -{ - PanoramiXRes *gc; - PanoramiXRes *stip = NULL; - PanoramiXRes *tile = NULL; - PanoramiXRes *clip = NULL; - REQUEST(xChangeGCReq); - int tile_offset = 0, stip_offset = 0, clip_offset = 0; - int result, len, j; - XID tmp; - - REQUEST_AT_LEAST_SIZE(xChangeGCReq); - - len = client->req_len - bytes_to_int32(sizeof(xChangeGCReq)); - if (Ones(stuff->mask) != len) - return BadLength; - - result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC, - client, DixReadAccess); - if (result != Success) - return (result == BadValue) ? BadGC : result; - - if ((Mask)stuff->mask & GCTile) { - tile_offset = Ones((Mask)stuff->mask & (GCTile - 1)); - if ((tmp = *((CARD32 *) &stuff[1] + tile_offset))) { - result = dixLookupResourceByType((pointer *)&tile, tmp, XRT_PIXMAP, - client, DixReadAccess); - if (result != Success) - return (result == BadValue) ? BadPixmap : result; - } - } - if ((Mask)stuff->mask & GCStipple) { - stip_offset = Ones((Mask)stuff->mask & (GCStipple - 1)); - if ((tmp = *((CARD32 *) &stuff[1] + stip_offset))) { - result = dixLookupResourceByType((pointer *)&stip, tmp, XRT_PIXMAP, - client, DixReadAccess); - if (result != Success) - return (result == BadValue) ? BadPixmap : result; - } - } - if ((Mask)stuff->mask & GCClipMask) { - clip_offset = Ones((Mask)stuff->mask & (GCClipMask - 1)); - if ((tmp = *((CARD32 *) &stuff[1] + clip_offset))) { - result = dixLookupResourceByType((pointer *)&clip, tmp, XRT_PIXMAP, - client, DixReadAccess); - if (result != Success) - return (result == BadValue) ? BadPixmap : result; - } - } - - - FOR_NSCREENS_BACKWARD(j) { - stuff->gc = gc->info[j].id; - if (tile) - *((CARD32 *) &stuff[1] + tile_offset) = tile->info[j].id; - if (stip) - *((CARD32 *) &stuff[1] + stip_offset) = stip->info[j].id; - if (clip) - *((CARD32 *) &stuff[1] + clip_offset) = clip->info[j].id; - result = (*SavedProcVector[X_ChangeGC])(client); - if(result != Success) break; - } - - return (result); -} - - -int PanoramiXCopyGC(ClientPtr client) -{ - PanoramiXRes *srcGC, *dstGC; - int result, j; - REQUEST(xCopyGCReq); - - REQUEST_SIZE_MATCH(xCopyGCReq); - - result = dixLookupResourceByType((pointer *)&srcGC, stuff->srcGC, XRT_GC, - client, DixReadAccess); - if (result != Success) - return (result == BadValue) ? BadGC : result; - - result = dixLookupResourceByType((pointer *)&dstGC, stuff->dstGC, XRT_GC, - client, DixWriteAccess); - if (result != Success) - return (result == BadValue) ? BadGC : result; - - FOR_NSCREENS(j) { - stuff->srcGC = srcGC->info[j].id; - stuff->dstGC = dstGC->info[j].id; - result = (*SavedProcVector[X_CopyGC])(client); - if(result != Success) break; - } - - return (result); -} - - -int PanoramiXSetDashes(ClientPtr client) -{ - PanoramiXRes *gc; - int result, j; - REQUEST(xSetDashesReq); - - REQUEST_FIXED_SIZE(xSetDashesReq, stuff->nDashes); - - result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC, - client, DixWriteAccess); - if (result != Success) - return (result == BadValue) ? BadGC : result; - - FOR_NSCREENS_BACKWARD(j) { - stuff->gc = gc->info[j].id; - result = (*SavedProcVector[X_SetDashes])(client); - if(result != Success) break; - } - - return (result); -} - - -int PanoramiXSetClipRectangles(ClientPtr client) -{ - PanoramiXRes *gc; - int result, j; - REQUEST(xSetClipRectanglesReq); - - REQUEST_AT_LEAST_SIZE(xSetClipRectanglesReq); - - result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC, - client, DixWriteAccess); - if (result != Success) - return (result == BadValue) ? BadGC : result; - - FOR_NSCREENS_BACKWARD(j) { - stuff->gc = gc->info[j].id; - result = (*SavedProcVector[X_SetClipRectangles])(client); - if(result != Success) break; - } - - return (result); -} - - -int PanoramiXFreeGC(ClientPtr client) -{ - PanoramiXRes *gc; - int result, j; - REQUEST(xResourceReq); - - REQUEST_SIZE_MATCH(xResourceReq); - - result = dixLookupResourceByType((pointer *)&gc, stuff->id, XRT_GC, - client, DixDestroyAccess); - if (result != Success) - return (result == BadValue) ? BadGC : result; - - FOR_NSCREENS_BACKWARD(j) { - stuff->id = gc->info[j].id; - result = (*SavedProcVector[X_FreeGC])(client); - if(result != Success) break; - } - - /* Since ProcFreeGC is using FreeResource, it will free - our resource for us on the last pass through the loop above */ - - return (result); -} - - -int PanoramiXClearToBackground(ClientPtr client) -{ - PanoramiXRes *win; - int result, j, x, y; - Bool isRoot; - REQUEST(xClearAreaReq); - - REQUEST_SIZE_MATCH(xClearAreaReq); - - result = dixLookupResourceByType((pointer *)&win, stuff->window, - XRT_WINDOW, client, DixWriteAccess); - if (result != Success) - return (result == BadValue) ? BadWindow : result; - - x = stuff->x; - y = stuff->y; - isRoot = win->u.win.root; - FOR_NSCREENS_BACKWARD(j) { - stuff->window = win->info[j].id; - if(isRoot) { - stuff->x = x - panoramiXdataPtr[j].x; - stuff->y = y - panoramiXdataPtr[j].y; - } - result = (*SavedProcVector[X_ClearArea])(client); - if(result != Success) break; - } - - return (result); -} - - -/* - For Window to Pixmap copies you're screwed since each screen's - pixmap will look like what it sees on its screen. Unless the - screens overlap and the window lies on each, the two copies - will be out of sync. To remedy this we do a GetImage and PutImage - in place of the copy. Doing this as a single Image isn't quite - correct since it will include the obscured areas but we will - have to fix this later. (MArk). -*/ - -int PanoramiXCopyArea(ClientPtr client) -{ - int j, result, srcx, srcy, dstx, dsty; - PanoramiXRes *gc, *src, *dst; - Bool srcIsRoot = FALSE; - Bool dstIsRoot = FALSE; - Bool srcShared, dstShared; - REQUEST(xCopyAreaReq); - - REQUEST_SIZE_MATCH(xCopyAreaReq); - - result = dixLookupResourceByClass((pointer *)&src, stuff->srcDrawable, - XRC_DRAWABLE, client, DixReadAccess); - if (result != Success) - return (result == BadValue) ? BadDrawable : result; - - srcShared = IS_SHARED_PIXMAP(src); - - result = dixLookupResourceByClass((pointer *)&dst, stuff->dstDrawable, - XRC_DRAWABLE, client, DixWriteAccess); - if (result != Success) - return (result == BadValue) ? BadDrawable : result; - - dstShared = IS_SHARED_PIXMAP(dst); - - if(dstShared && srcShared) - return (* SavedProcVector[X_CopyArea])(client); - - result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC, - client, DixReadAccess); - if (result != Success) - return (result == BadValue) ? BadGC : result; - - if((dst->type == XRT_WINDOW) && dst->u.win.root) - dstIsRoot = TRUE; - if((src->type == XRT_WINDOW) && src->u.win.root) - srcIsRoot = TRUE; - - srcx = stuff->srcX; srcy = stuff->srcY; - dstx = stuff->dstX; dsty = stuff->dstY; - if((dst->type == XRT_PIXMAP) && (src->type == XRT_WINDOW)) { - DrawablePtr drawables[MAXSCREENS]; - DrawablePtr pDst; - GCPtr pGC; - char *data; - int pitch, rc; - - FOR_NSCREENS(j) { - rc = dixLookupDrawable(drawables+j, src->info[j].id, client, 0, - DixGetAttrAccess); - if (rc != Success) - return rc; - } - - pitch = PixmapBytePad(stuff->width, drawables[0]->depth); - if(!(data = xcalloc(1, stuff->height * pitch))) - return BadAlloc; - - XineramaGetImageData(drawables, srcx, srcy, - stuff->width, stuff->height, ZPixmap, ~0, data, pitch, - srcIsRoot); - - FOR_NSCREENS_BACKWARD(j) { - stuff->gc = gc->info[j].id; - VALIDATE_DRAWABLE_AND_GC(dst->info[j].id, pDst, DixWriteAccess); - if(drawables[0]->depth != pDst->depth) { - client->errorValue = stuff->dstDrawable; - xfree(data); - return (BadMatch); - } - - (*pGC->ops->PutImage) (pDst, pGC, pDst->depth, dstx, dsty, - stuff->width, stuff->height, - 0, ZPixmap, data); - - if(dstShared) break; - } - - xfree(data); - - result = Success; - } else { - DrawablePtr pDst = NULL, pSrc = NULL; - GCPtr pGC = NULL; - RegionPtr pRgn[MAXSCREENS]; - int rc; - - FOR_NSCREENS_BACKWARD(j) { - stuff->dstDrawable = dst->info[j].id; - stuff->srcDrawable = src->info[j].id; - stuff->gc = gc->info[j].id; - if (srcIsRoot) { - stuff->srcX = srcx - panoramiXdataPtr[j].x; - stuff->srcY = srcy - panoramiXdataPtr[j].y; - } - if (dstIsRoot) { - stuff->dstX = dstx - panoramiXdataPtr[j].x; - stuff->dstY = dsty - panoramiXdataPtr[j].y; - } - - 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[j] = (*pGC->ops->CopyArea)(pSrc, pDst, pGC, - stuff->srcX, stuff->srcY, - stuff->width, stuff->height, - stuff->dstX, stuff->dstY); - - if(dstShared) { - while(j--) pRgn[j] = NULL; - break; - } - } - - if(pGC->graphicsExposures) { - ScreenPtr pScreen = pDst->pScreen; - RegionRec totalReg; - Bool overlap; - - REGION_NULL(pScreen, &totalReg); - FOR_NSCREENS_BACKWARD(j) { - if(pRgn[j]) { - if(srcIsRoot) { - REGION_TRANSLATE(pScreen, pRgn[j], - panoramiXdataPtr[j].x, panoramiXdataPtr[j].y); - } - REGION_APPEND(pScreen, &totalReg, pRgn[j]); - REGION_DESTROY(pScreen, pRgn[j]); - } - } - REGION_VALIDATE(pScreen, &totalReg, &overlap); - (*pScreen->SendGraphicsExpose)( - client, &totalReg, stuff->dstDrawable, X_CopyArea, 0); - REGION_UNINIT(pScreen, &totalReg); - } - - result = client->noClientException; - } - - return (result); -} - - -int PanoramiXCopyPlane(ClientPtr client) -{ - int j, srcx, srcy, dstx, dsty, rc; - PanoramiXRes *gc, *src, *dst; - Bool srcIsRoot = FALSE; - Bool dstIsRoot = FALSE; - Bool srcShared, dstShared; - DrawablePtr psrcDraw, pdstDraw = NULL; - GCPtr pGC = NULL; - RegionPtr pRgn[MAXSCREENS]; - REQUEST(xCopyPlaneReq); - - REQUEST_SIZE_MATCH(xCopyPlaneReq); - - rc = dixLookupResourceByClass((pointer *)&src, stuff->srcDrawable, - XRC_DRAWABLE, client, DixReadAccess); - if (rc != Success) - return (rc == BadValue) ? BadDrawable : rc; - - srcShared = IS_SHARED_PIXMAP(src); - - rc = dixLookupResourceByClass((pointer *)&dst, stuff->dstDrawable, - XRC_DRAWABLE, client, DixWriteAccess); - if (rc != Success) - return (rc == BadValue) ? BadDrawable : rc; - - dstShared = IS_SHARED_PIXMAP(dst); - - if(dstShared && srcShared) - return (* SavedProcVector[X_CopyPlane])(client); - - rc = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC, - client, DixReadAccess); - if (rc != Success) - return (rc == BadValue) ? BadGC : rc; - - if((dst->type == XRT_WINDOW) && dst->u.win.root) - dstIsRoot = TRUE; - if((src->type == XRT_WINDOW) && src->u.win.root) - srcIsRoot = TRUE; - - srcx = stuff->srcX; srcy = stuff->srcY; - dstx = stuff->dstX; dsty = stuff->dstY; - - FOR_NSCREENS_BACKWARD(j) { - stuff->dstDrawable = dst->info[j].id; - stuff->srcDrawable = src->info[j].id; - stuff->gc = gc->info[j].id; - if (srcIsRoot) { - stuff->srcX = srcx - panoramiXdataPtr[j].x; - stuff->srcY = srcy - panoramiXdataPtr[j].y; - } - if (dstIsRoot) { - stuff->dstX = dstx - panoramiXdataPtr[j].x; - stuff->dstY = dsty - panoramiXdataPtr[j].y; - } - - 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; - - if(stuff->bitPlane == 0 || (stuff->bitPlane & (stuff->bitPlane - 1)) || - (stuff->bitPlane > (1L << (psrcDraw->depth - 1)))) { - client->errorValue = stuff->bitPlane; - return(BadValue); - } - - pRgn[j] = (*pGC->ops->CopyPlane)(psrcDraw, pdstDraw, pGC, - stuff->srcX, stuff->srcY, - stuff->width, stuff->height, - stuff->dstX, stuff->dstY, stuff->bitPlane); - - if(dstShared) { - while(j--) pRgn[j] = NULL; - break; - } - } - - if(pGC->graphicsExposures) { - ScreenPtr pScreen = pdstDraw->pScreen; - RegionRec totalReg; - Bool overlap; - - REGION_NULL(pScreen, &totalReg); - FOR_NSCREENS_BACKWARD(j) { - if(pRgn[j]) { - REGION_APPEND(pScreen, &totalReg, pRgn[j]); - REGION_DESTROY(pScreen, pRgn[j]); - } - } - REGION_VALIDATE(pScreen, &totalReg, &overlap); - (*pScreen->SendGraphicsExpose)( - client, &totalReg, stuff->dstDrawable, X_CopyPlane, 0); - REGION_UNINIT(pScreen, &totalReg); - } - - return (client->noClientException); -} - - -int PanoramiXPolyPoint(ClientPtr client) -{ - PanoramiXRes *gc, *draw; - int result, npoint, j; - xPoint *origPts; - Bool isRoot; - REQUEST(xPolyPointReq); - - REQUEST_AT_LEAST_SIZE(xPolyPointReq); - - result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable, - XRC_DRAWABLE, client, DixWriteAccess); - if (result != Success) - return (result == BadValue) ? BadDrawable : result; - - if(IS_SHARED_PIXMAP(draw)) - return (*SavedProcVector[X_PolyPoint])(client); - - result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC, - client, DixReadAccess); - if (result != Success) - return (result == BadValue) ? BadGC : result; - - isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; - npoint = bytes_to_int32((client->req_len << 2) - sizeof(xPolyPointReq)); - if (npoint > 0) { - origPts = xalloc(npoint * sizeof(xPoint)); - memcpy((char *) origPts, (char *) &stuff[1], npoint * sizeof(xPoint)); - FOR_NSCREENS_FORWARD(j){ - - if(j) memcpy(&stuff[1], origPts, npoint * sizeof(xPoint)); - - if (isRoot) { - int x_off = panoramiXdataPtr[j].x; - int y_off = panoramiXdataPtr[j].y; - - if(x_off || y_off) { - xPoint *pnts = (xPoint*)&stuff[1]; - int i = (stuff->coordMode==CoordModePrevious) ? 1 : npoint; - - while(i--) { - pnts->x -= x_off; - pnts->y -= y_off; - pnts++; - } - } - } - - stuff->drawable = draw->info[j].id; - stuff->gc = gc->info[j].id; - result = (* SavedProcVector[X_PolyPoint])(client); - if(result != Success) break; - } - xfree(origPts); - return (result); - } else - return (client->noClientException); -} - - -int PanoramiXPolyLine(ClientPtr client) -{ - PanoramiXRes *gc, *draw; - int result, npoint, j; - xPoint *origPts; - Bool isRoot; - REQUEST(xPolyLineReq); - - REQUEST_AT_LEAST_SIZE(xPolyLineReq); - - result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable, - XRC_DRAWABLE, client, DixWriteAccess); - if (result != Success) - return (result == BadValue) ? BadDrawable : result; - - if(IS_SHARED_PIXMAP(draw)) - return (*SavedProcVector[X_PolyLine])(client); - - result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC, - client, DixReadAccess); - if (result != Success) - return (result == BadValue) ? BadGC : result; - - isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; - npoint = bytes_to_int32((client->req_len << 2) - sizeof(xPolyLineReq)); - if (npoint > 0){ - origPts = xalloc(npoint * sizeof(xPoint)); - memcpy((char *) origPts, (char *) &stuff[1], npoint * sizeof(xPoint)); - FOR_NSCREENS_FORWARD(j){ - - if(j) memcpy(&stuff[1], origPts, npoint * sizeof(xPoint)); - - if (isRoot) { - int x_off = panoramiXdataPtr[j].x; - int y_off = panoramiXdataPtr[j].y; - - if(x_off || y_off) { - xPoint *pnts = (xPoint*)&stuff[1]; - int i = (stuff->coordMode==CoordModePrevious) ? 1 : npoint; - - while(i--) { - pnts->x -= x_off; - pnts->y -= y_off; - pnts++; - } - } - } - - stuff->drawable = draw->info[j].id; - stuff->gc = gc->info[j].id; - result = (* SavedProcVector[X_PolyLine])(client); - if(result != Success) break; - } - xfree(origPts); - return (result); - } else - return (client->noClientException); -} - - -int PanoramiXPolySegment(ClientPtr client) -{ - int result, nsegs, i, j; - PanoramiXRes *gc, *draw; - xSegment *origSegs; - Bool isRoot; - REQUEST(xPolySegmentReq); - - REQUEST_AT_LEAST_SIZE(xPolySegmentReq); - - result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable, - XRC_DRAWABLE, client, DixWriteAccess); - if (result != Success) - return (result == BadValue) ? BadDrawable : result; - - if(IS_SHARED_PIXMAP(draw)) - return (*SavedProcVector[X_PolySegment])(client); - - result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC, - client, DixReadAccess); - if (result != Success) - return (result == BadValue) ? BadGC : result; - - isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; - - nsegs = (client->req_len << 2) - sizeof(xPolySegmentReq); - if(nsegs & 4) return BadLength; - nsegs >>= 3; - if (nsegs > 0) { - origSegs = xalloc(nsegs * sizeof(xSegment)); - memcpy((char *) origSegs, (char *) &stuff[1], nsegs * sizeof(xSegment)); - FOR_NSCREENS_FORWARD(j){ - - if(j) memcpy(&stuff[1], origSegs, nsegs * sizeof(xSegment)); - - if (isRoot) { - int x_off = panoramiXdataPtr[j].x; - int y_off = panoramiXdataPtr[j].y; - - if(x_off || y_off) { - xSegment *segs = (xSegment*)&stuff[1]; - - for (i = nsegs; i--; segs++) { - segs->x1 -= x_off; - segs->x2 -= x_off; - segs->y1 -= y_off; - segs->y2 -= y_off; - } - } - } - - stuff->drawable = draw->info[j].id; - stuff->gc = gc->info[j].id; - result = (* SavedProcVector[X_PolySegment])(client); - if(result != Success) break; - } - xfree(origSegs); - return (result); - } else - return (client->noClientException); -} - - -int PanoramiXPolyRectangle(ClientPtr client) -{ - int result, nrects, i, j; - PanoramiXRes *gc, *draw; - Bool isRoot; - xRectangle *origRecs; - REQUEST(xPolyRectangleReq); - - REQUEST_AT_LEAST_SIZE(xPolyRectangleReq); - - result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable, - XRC_DRAWABLE, client, DixWriteAccess); - if (result != Success) - return (result == BadValue) ? BadDrawable : result; - - if(IS_SHARED_PIXMAP(draw)) - return (*SavedProcVector[X_PolyRectangle])(client); - - result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC, - client, DixReadAccess); - if (result != Success) - return (result == BadValue) ? BadGC : result; - - isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; - - nrects = (client->req_len << 2) - sizeof(xPolyRectangleReq); - if(nrects & 4) return BadLength; - nrects >>= 3; - if (nrects > 0){ - origRecs = xalloc(nrects * sizeof(xRectangle)); - memcpy((char *)origRecs,(char *)&stuff[1],nrects * sizeof(xRectangle)); - FOR_NSCREENS_FORWARD(j){ - - if(j) memcpy(&stuff[1], origRecs, nrects * sizeof(xRectangle)); - - if (isRoot) { - int x_off = panoramiXdataPtr[j].x; - int y_off = panoramiXdataPtr[j].y; - - - if(x_off || y_off) { - xRectangle *rects = (xRectangle *) &stuff[1]; - - for (i = nrects; i--; rects++) { - rects->x -= x_off; - rects->y -= y_off; - } - } - } - - stuff->drawable = draw->info[j].id; - stuff->gc = gc->info[j].id; - result = (* SavedProcVector[X_PolyRectangle])(client); - if(result != Success) break; - } - xfree(origRecs); - return (result); - } else - return (client->noClientException); -} - - -int PanoramiXPolyArc(ClientPtr client) -{ - int result, narcs, i, j; - PanoramiXRes *gc, *draw; - Bool isRoot; - xArc *origArcs; - REQUEST(xPolyArcReq); - - REQUEST_AT_LEAST_SIZE(xPolyArcReq); - - result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable, - XRC_DRAWABLE, client, DixWriteAccess); - if (result != Success) - return (result == BadValue) ? BadDrawable : result; - - if(IS_SHARED_PIXMAP(draw)) - return (*SavedProcVector[X_PolyArc])(client); - - result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC, - client, DixReadAccess); - if (result != Success) - return (result == BadValue) ? BadGC : result; - - isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; - - narcs = (client->req_len << 2) - sizeof(xPolyArcReq); - if(narcs % sizeof(xArc)) return BadLength; - narcs /= sizeof(xArc); - if (narcs > 0){ - origArcs = xalloc(narcs * sizeof(xArc)); - memcpy((char *) origArcs, (char *) &stuff[1], narcs * sizeof(xArc)); - FOR_NSCREENS_FORWARD(j){ - - if(j) memcpy(&stuff[1], origArcs, narcs * sizeof(xArc)); - - if (isRoot) { - int x_off = panoramiXdataPtr[j].x; - int y_off = panoramiXdataPtr[j].y; - - if(x_off || y_off) { - xArc *arcs = (xArc *) &stuff[1]; - - for (i = narcs; i--; arcs++) { - arcs->x -= x_off; - arcs->y -= y_off; - } - } - } - stuff->drawable = draw->info[j].id; - stuff->gc = gc->info[j].id; - result = (* SavedProcVector[X_PolyArc])(client); - if(result != Success) break; - } - xfree(origArcs); - return (result); - } else - return (client->noClientException); -} - - -int PanoramiXFillPoly(ClientPtr client) -{ - int result, count, j; - PanoramiXRes *gc, *draw; - Bool isRoot; - DDXPointPtr locPts; - REQUEST(xFillPolyReq); - - REQUEST_AT_LEAST_SIZE(xFillPolyReq); - - result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable, - XRC_DRAWABLE, client, DixWriteAccess); - if (result != Success) - return (result == BadValue) ? BadDrawable : result; - - if(IS_SHARED_PIXMAP(draw)) - return (*SavedProcVector[X_FillPoly])(client); - - result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC, - client, DixReadAccess); - if (result != Success) - return (result == BadValue) ? BadGC : result; - - isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; - - count = bytes_to_int32((client->req_len << 2) - sizeof(xFillPolyReq)); - if (count > 0){ - locPts = xalloc(count * sizeof(DDXPointRec)); - memcpy((char *)locPts, (char *)&stuff[1], count * sizeof(DDXPointRec)); - FOR_NSCREENS_FORWARD(j){ - - if(j) memcpy(&stuff[1], locPts, count * sizeof(DDXPointRec)); - - if (isRoot) { - int x_off = panoramiXdataPtr[j].x; - int y_off = panoramiXdataPtr[j].y; - - if(x_off || y_off) { - DDXPointPtr pnts = (DDXPointPtr)&stuff[1]; - int i = (stuff->coordMode==CoordModePrevious) ? 1 : count; - - while(i--) { - pnts->x -= x_off; - pnts->y -= y_off; - pnts++; - } - } - } - - stuff->drawable = draw->info[j].id; - stuff->gc = gc->info[j].id; - result = (* SavedProcVector[X_FillPoly])(client); - if(result != Success) break; - } - xfree(locPts); - return (result); - } else - return (client->noClientException); -} - - -int PanoramiXPolyFillRectangle(ClientPtr client) -{ - int result, things, i, j; - PanoramiXRes *gc, *draw; - Bool isRoot; - xRectangle *origRects; - REQUEST(xPolyFillRectangleReq); - - REQUEST_AT_LEAST_SIZE(xPolyFillRectangleReq); - - result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable, - XRC_DRAWABLE, client, DixWriteAccess); - if (result != Success) - return (result == BadValue) ? BadDrawable : result; - - if(IS_SHARED_PIXMAP(draw)) - return (*SavedProcVector[X_PolyFillRectangle])(client); - - result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC, - client, DixReadAccess); - if (result != Success) - return (result == BadValue) ? BadGC : result; - - isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; - - things = (client->req_len << 2) - sizeof(xPolyFillRectangleReq); - if(things & 4) return BadLength; - things >>= 3; - if (things > 0){ - origRects = xalloc(things * sizeof(xRectangle)); - memcpy((char*)origRects,(char*)&stuff[1], things * sizeof(xRectangle)); - FOR_NSCREENS_FORWARD(j){ - - if(j) memcpy(&stuff[1], origRects, things * sizeof(xRectangle)); - - if (isRoot) { - int x_off = panoramiXdataPtr[j].x; - int y_off = panoramiXdataPtr[j].y; - - if(x_off || y_off) { - xRectangle *rects = (xRectangle *) &stuff[1]; - - for (i = things; i--; rects++) { - rects->x -= x_off; - rects->y -= y_off; - } - } - } - - stuff->drawable = draw->info[j].id; - stuff->gc = gc->info[j].id; - result = (* SavedProcVector[X_PolyFillRectangle])(client); - if(result != Success) break; - } - xfree(origRects); - return (result); - } else - return (client->noClientException); -} - - -int PanoramiXPolyFillArc(ClientPtr client) -{ - PanoramiXRes *gc, *draw; - Bool isRoot; - int result, narcs, i, j; - xArc *origArcs; - REQUEST(xPolyFillArcReq); - - REQUEST_AT_LEAST_SIZE(xPolyFillArcReq); - - result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable, - XRC_DRAWABLE, client, DixWriteAccess); - if (result != Success) - return (result == BadValue) ? BadDrawable : result; - - if(IS_SHARED_PIXMAP(draw)) - return (*SavedProcVector[X_PolyFillArc])(client); - - result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC, - client, DixReadAccess); - if (result != Success) - return (result == BadValue) ? BadGC : result; - - isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; - - narcs = (client->req_len << 2) - sizeof(xPolyFillArcReq); - if (narcs % sizeof(xArc)) return BadLength; - narcs /= sizeof(xArc); - if (narcs > 0) { - origArcs = xalloc(narcs * sizeof(xArc)); - memcpy((char *) origArcs, (char *)&stuff[1], narcs * sizeof(xArc)); - FOR_NSCREENS_FORWARD(j){ - - if(j) memcpy(&stuff[1], origArcs, narcs * sizeof(xArc)); - - if (isRoot) { - int x_off = panoramiXdataPtr[j].x; - int y_off = panoramiXdataPtr[j].y; - - if(x_off || y_off) { - xArc *arcs = (xArc *) &stuff[1]; - - for (i = narcs; i--; arcs++) { - arcs->x -= x_off; - arcs->y -= y_off; - } - } - } - - stuff->drawable = draw->info[j].id; - stuff->gc = gc->info[j].id; - result = (* SavedProcVector[X_PolyFillArc])(client); - if(result != Success) break; - } - xfree(origArcs); - return (result); - } else - return (client->noClientException); -} - - -int PanoramiXPutImage(ClientPtr client) -{ - PanoramiXRes *gc, *draw; - Bool isRoot; - int j, result, orig_x, orig_y; - REQUEST(xPutImageReq); - - REQUEST_AT_LEAST_SIZE(xPutImageReq); - - result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable, - XRC_DRAWABLE, client, DixWriteAccess); - if (result != Success) - return (result == BadValue) ? BadDrawable : result; - - if(IS_SHARED_PIXMAP(draw)) - return (*SavedProcVector[X_PutImage])(client); - - result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC, - client, DixReadAccess); - if (result != Success) - return (result == BadValue) ? BadGC : result; - - isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; - - orig_x = stuff->dstX; - orig_y = stuff->dstY; - FOR_NSCREENS_BACKWARD(j){ - if (isRoot) { - stuff->dstX = orig_x - panoramiXdataPtr[j].x; - stuff->dstY = orig_y - panoramiXdataPtr[j].y; - } - stuff->drawable = draw->info[j].id; - stuff->gc = gc->info[j].id; - result = (* SavedProcVector[X_PutImage])(client); - if(result != Success) break; - } - return (result); -} - - -int PanoramiXGetImage(ClientPtr client) -{ - DrawablePtr drawables[MAXSCREENS]; - DrawablePtr pDraw; - PanoramiXRes *draw; - xGetImageReply xgi; - Bool isRoot; - char *pBuf; - int i, x, y, w, h, format, rc; - Mask plane = 0, planemask; - int linesDone, nlines, linesPerBuf; - long widthBytesLine, length; - - REQUEST(xGetImageReq); - - REQUEST_SIZE_MATCH(xGetImageReq); - - if ((stuff->format != XYPixmap) && (stuff->format != ZPixmap)) { - client->errorValue = stuff->format; - return(BadValue); - } - - rc = dixLookupResourceByClass((pointer *)&draw, stuff->drawable, - XRC_DRAWABLE, client, DixWriteAccess); - if (rc != Success) - return (rc == BadValue) ? BadDrawable : rc; - - if(draw->type == XRT_PIXMAP) - return (*SavedProcVector[X_GetImage])(client); - - rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0, - DixReadAccess); - if (rc != Success) - return rc; - - if(!((WindowPtr)pDraw)->realized) - return(BadMatch); - - x = stuff->x; - y = stuff->y; - w = stuff->width; - h = stuff->height; - format = stuff->format; - planemask = stuff->planeMask; - - isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; - - if(isRoot) { - if( /* check for being onscreen */ - x < 0 || x + w > PanoramiXPixWidth || - y < 0 || y + h > PanoramiXPixHeight ) - return(BadMatch); - } else { - if( /* check for being onscreen */ - panoramiXdataPtr[0].x + pDraw->x + x < 0 || - panoramiXdataPtr[0].x + pDraw->x + x + w > PanoramiXPixWidth || - panoramiXdataPtr[0].y + pDraw->y + y < 0 || - panoramiXdataPtr[0].y + pDraw->y + y + h > PanoramiXPixHeight || - /* check for being inside of border */ - x < - wBorderWidth((WindowPtr)pDraw) || - x + w > wBorderWidth((WindowPtr)pDraw) + (int)pDraw->width || - y < -wBorderWidth((WindowPtr)pDraw) || - y + h > wBorderWidth ((WindowPtr)pDraw) + (int)pDraw->height) - return(BadMatch); - } - - drawables[0] = pDraw; - for(i = 1; i < PanoramiXNumScreens; i++) { - rc = dixLookupDrawable(drawables+i, draw->info[i].id, client, 0, - DixGetAttrAccess); - if (rc != Success) - return rc; - } - - xgi.visual = wVisual (((WindowPtr) pDraw)); - xgi.type = X_Reply; - xgi.sequenceNumber = client->sequence; - xgi.depth = pDraw->depth; - if(format == ZPixmap) { - widthBytesLine = PixmapBytePad(w, pDraw->depth); - length = widthBytesLine * h; - - - } else { - widthBytesLine = BitmapBytePad(w); - plane = ((Mask)1) << (pDraw->depth - 1); - /* only planes asked for */ - length = widthBytesLine * h * - Ones(planemask & (plane | (plane - 1))); - - } - - xgi.length = bytes_to_int32(length); - - if (widthBytesLine == 0 || h == 0) - linesPerBuf = 0; - else if (widthBytesLine >= XINERAMA_IMAGE_BUFSIZE) - linesPerBuf = 1; - else { - linesPerBuf = XINERAMA_IMAGE_BUFSIZE / widthBytesLine; - if (linesPerBuf > h) - linesPerBuf = h; - } - length = linesPerBuf * widthBytesLine; - if(!(pBuf = xalloc(length))) - return (BadAlloc); - - WriteReplyToClient(client, sizeof (xGetImageReply), &xgi); - - if (linesPerBuf == 0) { - /* nothing to do */ - } - else if (format == ZPixmap) { - linesDone = 0; - while (h - linesDone > 0) { - nlines = min(linesPerBuf, h - linesDone); - - if(pDraw->depth == 1) - bzero(pBuf, nlines * widthBytesLine); - - XineramaGetImageData(drawables, x, y + linesDone, w, nlines, - format, planemask, pBuf, widthBytesLine, isRoot); - - (void)WriteToClient(client, - (int)(nlines * widthBytesLine), - pBuf); - linesDone += nlines; - } - } else { /* XYPixmap */ - for (; plane; plane >>= 1) { - if (planemask & plane) { - linesDone = 0; - while (h - linesDone > 0) { - nlines = min(linesPerBuf, h - linesDone); - - bzero(pBuf, nlines * widthBytesLine); - - XineramaGetImageData(drawables, x, y + linesDone, w, - nlines, format, plane, pBuf, - widthBytesLine, isRoot); - - (void)WriteToClient(client, - (int)(nlines * widthBytesLine), - pBuf); - - linesDone += nlines; - } - } - } - } - xfree(pBuf); - return (client->noClientException); -} - - -/* The text stuff should be rewritten so that duplication happens - at the GlyphBlt level. That is, loading the font and getting - the glyphs should only happen once */ - -int -PanoramiXPolyText8(ClientPtr client) -{ - PanoramiXRes *gc, *draw; - Bool isRoot; - int result, j; - int orig_x, orig_y; - REQUEST(xPolyTextReq); - - REQUEST_AT_LEAST_SIZE(xPolyTextReq); - - result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable, - XRC_DRAWABLE, client, DixWriteAccess); - if (result != Success) - return (result == BadValue) ? BadDrawable : result; - - if(IS_SHARED_PIXMAP(draw)) - return (*SavedProcVector[X_PolyText8])(client); - - result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC, - client, DixReadAccess); - if (result != Success) - return (result == BadValue) ? BadGC : result; - - isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; - - orig_x = stuff->x; - orig_y = stuff->y; - FOR_NSCREENS_BACKWARD(j){ - stuff->drawable = draw->info[j].id; - stuff->gc = gc->info[j].id; - if (isRoot) { - stuff->x = orig_x - panoramiXdataPtr[j].x; - stuff->y = orig_y - panoramiXdataPtr[j].y; - } - result = (*SavedProcVector[X_PolyText8])(client); - if(result != Success) break; - } - return (result); -} - -int -PanoramiXPolyText16(ClientPtr client) -{ - PanoramiXRes *gc, *draw; - Bool isRoot; - int result, j; - int orig_x, orig_y; - REQUEST(xPolyTextReq); - - REQUEST_AT_LEAST_SIZE(xPolyTextReq); - - result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable, - XRC_DRAWABLE, client, DixWriteAccess); - if (result != Success) - return (result == BadValue) ? BadDrawable : result; - - if(IS_SHARED_PIXMAP(draw)) - return (*SavedProcVector[X_PolyText16])(client); - - result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC, - client, DixReadAccess); - if (result != Success) - return (result == BadValue) ? BadGC : result; - - isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; - - orig_x = stuff->x; - orig_y = stuff->y; - FOR_NSCREENS_BACKWARD(j){ - stuff->drawable = draw->info[j].id; - stuff->gc = gc->info[j].id; - if (isRoot) { - stuff->x = orig_x - panoramiXdataPtr[j].x; - stuff->y = orig_y - panoramiXdataPtr[j].y; - } - result = (*SavedProcVector[X_PolyText16])(client); - if(result != Success) break; - } - return (result); -} - - -int PanoramiXImageText8(ClientPtr client) -{ - int result, j; - PanoramiXRes *gc, *draw; - Bool isRoot; - int orig_x, orig_y; - REQUEST(xImageTextReq); - - REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars); - - result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable, - XRC_DRAWABLE, client, DixWriteAccess); - if (result != Success) - return (result == BadValue) ? BadDrawable : result; - - if(IS_SHARED_PIXMAP(draw)) - return (*SavedProcVector[X_ImageText8])(client); - - result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC, - client, DixReadAccess); - if (result != Success) - return (result == BadValue) ? BadGC : result; - - isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; - - orig_x = stuff->x; - orig_y = stuff->y; - FOR_NSCREENS_BACKWARD(j){ - stuff->drawable = draw->info[j].id; - stuff->gc = gc->info[j].id; - if (isRoot) { - stuff->x = orig_x - panoramiXdataPtr[j].x; - stuff->y = orig_y - panoramiXdataPtr[j].y; - } - result = (*SavedProcVector[X_ImageText8])(client); - if(result != Success) break; - } - return (result); -} - - -int PanoramiXImageText16(ClientPtr client) -{ - int result, j; - PanoramiXRes *gc, *draw; - Bool isRoot; - int orig_x, orig_y; - REQUEST(xImageTextReq); - - REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars << 1); - - result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable, - XRC_DRAWABLE, client, DixWriteAccess); - if (result != Success) - return (result == BadValue) ? BadDrawable : result; - - if(IS_SHARED_PIXMAP(draw)) - return (*SavedProcVector[X_ImageText16])(client); - - result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC, - client, DixReadAccess); - if (result != Success) - return (result == BadValue) ? BadGC : result; - - isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; - - orig_x = stuff->x; - orig_y = stuff->y; - FOR_NSCREENS_BACKWARD(j){ - stuff->drawable = draw->info[j].id; - stuff->gc = gc->info[j].id; - if (isRoot) { - stuff->x = orig_x - panoramiXdataPtr[j].x; - stuff->y = orig_y - panoramiXdataPtr[j].y; - } - result = (*SavedProcVector[X_ImageText16])(client); - if(result != Success) break; - } - return (result); -} - - - -int PanoramiXCreateColormap(ClientPtr client) -{ - PanoramiXRes *win, *newCmap; - int result, j, orig_visual; - REQUEST(xCreateColormapReq); - - REQUEST_SIZE_MATCH(xCreateColormapReq); - - result = dixLookupResourceByType((pointer *)&win, stuff->window, - XRT_WINDOW, client, DixReadAccess); - if (result != Success) - return (result == BadValue) ? BadWindow : result; - - if(!(newCmap = xalloc(sizeof(PanoramiXRes)))) - return BadAlloc; - - newCmap->type = XRT_COLORMAP; - newCmap->info[0].id = stuff->mid; - for(j = 1; j < PanoramiXNumScreens; j++) - newCmap->info[j].id = FakeClientID(client->index); - - orig_visual = stuff->visual; - FOR_NSCREENS_BACKWARD(j){ - stuff->mid = newCmap->info[j].id; - stuff->window = win->info[j].id; - stuff->visual = PanoramiXTranslateVisualID(j, orig_visual); - result = (* SavedProcVector[X_CreateColormap])(client); - if(result != Success) break; - } - - if (result == Success) - AddResource(newCmap->info[0].id, XRT_COLORMAP, newCmap); - else - xfree(newCmap); - - return (result); -} - - -int PanoramiXFreeColormap(ClientPtr client) -{ - PanoramiXRes *cmap; - int result, j; - REQUEST(xResourceReq); - - REQUEST_SIZE_MATCH(xResourceReq); - - client->errorValue = stuff->id; - - result = dixLookupResourceByType((pointer *)&cmap, stuff->id, XRT_COLORMAP, - client, DixDestroyAccess); - if (result != Success) - return (result == BadValue) ? BadColor : result; - - FOR_NSCREENS_BACKWARD(j) { - stuff->id = cmap->info[j].id; - result = (* SavedProcVector[X_FreeColormap])(client); - if(result != Success) break; - } - - /* Since ProcFreeColormap is using FreeResource, it will free - our resource for us on the last pass through the loop above */ - - return (result); -} - - -int -PanoramiXCopyColormapAndFree(ClientPtr client) -{ - PanoramiXRes *cmap, *newCmap; - int result, j; - REQUEST(xCopyColormapAndFreeReq); - - REQUEST_SIZE_MATCH(xCopyColormapAndFreeReq); - - client->errorValue = stuff->srcCmap; - - result = dixLookupResourceByType((pointer *)&cmap, stuff->srcCmap, - XRT_COLORMAP, client, - DixReadAccess | DixWriteAccess); - if (result != Success) - return (result == BadValue) ? BadColor : result; - - if(!(newCmap = xalloc(sizeof(PanoramiXRes)))) - return BadAlloc; - - newCmap->type = XRT_COLORMAP; - newCmap->info[0].id = stuff->mid; - for(j = 1; j < PanoramiXNumScreens; j++) - newCmap->info[j].id = FakeClientID(client->index); - - FOR_NSCREENS_BACKWARD(j){ - stuff->srcCmap = cmap->info[j].id; - stuff->mid = newCmap->info[j].id; - result = (* SavedProcVector[X_CopyColormapAndFree])(client); - if(result != Success) break; - } - - if (result == Success) - AddResource(newCmap->info[0].id, XRT_COLORMAP, newCmap); - else - xfree(newCmap); - - return (result); -} - - -int PanoramiXInstallColormap(ClientPtr client) -{ - REQUEST(xResourceReq); - int result, j; - PanoramiXRes *cmap; - - REQUEST_SIZE_MATCH(xResourceReq); - - client->errorValue = stuff->id; - - result = dixLookupResourceByType((pointer *)&cmap, stuff->id, XRT_COLORMAP, - client, DixReadAccess); - if (result != Success) - return (result == BadValue) ? BadColor : result; - - FOR_NSCREENS_BACKWARD(j){ - stuff->id = cmap->info[j].id; - result = (* SavedProcVector[X_InstallColormap])(client); - if(result != Success) break; - } - return (result); -} - - -int PanoramiXUninstallColormap(ClientPtr client) -{ - REQUEST(xResourceReq); - int result, j; - PanoramiXRes *cmap; - - REQUEST_SIZE_MATCH(xResourceReq); - - client->errorValue = stuff->id; - - result = dixLookupResourceByType((pointer *)&cmap, stuff->id, XRT_COLORMAP, - client, DixReadAccess); - if (result != Success) - return (result == BadValue) ? BadColor : result; - - FOR_NSCREENS_BACKWARD(j) { - stuff->id = cmap->info[j].id; - result = (* SavedProcVector[X_UninstallColormap])(client); - if(result != Success) break; - } - return (result); -} - - -int PanoramiXAllocColor(ClientPtr client) -{ - int result, j; - PanoramiXRes *cmap; - REQUEST(xAllocColorReq); - - REQUEST_SIZE_MATCH(xAllocColorReq); - - client->errorValue = stuff->cmap; - - result = dixLookupResourceByType((pointer *)&cmap, stuff->cmap, - XRT_COLORMAP, client, DixWriteAccess); - if (result != Success) - return (result == BadValue) ? BadColor : result; - - FOR_NSCREENS_BACKWARD(j){ - stuff->cmap = cmap->info[j].id; - result = (* SavedProcVector[X_AllocColor])(client); - if(result != Success) break; - } - return (result); -} - - -int PanoramiXAllocNamedColor(ClientPtr client) -{ - int result, j; - PanoramiXRes *cmap; - REQUEST(xAllocNamedColorReq); - - REQUEST_FIXED_SIZE(xAllocNamedColorReq, stuff->nbytes); - - client->errorValue = stuff->cmap; - - result = dixLookupResourceByType((pointer *)&cmap, stuff->cmap, - XRT_COLORMAP, client, DixWriteAccess); - if (result != Success) - return (result == BadValue) ? BadColor : result; - - FOR_NSCREENS_BACKWARD(j){ - stuff->cmap = cmap->info[j].id; - result = (* SavedProcVector[X_AllocNamedColor])(client); - if(result != Success) break; - } - return (result); -} - - -int PanoramiXAllocColorCells(ClientPtr client) -{ - int result, j; - PanoramiXRes *cmap; - REQUEST(xAllocColorCellsReq); - - REQUEST_SIZE_MATCH(xAllocColorCellsReq); - - client->errorValue = stuff->cmap; - - result = dixLookupResourceByType((pointer *)&cmap, stuff->cmap, - XRT_COLORMAP, client, DixWriteAccess); - if (result != Success) - return (result == BadValue) ? BadColor : result; - - FOR_NSCREENS_BACKWARD(j){ - stuff->cmap = cmap->info[j].id; - result = (* SavedProcVector[X_AllocColorCells])(client); - if(result != Success) break; - } - return (result); -} - - -int PanoramiXAllocColorPlanes(ClientPtr client) -{ - int result, j; - PanoramiXRes *cmap; - REQUEST(xAllocColorPlanesReq); - - REQUEST_SIZE_MATCH(xAllocColorPlanesReq); - - client->errorValue = stuff->cmap; - - result = dixLookupResourceByType((pointer *)&cmap, stuff->cmap, - XRT_COLORMAP, client, DixWriteAccess); - if (result != Success) - return (result == BadValue) ? BadColor : result; - - FOR_NSCREENS_BACKWARD(j){ - stuff->cmap = cmap->info[j].id; - result = (* SavedProcVector[X_AllocColorPlanes])(client); - if(result != Success) break; - } - return (result); -} - - - -int PanoramiXFreeColors(ClientPtr client) -{ - int result, j; - PanoramiXRes *cmap; - REQUEST(xFreeColorsReq); - - REQUEST_AT_LEAST_SIZE(xFreeColorsReq); - - client->errorValue = stuff->cmap; - - result = dixLookupResourceByType((pointer *)&cmap, stuff->cmap, - XRT_COLORMAP, client, DixWriteAccess); - if (result != Success) - return (result == BadValue) ? BadColor : result; - - FOR_NSCREENS_BACKWARD(j) { - stuff->cmap = cmap->info[j].id; - result = (* SavedProcVector[X_FreeColors])(client); - } - return (result); -} - - -int PanoramiXStoreColors(ClientPtr client) -{ - int result, j; - PanoramiXRes *cmap; - REQUEST(xStoreColorsReq); - - REQUEST_AT_LEAST_SIZE(xStoreColorsReq); - - client->errorValue = stuff->cmap; - - result = dixLookupResourceByType((pointer *)&cmap, stuff->cmap, - XRT_COLORMAP, client, DixWriteAccess); - if (result != Success) - return (result == BadValue) ? BadColor : result; - - FOR_NSCREENS_BACKWARD(j){ - stuff->cmap = cmap->info[j].id; - result = (* SavedProcVector[X_StoreColors])(client); - if(result != Success) break; - } - return (result); -} - - -int PanoramiXStoreNamedColor(ClientPtr client) -{ - int result, j; - PanoramiXRes *cmap; - REQUEST(xStoreNamedColorReq); - - REQUEST_FIXED_SIZE(xStoreNamedColorReq, stuff->nbytes); - - client->errorValue = stuff->cmap; - - result = dixLookupResourceByType((pointer *)&cmap, stuff->cmap, - XRT_COLORMAP, client, DixWriteAccess); - if (result != Success) - return (result == BadValue) ? BadColor : result; - - FOR_NSCREENS_BACKWARD(j){ - stuff->cmap = cmap->info[j].id; - result = (* SavedProcVector[X_StoreNamedColor])(client); - if(result != Success) break; - } - return (result); -} +/***************************************************************** +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. +******************************************************************/ + +/* Massively rewritten by Mark Vojkovich */ + + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include +#include +#include "windowstr.h" +#include "dixfontstr.h" +#include "gcstruct.h" +#include "colormapst.h" +#include "scrnintstr.h" +#include "opaque.h" +#include "inputstr.h" +#include "migc.h" +#include "misc.h" +#include "dixstruct.h" +#include "panoramiX.h" +#include "panoramiXsrv.h" +#include "resource.h" +#include "panoramiXh.h" + +#define XINERAMA_IMAGE_BUFSIZE (256*1024) +#define INPUTONLY_LEGAL_MASK (CWWinGravity | CWEventMask | \ + CWDontPropagate | CWOverrideRedirect | CWCursor ) + +int PanoramiXCreateWindow(ClientPtr client) +{ + PanoramiXRes *parent, *newWin; + PanoramiXRes *backPix = NULL; + PanoramiXRes *bordPix = NULL; + PanoramiXRes *cmap = NULL; + REQUEST(xCreateWindowReq); + int pback_offset = 0, pbord_offset = 0, cmap_offset = 0; + int result, len, j; + int orig_x, orig_y; + XID orig_visual, tmp; + Bool parentIsRoot; + + REQUEST_AT_LEAST_SIZE(xCreateWindowReq); + + len = client->req_len - bytes_to_int32(sizeof(xCreateWindowReq)); + if (Ones(stuff->mask) != len) + return BadLength; + + result = dixLookupResourceByType((pointer *)&parent, stuff->parent, + XRT_WINDOW, client, DixWriteAccess); + if (result != Success) + return (result == BadValue) ? BadWindow : result; + + if(stuff->class == CopyFromParent) + stuff->class = parent->u.win.class; + + if((stuff->class == InputOnly) && (stuff->mask & (~INPUTONLY_LEGAL_MASK))) + return BadMatch; + + if ((Mask)stuff->mask & CWBackPixmap) { + pback_offset = Ones((Mask)stuff->mask & (CWBackPixmap - 1)); + tmp = *((CARD32 *) &stuff[1] + pback_offset); + if ((tmp != None) && (tmp != ParentRelative)) { + result = dixLookupResourceByType((pointer *)&backPix, tmp, + XRT_PIXMAP, client, DixReadAccess); + if (result != Success) + return (result == BadValue) ? BadPixmap : result; + } + } + if ((Mask)stuff->mask & CWBorderPixmap) { + pbord_offset = Ones((Mask)stuff->mask & (CWBorderPixmap - 1)); + tmp = *((CARD32 *) &stuff[1] + pbord_offset); + if (tmp != CopyFromParent) { + result = dixLookupResourceByType((pointer *)&bordPix, tmp, + XRT_PIXMAP, client, DixReadAccess); + if (result != Success) + return (result == BadValue) ? BadPixmap : result; + } + } + if ((Mask)stuff->mask & CWColormap) { + cmap_offset = Ones((Mask)stuff->mask & (CWColormap - 1)); + tmp = *((CARD32 *) &stuff[1] + cmap_offset); + if ((tmp != CopyFromParent) && (tmp != None)) { + result = dixLookupResourceByType((pointer *)&cmap, tmp, + XRT_COLORMAP, client, DixReadAccess); + if (result != Success) + return (result == BadValue) ? BadColor : result; + } + } + + if(!(newWin = malloc(sizeof(PanoramiXRes)))) + return BadAlloc; + + newWin->type = XRT_WINDOW; + newWin->u.win.visibility = VisibilityNotViewable; + newWin->u.win.class = stuff->class; + newWin->u.win.root = FALSE; + newWin->info[0].id = stuff->wid; + for(j = 1; j < PanoramiXNumScreens; j++) + newWin->info[j].id = FakeClientID(client->index); + + if (stuff->class == InputOnly) + stuff->visual = CopyFromParent; + orig_visual = stuff->visual; + orig_x = stuff->x; + orig_y = stuff->y; + parentIsRoot = (stuff->parent == WindowTable[0]->drawable.id) || + (stuff->parent == savedScreenInfo[0].wid); + FOR_NSCREENS_BACKWARD(j) { + stuff->wid = newWin->info[j].id; + stuff->parent = parent->info[j].id; + if (parentIsRoot) { + stuff->x = orig_x - panoramiXdataPtr[j].x; + stuff->y = orig_y - panoramiXdataPtr[j].y; + } + if (backPix) + *((CARD32 *) &stuff[1] + pback_offset) = backPix->info[j].id; + if (bordPix) + *((CARD32 *) &stuff[1] + pbord_offset) = bordPix->info[j].id; + if (cmap) + *((CARD32 *) &stuff[1] + cmap_offset) = cmap->info[j].id; + if ( orig_visual != CopyFromParent ) + stuff->visual = PanoramiXTranslateVisualID(j, orig_visual); + result = (*SavedProcVector[X_CreateWindow])(client); + if(result != Success) break; + } + + if (result == Success) + AddResource(newWin->info[0].id, XRT_WINDOW, newWin); + else + free(newWin); + + return (result); +} + + +int PanoramiXChangeWindowAttributes(ClientPtr client) +{ + PanoramiXRes *win; + PanoramiXRes *backPix = NULL; + PanoramiXRes *bordPix = NULL; + PanoramiXRes *cmap = NULL; + REQUEST(xChangeWindowAttributesReq); + int pback_offset = 0, pbord_offset = 0, cmap_offset = 0; + int result, len, j; + XID tmp; + + REQUEST_AT_LEAST_SIZE(xChangeWindowAttributesReq); + + len = client->req_len - bytes_to_int32(sizeof(xChangeWindowAttributesReq)); + if (Ones(stuff->valueMask) != len) + return BadLength; + + result = dixLookupResourceByType((pointer *)&win, stuff->window, + XRT_WINDOW, client, DixWriteAccess); + if (result != Success) + return (result == BadValue) ? BadWindow : result; + + if((win->u.win.class == InputOnly) && + (stuff->valueMask & (~INPUTONLY_LEGAL_MASK))) + return BadMatch; + + if ((Mask)stuff->valueMask & CWBackPixmap) { + pback_offset = Ones((Mask)stuff->valueMask & (CWBackPixmap - 1)); + tmp = *((CARD32 *) &stuff[1] + pback_offset); + if ((tmp != None) && (tmp != ParentRelative)) { + result = dixLookupResourceByType((pointer *)&backPix, tmp, + XRT_PIXMAP, client, DixReadAccess); + if (result != Success) + return (result == BadValue) ? BadPixmap : result; + } + } + if ((Mask)stuff->valueMask & CWBorderPixmap) { + pbord_offset = Ones((Mask)stuff->valueMask & (CWBorderPixmap - 1)); + tmp = *((CARD32 *) &stuff[1] + pbord_offset); + if (tmp != CopyFromParent) { + result = dixLookupResourceByType((pointer *)&bordPix, tmp, + XRT_PIXMAP, client, DixReadAccess); + if (result != Success) + return (result == BadValue) ? BadPixmap : result; + } + } + if ((Mask)stuff->valueMask & CWColormap) { + cmap_offset = Ones((Mask)stuff->valueMask & (CWColormap - 1)); + tmp = *((CARD32 *) &stuff[1] + cmap_offset); + if ((tmp != CopyFromParent) && (tmp != None)) { + result = dixLookupResourceByType((pointer *)&cmap, tmp, + XRT_COLORMAP, client, DixReadAccess); + if (result != Success) + return (result == BadValue) ? BadColor : result; + } + } + + FOR_NSCREENS_BACKWARD(j) { + stuff->window = win->info[j].id; + if (backPix) + *((CARD32 *) &stuff[1] + pback_offset) = backPix->info[j].id; + if (bordPix) + *((CARD32 *) &stuff[1] + pbord_offset) = bordPix->info[j].id; + if (cmap) + *((CARD32 *) &stuff[1] + cmap_offset) = cmap->info[j].id; + result = (*SavedProcVector[X_ChangeWindowAttributes])(client); + } + + return (result); +} + + +int PanoramiXDestroyWindow(ClientPtr client) +{ + PanoramiXRes *win; + int result, j; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + + result = dixLookupResourceByType((pointer *)&win, stuff->id, XRT_WINDOW, + client, DixDestroyAccess); + if (result != Success) + return (result == BadValue) ? BadWindow : result; + + FOR_NSCREENS_BACKWARD(j) { + stuff->id = win->info[j].id; + result = (*SavedProcVector[X_DestroyWindow])(client); + if(result != Success) break; + } + + /* Since ProcDestroyWindow is using FreeResource, it will free + our resource for us on the last pass through the loop above */ + + return (result); +} + + +int PanoramiXDestroySubwindows(ClientPtr client) +{ + PanoramiXRes *win; + int result, j; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + + result = dixLookupResourceByType((pointer *)&win, stuff->id, XRT_WINDOW, + client, DixDestroyAccess); + if (result != Success) + return (result == BadValue) ? BadWindow : result; + + FOR_NSCREENS_BACKWARD(j) { + stuff->id = win->info[j].id; + result = (*SavedProcVector[X_DestroySubwindows])(client); + if(result != Success) break; + } + + /* DestroySubwindows is using FreeResource which will free + our resources for us on the last pass through the loop above */ + + return (result); +} + + +int PanoramiXChangeSaveSet(ClientPtr client) +{ + PanoramiXRes *win; + int result, j; + REQUEST(xChangeSaveSetReq); + + REQUEST_SIZE_MATCH(xChangeSaveSetReq); + + result = dixLookupResourceByType((pointer *)&win, stuff->window, + XRT_WINDOW, client, DixReadAccess); + if (result != Success) + return (result == BadValue) ? BadWindow : result; + + FOR_NSCREENS_BACKWARD(j) { + stuff->window = win->info[j].id; + result = (*SavedProcVector[X_ChangeSaveSet])(client); + if(result != Success) break; + } + + return (result); +} + + +int PanoramiXReparentWindow(ClientPtr client) +{ + PanoramiXRes *win, *parent; + int result, j; + int x, y; + Bool parentIsRoot; + REQUEST(xReparentWindowReq); + + REQUEST_SIZE_MATCH(xReparentWindowReq); + + result = dixLookupResourceByType((pointer *)&win, stuff->window, + XRT_WINDOW, client, DixWriteAccess); + if (result != Success) + return (result == BadValue) ? BadWindow : result; + + result = dixLookupResourceByType((pointer *)&parent, stuff->parent, + XRT_WINDOW, client, DixWriteAccess); + if (result != Success) + return (result == BadValue) ? BadWindow : result; + + x = stuff->x; + y = stuff->y; + parentIsRoot = (stuff->parent == WindowTable[0]->drawable.id) || + (stuff->parent == savedScreenInfo[0].wid); + FOR_NSCREENS_BACKWARD(j) { + stuff->window = win->info[j].id; + stuff->parent = parent->info[j].id; + if(parentIsRoot) { + stuff->x = x - panoramiXdataPtr[j].x; + stuff->y = y - panoramiXdataPtr[j].y; + } + result = (*SavedProcVector[X_ReparentWindow])(client); + if(result != Success) break; + } + + return (result); +} + + +int PanoramiXMapWindow(ClientPtr client) +{ + PanoramiXRes *win; + int result, j; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + + result = dixLookupResourceByType((pointer *)&win, stuff->id, + XRT_WINDOW, client, DixReadAccess); + if (result != Success) + return (result == BadValue) ? BadWindow : result; + + FOR_NSCREENS_FORWARD(j) { + stuff->id = win->info[j].id; + result = (*SavedProcVector[X_MapWindow])(client); + if(result != Success) break; + } + + return (result); +} + + +int PanoramiXMapSubwindows(ClientPtr client) +{ + PanoramiXRes *win; + int result, j; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + + result = dixLookupResourceByType((pointer *)&win, stuff->id, + XRT_WINDOW, client, DixReadAccess); + if (result != Success) + return (result == BadValue) ? BadWindow : result; + + FOR_NSCREENS_FORWARD(j) { + stuff->id = win->info[j].id; + result = (*SavedProcVector[X_MapSubwindows])(client); + if(result != Success) break; + } + + return (result); +} + + +int PanoramiXUnmapWindow(ClientPtr client) +{ + PanoramiXRes *win; + int result, j; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + + result = dixLookupResourceByType((pointer *)&win, stuff->id, + XRT_WINDOW, client, DixReadAccess); + if (result != Success) + return (result == BadValue) ? BadWindow : result; + + FOR_NSCREENS_FORWARD(j) { + stuff->id = win->info[j].id; + result = (*SavedProcVector[X_UnmapWindow])(client); + if(result != Success) break; + } + + return (result); +} + + +int PanoramiXUnmapSubwindows(ClientPtr client) +{ + PanoramiXRes *win; + int result, j; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + + result = dixLookupResourceByType((pointer *)&win, stuff->id, + XRT_WINDOW, client, DixReadAccess); + if (result != Success) + return (result == BadValue) ? BadWindow : result; + + FOR_NSCREENS_FORWARD(j) { + stuff->id = win->info[j].id; + result = (*SavedProcVector[X_UnmapSubwindows])(client); + if(result != Success) break; + } + + return (result); +} + + +int PanoramiXConfigureWindow(ClientPtr client) +{ + PanoramiXRes *win; + PanoramiXRes *sib = NULL; + WindowPtr pWin; + int result, j, len, sib_offset = 0, x = 0, y = 0; + int x_offset = -1; + int y_offset = -1; + REQUEST(xConfigureWindowReq); + + REQUEST_AT_LEAST_SIZE(xConfigureWindowReq); + + len = client->req_len - bytes_to_int32(sizeof(xConfigureWindowReq)); + if (Ones(stuff->mask) != len) + return BadLength; + + /* because we need the parent */ + result = dixLookupResourceByType((pointer *)&pWin, stuff->window, + RT_WINDOW, client, DixWriteAccess); + if (result != Success) + return (result == BadValue) ? BadWindow : result; + + result = dixLookupResourceByType((pointer *)&win, stuff->window, + XRT_WINDOW, client, DixWriteAccess); + if (result != Success) + return (result == BadValue) ? BadWindow : result; + + if ((Mask)stuff->mask & CWSibling) { + XID tmp; + sib_offset = Ones((Mask)stuff->mask & (CWSibling - 1)); + if ((tmp = *((CARD32 *) &stuff[1] + sib_offset))) { + result = dixLookupResourceByType((pointer *)&sib, tmp, XRT_WINDOW, + client, DixReadAccess); + if (result != Success) + return (result == BadValue) ? BadWindow : result; + } + } + + if(pWin->parent && ((pWin->parent == WindowTable[0]) || + (pWin->parent->drawable.id == savedScreenInfo[0].wid))) + { + if ((Mask)stuff->mask & CWX) { + x_offset = 0; + x = *((CARD32 *)&stuff[1]); + } + if ((Mask)stuff->mask & CWY) { + y_offset = (x_offset == -1) ? 0 : 1; + y = *((CARD32 *) &stuff[1] + y_offset); + } + } + + /* have to go forward or you get expose events before + ConfigureNotify events */ + FOR_NSCREENS_FORWARD(j) { + stuff->window = win->info[j].id; + if(sib) + *((CARD32 *) &stuff[1] + sib_offset) = sib->info[j].id; + if(x_offset >= 0) + *((CARD32 *) &stuff[1] + x_offset) = x - panoramiXdataPtr[j].x; + if(y_offset >= 0) + *((CARD32 *) &stuff[1] + y_offset) = y - panoramiXdataPtr[j].y; + result = (*SavedProcVector[X_ConfigureWindow])(client); + if(result != Success) break; + } + + return (result); +} + + +int PanoramiXCirculateWindow(ClientPtr client) +{ + PanoramiXRes *win; + int result, j; + REQUEST(xCirculateWindowReq); + + REQUEST_SIZE_MATCH(xCirculateWindowReq); + + result = dixLookupResourceByType((pointer *)&win, stuff->window, + XRT_WINDOW, client, DixWriteAccess); + if (result != Success) + return (result == BadValue) ? BadWindow : result; + + FOR_NSCREENS_FORWARD(j) { + stuff->window = win->info[j].id; + result = (*SavedProcVector[X_CirculateWindow])(client); + if(result != Success) break; + } + + return (result); +} + + +int PanoramiXGetGeometry(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 = WindowTable[0]->drawable.id; + rep.depth = pDraw->depth; + rep.width = pDraw->width; + rep.height = pDraw->height; + rep.x = rep.y = rep.borderWidth = 0; + + if (stuff->id == rep.root) { + xWindowRoot *root = (xWindowRoot *) + (ConnectionInfo + connBlockScreenStart); + + rep.width = root->pixWidth; + rep.height = root->pixHeight; + } else + if ((pDraw->type == UNDRAWABLE_WINDOW) || (pDraw->type == DRAWABLE_WINDOW)) + { + WindowPtr pWin = (WindowPtr)pDraw; + rep.x = pWin->origin.x - wBorderWidth (pWin); + rep.y = pWin->origin.y - wBorderWidth (pWin); + if((pWin->parent == WindowTable[0]) || + (pWin->parent->drawable.id == savedScreenInfo[0].wid)) + { + rep.x += panoramiXdataPtr[0].x; + rep.y += panoramiXdataPtr[0].y; + } + rep.borderWidth = pWin->borderWidth; + } + + WriteReplyToClient(client, sizeof(xGetGeometryReply), &rep); + return Success; +} + +int PanoramiXTranslateCoords(ClientPtr client) +{ + INT16 x, y; + REQUEST(xTranslateCoordsReq); + int rc; + WindowPtr pWin, pDst; + xTranslateCoordsReply rep; + + REQUEST_SIZE_MATCH(xTranslateCoordsReq); + rc = dixLookupWindow(&pWin, stuff->srcWid, client, DixReadAccess); + if (rc != Success) + return rc; + rc = dixLookupWindow(&pDst, stuff->dstWid, client, DixReadAccess); + if (rc != Success) + return rc; + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.sameScreen = xTrue; + rep.child = None; + + if((pWin == WindowTable[0]) || + (pWin->drawable.id == savedScreenInfo[0].wid)) + { + x = stuff->srcX - panoramiXdataPtr[0].x; + y = stuff->srcY - panoramiXdataPtr[0].y; + } else { + 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) || + POINT_IN_REGION(pWin->drawable.pScreen, + wBoundingShape(pWin), + x - pWin->drawable.x, + y - pWin->drawable.y, &box)) + ) + { + rep.child = pWin->drawable.id; + pWin = (WindowPtr) NULL; + } + else + pWin = pWin->nextSib; + } + rep.dstX = x - pDst->drawable.x; + rep.dstY = y - pDst->drawable.y; + if((pDst == WindowTable[0]) || + (pDst->drawable.id == savedScreenInfo[0].wid)) + { + rep.dstX += panoramiXdataPtr[0].x; + rep.dstY += panoramiXdataPtr[0].y; + } + + WriteReplyToClient(client, sizeof(xTranslateCoordsReply), &rep); + return Success; +} + +int PanoramiXCreatePixmap(ClientPtr client) +{ + PanoramiXRes *refDraw, *newPix; + int result, j; + REQUEST(xCreatePixmapReq); + + REQUEST_SIZE_MATCH(xCreatePixmapReq); + client->errorValue = stuff->pid; + + result = dixLookupResourceByClass((pointer *)&refDraw, stuff->drawable, + XRC_DRAWABLE, client, DixReadAccess); + if (result != Success) + return (result == BadValue) ? BadDrawable : result; + + if(!(newPix = malloc(sizeof(PanoramiXRes)))) + return BadAlloc; + + newPix->type = XRT_PIXMAP; + newPix->u.pix.shared = FALSE; + newPix->info[0].id = stuff->pid; + for(j = 1; j < PanoramiXNumScreens; j++) + newPix->info[j].id = FakeClientID(client->index); + + FOR_NSCREENS_BACKWARD(j) { + stuff->pid = newPix->info[j].id; + stuff->drawable = refDraw->info[j].id; + result = (*SavedProcVector[X_CreatePixmap])(client); + if(result != Success) break; + } + + if (result == Success) + AddResource(newPix->info[0].id, XRT_PIXMAP, newPix); + else + free(newPix); + + return (result); +} + + +int PanoramiXFreePixmap(ClientPtr client) +{ + PanoramiXRes *pix; + int result, j; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + + client->errorValue = stuff->id; + + result = dixLookupResourceByType((pointer *)&pix, stuff->id, XRT_PIXMAP, + client, DixDestroyAccess); + if (result != Success) + return (result == BadValue) ? BadPixmap : result; + + FOR_NSCREENS_BACKWARD(j) { + stuff->id = pix->info[j].id; + result = (*SavedProcVector[X_FreePixmap])(client); + if(result != Success) break; + } + + /* Since ProcFreePixmap is using FreeResource, it will free + our resource for us on the last pass through the loop above */ + + return (result); +} + + +int PanoramiXCreateGC(ClientPtr client) +{ + PanoramiXRes *refDraw; + PanoramiXRes *newGC; + PanoramiXRes *stip = NULL; + PanoramiXRes *tile = NULL; + PanoramiXRes *clip = NULL; + REQUEST(xCreateGCReq); + int tile_offset = 0, stip_offset = 0, clip_offset = 0; + int result, len, j; + XID tmp; + + REQUEST_AT_LEAST_SIZE(xCreateGCReq); + + client->errorValue = stuff->gc; + len = client->req_len - bytes_to_int32(sizeof(xCreateGCReq)); + if (Ones(stuff->mask) != len) + return BadLength; + + result = dixLookupResourceByClass((pointer *)&refDraw, stuff->drawable, + XRC_DRAWABLE, client, DixReadAccess); + if (result != Success) + return (result == BadValue) ? BadDrawable : result; + + if ((Mask)stuff->mask & GCTile) { + tile_offset = Ones((Mask)stuff->mask & (GCTile - 1)); + if ((tmp = *((CARD32 *) &stuff[1] + tile_offset))) { + result = dixLookupResourceByType((pointer *)&tile, tmp, XRT_PIXMAP, + client, DixReadAccess); + if (result != Success) + return (result == BadValue) ? BadPixmap : result; + } + } + if ((Mask)stuff->mask & GCStipple) { + stip_offset = Ones((Mask)stuff->mask & (GCStipple - 1)); + if ((tmp = *((CARD32 *) &stuff[1] + stip_offset))) { + result = dixLookupResourceByType((pointer *)&stip, tmp, XRT_PIXMAP, + client, DixReadAccess); + if (result != Success) + return (result == BadValue) ? BadPixmap : result; + } + } + if ((Mask)stuff->mask & GCClipMask) { + clip_offset = Ones((Mask)stuff->mask & (GCClipMask - 1)); + if ((tmp = *((CARD32 *) &stuff[1] + clip_offset))) { + result = dixLookupResourceByType((pointer *)&clip, tmp, XRT_PIXMAP, + client, DixReadAccess); + if (result != Success) + return (result == BadValue) ? BadPixmap : result; + } + } + + if(!(newGC = malloc(sizeof(PanoramiXRes)))) + return BadAlloc; + + newGC->type = XRT_GC; + newGC->info[0].id = stuff->gc; + for(j = 1; j < PanoramiXNumScreens; j++) + newGC->info[j].id = FakeClientID(client->index); + + FOR_NSCREENS_BACKWARD(j) { + stuff->gc = newGC->info[j].id; + stuff->drawable = refDraw->info[j].id; + if (tile) + *((CARD32 *) &stuff[1] + tile_offset) = tile->info[j].id; + if (stip) + *((CARD32 *) &stuff[1] + stip_offset) = stip->info[j].id; + if (clip) + *((CARD32 *) &stuff[1] + clip_offset) = clip->info[j].id; + result = (*SavedProcVector[X_CreateGC])(client); + if(result != Success) break; + } + + if (result == Success) + AddResource(newGC->info[0].id, XRT_GC, newGC); + else + free(newGC); + + return (result); +} + +int PanoramiXChangeGC(ClientPtr client) +{ + PanoramiXRes *gc; + PanoramiXRes *stip = NULL; + PanoramiXRes *tile = NULL; + PanoramiXRes *clip = NULL; + REQUEST(xChangeGCReq); + int tile_offset = 0, stip_offset = 0, clip_offset = 0; + int result, len, j; + XID tmp; + + REQUEST_AT_LEAST_SIZE(xChangeGCReq); + + len = client->req_len - bytes_to_int32(sizeof(xChangeGCReq)); + if (Ones(stuff->mask) != len) + return BadLength; + + result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC, + client, DixReadAccess); + if (result != Success) + return (result == BadValue) ? BadGC : result; + + if ((Mask)stuff->mask & GCTile) { + tile_offset = Ones((Mask)stuff->mask & (GCTile - 1)); + if ((tmp = *((CARD32 *) &stuff[1] + tile_offset))) { + result = dixLookupResourceByType((pointer *)&tile, tmp, XRT_PIXMAP, + client, DixReadAccess); + if (result != Success) + return (result == BadValue) ? BadPixmap : result; + } + } + if ((Mask)stuff->mask & GCStipple) { + stip_offset = Ones((Mask)stuff->mask & (GCStipple - 1)); + if ((tmp = *((CARD32 *) &stuff[1] + stip_offset))) { + result = dixLookupResourceByType((pointer *)&stip, tmp, XRT_PIXMAP, + client, DixReadAccess); + if (result != Success) + return (result == BadValue) ? BadPixmap : result; + } + } + if ((Mask)stuff->mask & GCClipMask) { + clip_offset = Ones((Mask)stuff->mask & (GCClipMask - 1)); + if ((tmp = *((CARD32 *) &stuff[1] + clip_offset))) { + result = dixLookupResourceByType((pointer *)&clip, tmp, XRT_PIXMAP, + client, DixReadAccess); + if (result != Success) + return (result == BadValue) ? BadPixmap : result; + } + } + + + FOR_NSCREENS_BACKWARD(j) { + stuff->gc = gc->info[j].id; + if (tile) + *((CARD32 *) &stuff[1] + tile_offset) = tile->info[j].id; + if (stip) + *((CARD32 *) &stuff[1] + stip_offset) = stip->info[j].id; + if (clip) + *((CARD32 *) &stuff[1] + clip_offset) = clip->info[j].id; + result = (*SavedProcVector[X_ChangeGC])(client); + if(result != Success) break; + } + + return (result); +} + + +int PanoramiXCopyGC(ClientPtr client) +{ + PanoramiXRes *srcGC, *dstGC; + int result, j; + REQUEST(xCopyGCReq); + + REQUEST_SIZE_MATCH(xCopyGCReq); + + result = dixLookupResourceByType((pointer *)&srcGC, stuff->srcGC, XRT_GC, + client, DixReadAccess); + if (result != Success) + return (result == BadValue) ? BadGC : result; + + result = dixLookupResourceByType((pointer *)&dstGC, stuff->dstGC, XRT_GC, + client, DixWriteAccess); + if (result != Success) + return (result == BadValue) ? BadGC : result; + + FOR_NSCREENS(j) { + stuff->srcGC = srcGC->info[j].id; + stuff->dstGC = dstGC->info[j].id; + result = (*SavedProcVector[X_CopyGC])(client); + if(result != Success) break; + } + + return (result); +} + + +int PanoramiXSetDashes(ClientPtr client) +{ + PanoramiXRes *gc; + int result, j; + REQUEST(xSetDashesReq); + + REQUEST_FIXED_SIZE(xSetDashesReq, stuff->nDashes); + + result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC, + client, DixWriteAccess); + if (result != Success) + return (result == BadValue) ? BadGC : result; + + FOR_NSCREENS_BACKWARD(j) { + stuff->gc = gc->info[j].id; + result = (*SavedProcVector[X_SetDashes])(client); + if(result != Success) break; + } + + return (result); +} + + +int PanoramiXSetClipRectangles(ClientPtr client) +{ + PanoramiXRes *gc; + int result, j; + REQUEST(xSetClipRectanglesReq); + + REQUEST_AT_LEAST_SIZE(xSetClipRectanglesReq); + + result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC, + client, DixWriteAccess); + if (result != Success) + return (result == BadValue) ? BadGC : result; + + FOR_NSCREENS_BACKWARD(j) { + stuff->gc = gc->info[j].id; + result = (*SavedProcVector[X_SetClipRectangles])(client); + if(result != Success) break; + } + + return (result); +} + + +int PanoramiXFreeGC(ClientPtr client) +{ + PanoramiXRes *gc; + int result, j; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + + result = dixLookupResourceByType((pointer *)&gc, stuff->id, XRT_GC, + client, DixDestroyAccess); + if (result != Success) + return (result == BadValue) ? BadGC : result; + + FOR_NSCREENS_BACKWARD(j) { + stuff->id = gc->info[j].id; + result = (*SavedProcVector[X_FreeGC])(client); + if(result != Success) break; + } + + /* Since ProcFreeGC is using FreeResource, it will free + our resource for us on the last pass through the loop above */ + + return (result); +} + + +int PanoramiXClearToBackground(ClientPtr client) +{ + PanoramiXRes *win; + int result, j, x, y; + Bool isRoot; + REQUEST(xClearAreaReq); + + REQUEST_SIZE_MATCH(xClearAreaReq); + + result = dixLookupResourceByType((pointer *)&win, stuff->window, + XRT_WINDOW, client, DixWriteAccess); + if (result != Success) + return (result == BadValue) ? BadWindow : result; + + x = stuff->x; + y = stuff->y; + isRoot = win->u.win.root; + FOR_NSCREENS_BACKWARD(j) { + stuff->window = win->info[j].id; + if(isRoot) { + stuff->x = x - panoramiXdataPtr[j].x; + stuff->y = y - panoramiXdataPtr[j].y; + } + result = (*SavedProcVector[X_ClearArea])(client); + if(result != Success) break; + } + + return (result); +} + + +/* + For Window to Pixmap copies you're screwed since each screen's + pixmap will look like what it sees on its screen. Unless the + screens overlap and the window lies on each, the two copies + will be out of sync. To remedy this we do a GetImage and PutImage + in place of the copy. Doing this as a single Image isn't quite + correct since it will include the obscured areas but we will + have to fix this later. (MArk). +*/ + +int PanoramiXCopyArea(ClientPtr client) +{ + int j, result, srcx, srcy, dstx, dsty; + PanoramiXRes *gc, *src, *dst; + Bool srcIsRoot = FALSE; + Bool dstIsRoot = FALSE; + Bool srcShared, dstShared; + REQUEST(xCopyAreaReq); + + REQUEST_SIZE_MATCH(xCopyAreaReq); + + result = dixLookupResourceByClass((pointer *)&src, stuff->srcDrawable, + XRC_DRAWABLE, client, DixReadAccess); + if (result != Success) + return (result == BadValue) ? BadDrawable : result; + + srcShared = IS_SHARED_PIXMAP(src); + + result = dixLookupResourceByClass((pointer *)&dst, stuff->dstDrawable, + XRC_DRAWABLE, client, DixWriteAccess); + if (result != Success) + return (result == BadValue) ? BadDrawable : result; + + dstShared = IS_SHARED_PIXMAP(dst); + + if(dstShared && srcShared) + return (* SavedProcVector[X_CopyArea])(client); + + result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC, + client, DixReadAccess); + if (result != Success) + return (result == BadValue) ? BadGC : result; + + if((dst->type == XRT_WINDOW) && dst->u.win.root) + dstIsRoot = TRUE; + if((src->type == XRT_WINDOW) && src->u.win.root) + srcIsRoot = TRUE; + + srcx = stuff->srcX; srcy = stuff->srcY; + dstx = stuff->dstX; dsty = stuff->dstY; + if((dst->type == XRT_PIXMAP) && (src->type == XRT_WINDOW)) { + DrawablePtr drawables[MAXSCREENS]; + DrawablePtr pDst; + GCPtr pGC; + char *data; + int pitch, rc; + + FOR_NSCREENS(j) { + rc = dixLookupDrawable(drawables+j, src->info[j].id, client, 0, + DixGetAttrAccess); + if (rc != Success) + return rc; + } + + pitch = PixmapBytePad(stuff->width, drawables[0]->depth); + if(!(data = calloc(1, stuff->height * pitch))) + return BadAlloc; + + XineramaGetImageData(drawables, srcx, srcy, + stuff->width, stuff->height, ZPixmap, ~0, data, pitch, + srcIsRoot); + + FOR_NSCREENS_BACKWARD(j) { + stuff->gc = gc->info[j].id; + VALIDATE_DRAWABLE_AND_GC(dst->info[j].id, pDst, DixWriteAccess); + if(drawables[0]->depth != pDst->depth) { + client->errorValue = stuff->dstDrawable; + free(data); + return (BadMatch); + } + + (*pGC->ops->PutImage) (pDst, pGC, pDst->depth, dstx, dsty, + stuff->width, stuff->height, + 0, ZPixmap, data); + + if(dstShared) break; + } + + free(data); + } else { + DrawablePtr pDst = NULL, pSrc = NULL; + GCPtr pGC = NULL; + RegionPtr pRgn[MAXSCREENS]; + int rc; + + FOR_NSCREENS_BACKWARD(j) { + stuff->dstDrawable = dst->info[j].id; + stuff->srcDrawable = src->info[j].id; + stuff->gc = gc->info[j].id; + if (srcIsRoot) { + stuff->srcX = srcx - panoramiXdataPtr[j].x; + stuff->srcY = srcy - panoramiXdataPtr[j].y; + } + if (dstIsRoot) { + stuff->dstX = dstx - panoramiXdataPtr[j].x; + stuff->dstY = dsty - panoramiXdataPtr[j].y; + } + + 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[j] = (*pGC->ops->CopyArea)(pSrc, pDst, pGC, + stuff->srcX, stuff->srcY, + stuff->width, stuff->height, + stuff->dstX, stuff->dstY); + + if(dstShared) { + while(j--) pRgn[j] = NULL; + break; + } + } + + if(pGC->graphicsExposures) { + ScreenPtr pScreen = pDst->pScreen; + RegionRec totalReg; + Bool overlap; + + REGION_NULL(pScreen, &totalReg); + FOR_NSCREENS_BACKWARD(j) { + if(pRgn[j]) { + if(srcIsRoot) { + REGION_TRANSLATE(pScreen, pRgn[j], + panoramiXdataPtr[j].x, panoramiXdataPtr[j].y); + } + REGION_APPEND(pScreen, &totalReg, pRgn[j]); + REGION_DESTROY(pScreen, pRgn[j]); + } + } + REGION_VALIDATE(pScreen, &totalReg, &overlap); + (*pScreen->SendGraphicsExpose)( + client, &totalReg, stuff->dstDrawable, X_CopyArea, 0); + REGION_UNINIT(pScreen, &totalReg); + } + } + + return Success; +} + + +int PanoramiXCopyPlane(ClientPtr client) +{ + int j, srcx, srcy, dstx, dsty, rc; + PanoramiXRes *gc, *src, *dst; + Bool srcIsRoot = FALSE; + Bool dstIsRoot = FALSE; + Bool srcShared, dstShared; + DrawablePtr psrcDraw, pdstDraw = NULL; + GCPtr pGC = NULL; + RegionPtr pRgn[MAXSCREENS]; + REQUEST(xCopyPlaneReq); + + REQUEST_SIZE_MATCH(xCopyPlaneReq); + + rc = dixLookupResourceByClass((pointer *)&src, stuff->srcDrawable, + XRC_DRAWABLE, client, DixReadAccess); + if (rc != Success) + return (rc == BadValue) ? BadDrawable : rc; + + srcShared = IS_SHARED_PIXMAP(src); + + rc = dixLookupResourceByClass((pointer *)&dst, stuff->dstDrawable, + XRC_DRAWABLE, client, DixWriteAccess); + if (rc != Success) + return (rc == BadValue) ? BadDrawable : rc; + + dstShared = IS_SHARED_PIXMAP(dst); + + if(dstShared && srcShared) + return (* SavedProcVector[X_CopyPlane])(client); + + rc = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC, + client, DixReadAccess); + if (rc != Success) + return (rc == BadValue) ? BadGC : rc; + + if((dst->type == XRT_WINDOW) && dst->u.win.root) + dstIsRoot = TRUE; + if((src->type == XRT_WINDOW) && src->u.win.root) + srcIsRoot = TRUE; + + srcx = stuff->srcX; srcy = stuff->srcY; + dstx = stuff->dstX; dsty = stuff->dstY; + + FOR_NSCREENS_BACKWARD(j) { + stuff->dstDrawable = dst->info[j].id; + stuff->srcDrawable = src->info[j].id; + stuff->gc = gc->info[j].id; + if (srcIsRoot) { + stuff->srcX = srcx - panoramiXdataPtr[j].x; + stuff->srcY = srcy - panoramiXdataPtr[j].y; + } + if (dstIsRoot) { + stuff->dstX = dstx - panoramiXdataPtr[j].x; + stuff->dstY = dsty - panoramiXdataPtr[j].y; + } + + 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; + + if(stuff->bitPlane == 0 || (stuff->bitPlane & (stuff->bitPlane - 1)) || + (stuff->bitPlane > (1L << (psrcDraw->depth - 1)))) { + client->errorValue = stuff->bitPlane; + return(BadValue); + } + + pRgn[j] = (*pGC->ops->CopyPlane)(psrcDraw, pdstDraw, pGC, + stuff->srcX, stuff->srcY, + stuff->width, stuff->height, + stuff->dstX, stuff->dstY, stuff->bitPlane); + + if(dstShared) { + while(j--) pRgn[j] = NULL; + break; + } + } + + if(pGC->graphicsExposures) { + ScreenPtr pScreen = pdstDraw->pScreen; + RegionRec totalReg; + Bool overlap; + + REGION_NULL(pScreen, &totalReg); + FOR_NSCREENS_BACKWARD(j) { + if(pRgn[j]) { + REGION_APPEND(pScreen, &totalReg, pRgn[j]); + REGION_DESTROY(pScreen, pRgn[j]); + } + } + REGION_VALIDATE(pScreen, &totalReg, &overlap); + (*pScreen->SendGraphicsExpose)( + client, &totalReg, stuff->dstDrawable, X_CopyPlane, 0); + REGION_UNINIT(pScreen, &totalReg); + } + + return Success; +} + + +int PanoramiXPolyPoint(ClientPtr client) +{ + PanoramiXRes *gc, *draw; + int result, npoint, j; + xPoint *origPts; + Bool isRoot; + REQUEST(xPolyPointReq); + + REQUEST_AT_LEAST_SIZE(xPolyPointReq); + + result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable, + XRC_DRAWABLE, client, DixWriteAccess); + if (result != Success) + return (result == BadValue) ? BadDrawable : result; + + if(IS_SHARED_PIXMAP(draw)) + return (*SavedProcVector[X_PolyPoint])(client); + + result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC, + client, DixReadAccess); + if (result != Success) + return (result == BadValue) ? BadGC : result; + + isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; + npoint = bytes_to_int32((client->req_len << 2) - sizeof(xPolyPointReq)); + if (npoint > 0) { + origPts = malloc(npoint * sizeof(xPoint)); + memcpy((char *) origPts, (char *) &stuff[1], npoint * sizeof(xPoint)); + FOR_NSCREENS_FORWARD(j){ + + if(j) memcpy(&stuff[1], origPts, npoint * sizeof(xPoint)); + + if (isRoot) { + int x_off = panoramiXdataPtr[j].x; + int y_off = panoramiXdataPtr[j].y; + + if(x_off || y_off) { + xPoint *pnts = (xPoint*)&stuff[1]; + int i = (stuff->coordMode==CoordModePrevious) ? 1 : npoint; + + while(i--) { + pnts->x -= x_off; + pnts->y -= y_off; + pnts++; + } + } + } + + stuff->drawable = draw->info[j].id; + stuff->gc = gc->info[j].id; + result = (* SavedProcVector[X_PolyPoint])(client); + if(result != Success) break; + } + free(origPts); + return (result); + } else + return Success; +} + + +int PanoramiXPolyLine(ClientPtr client) +{ + PanoramiXRes *gc, *draw; + int result, npoint, j; + xPoint *origPts; + Bool isRoot; + REQUEST(xPolyLineReq); + + REQUEST_AT_LEAST_SIZE(xPolyLineReq); + + result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable, + XRC_DRAWABLE, client, DixWriteAccess); + if (result != Success) + return (result == BadValue) ? BadDrawable : result; + + if(IS_SHARED_PIXMAP(draw)) + return (*SavedProcVector[X_PolyLine])(client); + + result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC, + client, DixReadAccess); + if (result != Success) + return (result == BadValue) ? BadGC : result; + + isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; + npoint = bytes_to_int32((client->req_len << 2) - sizeof(xPolyLineReq)); + if (npoint > 0){ + origPts = malloc(npoint * sizeof(xPoint)); + memcpy((char *) origPts, (char *) &stuff[1], npoint * sizeof(xPoint)); + FOR_NSCREENS_FORWARD(j){ + + if(j) memcpy(&stuff[1], origPts, npoint * sizeof(xPoint)); + + if (isRoot) { + int x_off = panoramiXdataPtr[j].x; + int y_off = panoramiXdataPtr[j].y; + + if(x_off || y_off) { + xPoint *pnts = (xPoint*)&stuff[1]; + int i = (stuff->coordMode==CoordModePrevious) ? 1 : npoint; + + while(i--) { + pnts->x -= x_off; + pnts->y -= y_off; + pnts++; + } + } + } + + stuff->drawable = draw->info[j].id; + stuff->gc = gc->info[j].id; + result = (* SavedProcVector[X_PolyLine])(client); + if(result != Success) break; + } + free(origPts); + return (result); + } else + return Success; +} + + +int PanoramiXPolySegment(ClientPtr client) +{ + int result, nsegs, i, j; + PanoramiXRes *gc, *draw; + xSegment *origSegs; + Bool isRoot; + REQUEST(xPolySegmentReq); + + REQUEST_AT_LEAST_SIZE(xPolySegmentReq); + + result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable, + XRC_DRAWABLE, client, DixWriteAccess); + if (result != Success) + return (result == BadValue) ? BadDrawable : result; + + if(IS_SHARED_PIXMAP(draw)) + return (*SavedProcVector[X_PolySegment])(client); + + result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC, + client, DixReadAccess); + if (result != Success) + return (result == BadValue) ? BadGC : result; + + isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; + + nsegs = (client->req_len << 2) - sizeof(xPolySegmentReq); + if(nsegs & 4) return BadLength; + nsegs >>= 3; + if (nsegs > 0) { + origSegs = malloc(nsegs * sizeof(xSegment)); + memcpy((char *) origSegs, (char *) &stuff[1], nsegs * sizeof(xSegment)); + FOR_NSCREENS_FORWARD(j){ + + if(j) memcpy(&stuff[1], origSegs, nsegs * sizeof(xSegment)); + + if (isRoot) { + int x_off = panoramiXdataPtr[j].x; + int y_off = panoramiXdataPtr[j].y; + + if(x_off || y_off) { + xSegment *segs = (xSegment*)&stuff[1]; + + for (i = nsegs; i--; segs++) { + segs->x1 -= x_off; + segs->x2 -= x_off; + segs->y1 -= y_off; + segs->y2 -= y_off; + } + } + } + + stuff->drawable = draw->info[j].id; + stuff->gc = gc->info[j].id; + result = (* SavedProcVector[X_PolySegment])(client); + if(result != Success) break; + } + free(origSegs); + return (result); + } else + return Success; +} + + +int PanoramiXPolyRectangle(ClientPtr client) +{ + int result, nrects, i, j; + PanoramiXRes *gc, *draw; + Bool isRoot; + xRectangle *origRecs; + REQUEST(xPolyRectangleReq); + + REQUEST_AT_LEAST_SIZE(xPolyRectangleReq); + + result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable, + XRC_DRAWABLE, client, DixWriteAccess); + if (result != Success) + return (result == BadValue) ? BadDrawable : result; + + if(IS_SHARED_PIXMAP(draw)) + return (*SavedProcVector[X_PolyRectangle])(client); + + result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC, + client, DixReadAccess); + if (result != Success) + return (result == BadValue) ? BadGC : result; + + isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; + + nrects = (client->req_len << 2) - sizeof(xPolyRectangleReq); + if(nrects & 4) return BadLength; + nrects >>= 3; + if (nrects > 0){ + origRecs = malloc(nrects * sizeof(xRectangle)); + memcpy((char *)origRecs,(char *)&stuff[1],nrects * sizeof(xRectangle)); + FOR_NSCREENS_FORWARD(j){ + + if(j) memcpy(&stuff[1], origRecs, nrects * sizeof(xRectangle)); + + if (isRoot) { + int x_off = panoramiXdataPtr[j].x; + int y_off = panoramiXdataPtr[j].y; + + + if(x_off || y_off) { + xRectangle *rects = (xRectangle *) &stuff[1]; + + for (i = nrects; i--; rects++) { + rects->x -= x_off; + rects->y -= y_off; + } + } + } + + stuff->drawable = draw->info[j].id; + stuff->gc = gc->info[j].id; + result = (* SavedProcVector[X_PolyRectangle])(client); + if(result != Success) break; + } + free(origRecs); + return (result); + } else + return Success; +} + + +int PanoramiXPolyArc(ClientPtr client) +{ + int result, narcs, i, j; + PanoramiXRes *gc, *draw; + Bool isRoot; + xArc *origArcs; + REQUEST(xPolyArcReq); + + REQUEST_AT_LEAST_SIZE(xPolyArcReq); + + result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable, + XRC_DRAWABLE, client, DixWriteAccess); + if (result != Success) + return (result == BadValue) ? BadDrawable : result; + + if(IS_SHARED_PIXMAP(draw)) + return (*SavedProcVector[X_PolyArc])(client); + + result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC, + client, DixReadAccess); + if (result != Success) + return (result == BadValue) ? BadGC : result; + + isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; + + narcs = (client->req_len << 2) - sizeof(xPolyArcReq); + if(narcs % sizeof(xArc)) return BadLength; + narcs /= sizeof(xArc); + if (narcs > 0){ + origArcs = malloc(narcs * sizeof(xArc)); + memcpy((char *) origArcs, (char *) &stuff[1], narcs * sizeof(xArc)); + FOR_NSCREENS_FORWARD(j){ + + if(j) memcpy(&stuff[1], origArcs, narcs * sizeof(xArc)); + + if (isRoot) { + int x_off = panoramiXdataPtr[j].x; + int y_off = panoramiXdataPtr[j].y; + + if(x_off || y_off) { + xArc *arcs = (xArc *) &stuff[1]; + + for (i = narcs; i--; arcs++) { + arcs->x -= x_off; + arcs->y -= y_off; + } + } + } + stuff->drawable = draw->info[j].id; + stuff->gc = gc->info[j].id; + result = (* SavedProcVector[X_PolyArc])(client); + if(result != Success) break; + } + free(origArcs); + return (result); + } else + return Success; +} + + +int PanoramiXFillPoly(ClientPtr client) +{ + int result, count, j; + PanoramiXRes *gc, *draw; + Bool isRoot; + DDXPointPtr locPts; + REQUEST(xFillPolyReq); + + REQUEST_AT_LEAST_SIZE(xFillPolyReq); + + result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable, + XRC_DRAWABLE, client, DixWriteAccess); + if (result != Success) + return (result == BadValue) ? BadDrawable : result; + + if(IS_SHARED_PIXMAP(draw)) + return (*SavedProcVector[X_FillPoly])(client); + + result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC, + client, DixReadAccess); + if (result != Success) + return (result == BadValue) ? BadGC : result; + + isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; + + count = bytes_to_int32((client->req_len << 2) - sizeof(xFillPolyReq)); + if (count > 0){ + locPts = malloc(count * sizeof(DDXPointRec)); + memcpy((char *)locPts, (char *)&stuff[1], count * sizeof(DDXPointRec)); + FOR_NSCREENS_FORWARD(j){ + + if(j) memcpy(&stuff[1], locPts, count * sizeof(DDXPointRec)); + + if (isRoot) { + int x_off = panoramiXdataPtr[j].x; + int y_off = panoramiXdataPtr[j].y; + + if(x_off || y_off) { + DDXPointPtr pnts = (DDXPointPtr)&stuff[1]; + int i = (stuff->coordMode==CoordModePrevious) ? 1 : count; + + while(i--) { + pnts->x -= x_off; + pnts->y -= y_off; + pnts++; + } + } + } + + stuff->drawable = draw->info[j].id; + stuff->gc = gc->info[j].id; + result = (* SavedProcVector[X_FillPoly])(client); + if(result != Success) break; + } + free(locPts); + return (result); + } else + return Success; +} + + +int PanoramiXPolyFillRectangle(ClientPtr client) +{ + int result, things, i, j; + PanoramiXRes *gc, *draw; + Bool isRoot; + xRectangle *origRects; + REQUEST(xPolyFillRectangleReq); + + REQUEST_AT_LEAST_SIZE(xPolyFillRectangleReq); + + result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable, + XRC_DRAWABLE, client, DixWriteAccess); + if (result != Success) + return (result == BadValue) ? BadDrawable : result; + + if(IS_SHARED_PIXMAP(draw)) + return (*SavedProcVector[X_PolyFillRectangle])(client); + + result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC, + client, DixReadAccess); + if (result != Success) + return (result == BadValue) ? BadGC : result; + + isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; + + things = (client->req_len << 2) - sizeof(xPolyFillRectangleReq); + if(things & 4) return BadLength; + things >>= 3; + if (things > 0){ + origRects = malloc(things * sizeof(xRectangle)); + memcpy((char*)origRects,(char*)&stuff[1], things * sizeof(xRectangle)); + FOR_NSCREENS_FORWARD(j){ + + if(j) memcpy(&stuff[1], origRects, things * sizeof(xRectangle)); + + if (isRoot) { + int x_off = panoramiXdataPtr[j].x; + int y_off = panoramiXdataPtr[j].y; + + if(x_off || y_off) { + xRectangle *rects = (xRectangle *) &stuff[1]; + + for (i = things; i--; rects++) { + rects->x -= x_off; + rects->y -= y_off; + } + } + } + + stuff->drawable = draw->info[j].id; + stuff->gc = gc->info[j].id; + result = (* SavedProcVector[X_PolyFillRectangle])(client); + if(result != Success) break; + } + free(origRects); + return (result); + } else + return Success; +} + + +int PanoramiXPolyFillArc(ClientPtr client) +{ + PanoramiXRes *gc, *draw; + Bool isRoot; + int result, narcs, i, j; + xArc *origArcs; + REQUEST(xPolyFillArcReq); + + REQUEST_AT_LEAST_SIZE(xPolyFillArcReq); + + result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable, + XRC_DRAWABLE, client, DixWriteAccess); + if (result != Success) + return (result == BadValue) ? BadDrawable : result; + + if(IS_SHARED_PIXMAP(draw)) + return (*SavedProcVector[X_PolyFillArc])(client); + + result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC, + client, DixReadAccess); + if (result != Success) + return (result == BadValue) ? BadGC : result; + + isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; + + narcs = (client->req_len << 2) - sizeof(xPolyFillArcReq); + if (narcs % sizeof(xArc)) return BadLength; + narcs /= sizeof(xArc); + if (narcs > 0) { + origArcs = malloc(narcs * sizeof(xArc)); + memcpy((char *) origArcs, (char *)&stuff[1], narcs * sizeof(xArc)); + FOR_NSCREENS_FORWARD(j){ + + if(j) memcpy(&stuff[1], origArcs, narcs * sizeof(xArc)); + + if (isRoot) { + int x_off = panoramiXdataPtr[j].x; + int y_off = panoramiXdataPtr[j].y; + + if(x_off || y_off) { + xArc *arcs = (xArc *) &stuff[1]; + + for (i = narcs; i--; arcs++) { + arcs->x -= x_off; + arcs->y -= y_off; + } + } + } + + stuff->drawable = draw->info[j].id; + stuff->gc = gc->info[j].id; + result = (* SavedProcVector[X_PolyFillArc])(client); + if(result != Success) break; + } + free(origArcs); + return (result); + } else + return Success; +} + + +int PanoramiXPutImage(ClientPtr client) +{ + PanoramiXRes *gc, *draw; + Bool isRoot; + int j, result, orig_x, orig_y; + REQUEST(xPutImageReq); + + REQUEST_AT_LEAST_SIZE(xPutImageReq); + + result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable, + XRC_DRAWABLE, client, DixWriteAccess); + if (result != Success) + return (result == BadValue) ? BadDrawable : result; + + if(IS_SHARED_PIXMAP(draw)) + return (*SavedProcVector[X_PutImage])(client); + + result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC, + client, DixReadAccess); + if (result != Success) + return (result == BadValue) ? BadGC : result; + + isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; + + orig_x = stuff->dstX; + orig_y = stuff->dstY; + FOR_NSCREENS_BACKWARD(j){ + if (isRoot) { + stuff->dstX = orig_x - panoramiXdataPtr[j].x; + stuff->dstY = orig_y - panoramiXdataPtr[j].y; + } + stuff->drawable = draw->info[j].id; + stuff->gc = gc->info[j].id; + result = (* SavedProcVector[X_PutImage])(client); + if(result != Success) break; + } + return (result); +} + + +int PanoramiXGetImage(ClientPtr client) +{ + DrawablePtr drawables[MAXSCREENS]; + DrawablePtr pDraw; + PanoramiXRes *draw; + xGetImageReply xgi; + Bool isRoot; + char *pBuf; + int i, x, y, w, h, format, rc; + Mask plane = 0, planemask; + int linesDone, nlines, linesPerBuf; + long widthBytesLine, length; + + REQUEST(xGetImageReq); + + REQUEST_SIZE_MATCH(xGetImageReq); + + if ((stuff->format != XYPixmap) && (stuff->format != ZPixmap)) { + client->errorValue = stuff->format; + return(BadValue); + } + + rc = dixLookupResourceByClass((pointer *)&draw, stuff->drawable, + XRC_DRAWABLE, client, DixWriteAccess); + if (rc != Success) + return (rc == BadValue) ? BadDrawable : rc; + + if(draw->type == XRT_PIXMAP) + return (*SavedProcVector[X_GetImage])(client); + + rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0, + DixReadAccess); + if (rc != Success) + return rc; + + if(!((WindowPtr)pDraw)->realized) + return(BadMatch); + + x = stuff->x; + y = stuff->y; + w = stuff->width; + h = stuff->height; + format = stuff->format; + planemask = stuff->planeMask; + + isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; + + if(isRoot) { + if( /* check for being onscreen */ + x < 0 || x + w > PanoramiXPixWidth || + y < 0 || y + h > PanoramiXPixHeight ) + return(BadMatch); + } else { + if( /* check for being onscreen */ + panoramiXdataPtr[0].x + pDraw->x + x < 0 || + panoramiXdataPtr[0].x + pDraw->x + x + w > PanoramiXPixWidth || + panoramiXdataPtr[0].y + pDraw->y + y < 0 || + panoramiXdataPtr[0].y + pDraw->y + y + h > PanoramiXPixHeight || + /* check for being inside of border */ + x < - wBorderWidth((WindowPtr)pDraw) || + x + w > wBorderWidth((WindowPtr)pDraw) + (int)pDraw->width || + y < -wBorderWidth((WindowPtr)pDraw) || + y + h > wBorderWidth ((WindowPtr)pDraw) + (int)pDraw->height) + return(BadMatch); + } + + drawables[0] = pDraw; + for(i = 1; i < PanoramiXNumScreens; i++) { + rc = dixLookupDrawable(drawables+i, draw->info[i].id, client, 0, + DixGetAttrAccess); + if (rc != Success) + return rc; + } + + xgi.visual = wVisual (((WindowPtr) pDraw)); + xgi.type = X_Reply; + xgi.sequenceNumber = client->sequence; + xgi.depth = pDraw->depth; + if(format == ZPixmap) { + widthBytesLine = PixmapBytePad(w, pDraw->depth); + length = widthBytesLine * h; + + + } else { + widthBytesLine = BitmapBytePad(w); + plane = ((Mask)1) << (pDraw->depth - 1); + /* only planes asked for */ + length = widthBytesLine * h * + Ones(planemask & (plane | (plane - 1))); + + } + + xgi.length = bytes_to_int32(length); + + if (widthBytesLine == 0 || h == 0) + linesPerBuf = 0; + else if (widthBytesLine >= XINERAMA_IMAGE_BUFSIZE) + linesPerBuf = 1; + else { + linesPerBuf = XINERAMA_IMAGE_BUFSIZE / widthBytesLine; + if (linesPerBuf > h) + linesPerBuf = h; + } + length = linesPerBuf * widthBytesLine; + if(!(pBuf = malloc(length))) + return (BadAlloc); + + WriteReplyToClient(client, sizeof (xGetImageReply), &xgi); + + if (linesPerBuf == 0) { + /* nothing to do */ + } + else if (format == ZPixmap) { + linesDone = 0; + while (h - linesDone > 0) { + nlines = min(linesPerBuf, h - linesDone); + + if(pDraw->depth == 1) + bzero(pBuf, nlines * widthBytesLine); + + XineramaGetImageData(drawables, x, y + linesDone, w, nlines, + format, planemask, pBuf, widthBytesLine, isRoot); + + (void)WriteToClient(client, + (int)(nlines * widthBytesLine), + pBuf); + linesDone += nlines; + } + } else { /* XYPixmap */ + for (; plane; plane >>= 1) { + if (planemask & plane) { + linesDone = 0; + while (h - linesDone > 0) { + nlines = min(linesPerBuf, h - linesDone); + + bzero(pBuf, nlines * widthBytesLine); + + XineramaGetImageData(drawables, x, y + linesDone, w, + nlines, format, plane, pBuf, + widthBytesLine, isRoot); + + (void)WriteToClient(client, + (int)(nlines * widthBytesLine), + pBuf); + + linesDone += nlines; + } + } + } + } + free(pBuf); + return Success; +} + + +/* The text stuff should be rewritten so that duplication happens + at the GlyphBlt level. That is, loading the font and getting + the glyphs should only happen once */ + +int +PanoramiXPolyText8(ClientPtr client) +{ + PanoramiXRes *gc, *draw; + Bool isRoot; + int result, j; + int orig_x, orig_y; + REQUEST(xPolyTextReq); + + REQUEST_AT_LEAST_SIZE(xPolyTextReq); + + result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable, + XRC_DRAWABLE, client, DixWriteAccess); + if (result != Success) + return (result == BadValue) ? BadDrawable : result; + + if(IS_SHARED_PIXMAP(draw)) + return (*SavedProcVector[X_PolyText8])(client); + + result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC, + client, DixReadAccess); + if (result != Success) + return (result == BadValue) ? BadGC : result; + + isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; + + orig_x = stuff->x; + orig_y = stuff->y; + FOR_NSCREENS_BACKWARD(j){ + stuff->drawable = draw->info[j].id; + stuff->gc = gc->info[j].id; + if (isRoot) { + stuff->x = orig_x - panoramiXdataPtr[j].x; + stuff->y = orig_y - panoramiXdataPtr[j].y; + } + result = (*SavedProcVector[X_PolyText8])(client); + if(result != Success) break; + } + return (result); +} + +int +PanoramiXPolyText16(ClientPtr client) +{ + PanoramiXRes *gc, *draw; + Bool isRoot; + int result, j; + int orig_x, orig_y; + REQUEST(xPolyTextReq); + + REQUEST_AT_LEAST_SIZE(xPolyTextReq); + + result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable, + XRC_DRAWABLE, client, DixWriteAccess); + if (result != Success) + return (result == BadValue) ? BadDrawable : result; + + if(IS_SHARED_PIXMAP(draw)) + return (*SavedProcVector[X_PolyText16])(client); + + result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC, + client, DixReadAccess); + if (result != Success) + return (result == BadValue) ? BadGC : result; + + isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; + + orig_x = stuff->x; + orig_y = stuff->y; + FOR_NSCREENS_BACKWARD(j){ + stuff->drawable = draw->info[j].id; + stuff->gc = gc->info[j].id; + if (isRoot) { + stuff->x = orig_x - panoramiXdataPtr[j].x; + stuff->y = orig_y - panoramiXdataPtr[j].y; + } + result = (*SavedProcVector[X_PolyText16])(client); + if(result != Success) break; + } + return (result); +} + + +int PanoramiXImageText8(ClientPtr client) +{ + int result, j; + PanoramiXRes *gc, *draw; + Bool isRoot; + int orig_x, orig_y; + REQUEST(xImageTextReq); + + REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars); + + result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable, + XRC_DRAWABLE, client, DixWriteAccess); + if (result != Success) + return (result == BadValue) ? BadDrawable : result; + + if(IS_SHARED_PIXMAP(draw)) + return (*SavedProcVector[X_ImageText8])(client); + + result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC, + client, DixReadAccess); + if (result != Success) + return (result == BadValue) ? BadGC : result; + + isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; + + orig_x = stuff->x; + orig_y = stuff->y; + FOR_NSCREENS_BACKWARD(j){ + stuff->drawable = draw->info[j].id; + stuff->gc = gc->info[j].id; + if (isRoot) { + stuff->x = orig_x - panoramiXdataPtr[j].x; + stuff->y = orig_y - panoramiXdataPtr[j].y; + } + result = (*SavedProcVector[X_ImageText8])(client); + if(result != Success) break; + } + return (result); +} + + +int PanoramiXImageText16(ClientPtr client) +{ + int result, j; + PanoramiXRes *gc, *draw; + Bool isRoot; + int orig_x, orig_y; + REQUEST(xImageTextReq); + + REQUEST_FIXED_SIZE(xImageTextReq, stuff->nChars << 1); + + result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable, + XRC_DRAWABLE, client, DixWriteAccess); + if (result != Success) + return (result == BadValue) ? BadDrawable : result; + + if(IS_SHARED_PIXMAP(draw)) + return (*SavedProcVector[X_ImageText16])(client); + + result = dixLookupResourceByType((pointer *)&gc, stuff->gc, XRT_GC, + client, DixReadAccess); + if (result != Success) + return (result == BadValue) ? BadGC : result; + + isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; + + orig_x = stuff->x; + orig_y = stuff->y; + FOR_NSCREENS_BACKWARD(j){ + stuff->drawable = draw->info[j].id; + stuff->gc = gc->info[j].id; + if (isRoot) { + stuff->x = orig_x - panoramiXdataPtr[j].x; + stuff->y = orig_y - panoramiXdataPtr[j].y; + } + result = (*SavedProcVector[X_ImageText16])(client); + if(result != Success) break; + } + return (result); +} + + + +int PanoramiXCreateColormap(ClientPtr client) +{ + PanoramiXRes *win, *newCmap; + int result, j, orig_visual; + REQUEST(xCreateColormapReq); + + REQUEST_SIZE_MATCH(xCreateColormapReq); + + result = dixLookupResourceByType((pointer *)&win, stuff->window, + XRT_WINDOW, client, DixReadAccess); + if (result != Success) + return (result == BadValue) ? BadWindow : result; + + if(!(newCmap = malloc(sizeof(PanoramiXRes)))) + return BadAlloc; + + newCmap->type = XRT_COLORMAP; + newCmap->info[0].id = stuff->mid; + for(j = 1; j < PanoramiXNumScreens; j++) + newCmap->info[j].id = FakeClientID(client->index); + + orig_visual = stuff->visual; + FOR_NSCREENS_BACKWARD(j){ + stuff->mid = newCmap->info[j].id; + stuff->window = win->info[j].id; + stuff->visual = PanoramiXTranslateVisualID(j, orig_visual); + result = (* SavedProcVector[X_CreateColormap])(client); + if(result != Success) break; + } + + if (result == Success) + AddResource(newCmap->info[0].id, XRT_COLORMAP, newCmap); + else + free(newCmap); + + return (result); +} + + +int PanoramiXFreeColormap(ClientPtr client) +{ + PanoramiXRes *cmap; + int result, j; + REQUEST(xResourceReq); + + REQUEST_SIZE_MATCH(xResourceReq); + + client->errorValue = stuff->id; + + result = dixLookupResourceByType((pointer *)&cmap, stuff->id, XRT_COLORMAP, + client, DixDestroyAccess); + if (result != Success) + return (result == BadValue) ? BadColor : result; + + FOR_NSCREENS_BACKWARD(j) { + stuff->id = cmap->info[j].id; + result = (* SavedProcVector[X_FreeColormap])(client); + if(result != Success) break; + } + + /* Since ProcFreeColormap is using FreeResource, it will free + our resource for us on the last pass through the loop above */ + + return (result); +} + + +int +PanoramiXCopyColormapAndFree(ClientPtr client) +{ + PanoramiXRes *cmap, *newCmap; + int result, j; + REQUEST(xCopyColormapAndFreeReq); + + REQUEST_SIZE_MATCH(xCopyColormapAndFreeReq); + + client->errorValue = stuff->srcCmap; + + result = dixLookupResourceByType((pointer *)&cmap, stuff->srcCmap, + XRT_COLORMAP, client, + DixReadAccess | DixWriteAccess); + if (result != Success) + return (result == BadValue) ? BadColor : result; + + if(!(newCmap = malloc(sizeof(PanoramiXRes)))) + return BadAlloc; + + newCmap->type = XRT_COLORMAP; + newCmap->info[0].id = stuff->mid; + for(j = 1; j < PanoramiXNumScreens; j++) + newCmap->info[j].id = FakeClientID(client->index); + + FOR_NSCREENS_BACKWARD(j){ + stuff->srcCmap = cmap->info[j].id; + stuff->mid = newCmap->info[j].id; + result = (* SavedProcVector[X_CopyColormapAndFree])(client); + if(result != Success) break; + } + + if (result == Success) + AddResource(newCmap->info[0].id, XRT_COLORMAP, newCmap); + else + free(newCmap); + + return (result); +} + + +int PanoramiXInstallColormap(ClientPtr client) +{ + REQUEST(xResourceReq); + int result, j; + PanoramiXRes *cmap; + + REQUEST_SIZE_MATCH(xResourceReq); + + client->errorValue = stuff->id; + + result = dixLookupResourceByType((pointer *)&cmap, stuff->id, XRT_COLORMAP, + client, DixReadAccess); + if (result != Success) + return (result == BadValue) ? BadColor : result; + + FOR_NSCREENS_BACKWARD(j){ + stuff->id = cmap->info[j].id; + result = (* SavedProcVector[X_InstallColormap])(client); + if(result != Success) break; + } + return (result); +} + + +int PanoramiXUninstallColormap(ClientPtr client) +{ + REQUEST(xResourceReq); + int result, j; + PanoramiXRes *cmap; + + REQUEST_SIZE_MATCH(xResourceReq); + + client->errorValue = stuff->id; + + result = dixLookupResourceByType((pointer *)&cmap, stuff->id, XRT_COLORMAP, + client, DixReadAccess); + if (result != Success) + return (result == BadValue) ? BadColor : result; + + FOR_NSCREENS_BACKWARD(j) { + stuff->id = cmap->info[j].id; + result = (* SavedProcVector[X_UninstallColormap])(client); + if(result != Success) break; + } + return (result); +} + + +int PanoramiXAllocColor(ClientPtr client) +{ + int result, j; + PanoramiXRes *cmap; + REQUEST(xAllocColorReq); + + REQUEST_SIZE_MATCH(xAllocColorReq); + + client->errorValue = stuff->cmap; + + result = dixLookupResourceByType((pointer *)&cmap, stuff->cmap, + XRT_COLORMAP, client, DixWriteAccess); + if (result != Success) + return (result == BadValue) ? BadColor : result; + + FOR_NSCREENS_BACKWARD(j){ + stuff->cmap = cmap->info[j].id; + result = (* SavedProcVector[X_AllocColor])(client); + if(result != Success) break; + } + return (result); +} + + +int PanoramiXAllocNamedColor(ClientPtr client) +{ + int result, j; + PanoramiXRes *cmap; + REQUEST(xAllocNamedColorReq); + + REQUEST_FIXED_SIZE(xAllocNamedColorReq, stuff->nbytes); + + client->errorValue = stuff->cmap; + + result = dixLookupResourceByType((pointer *)&cmap, stuff->cmap, + XRT_COLORMAP, client, DixWriteAccess); + if (result != Success) + return (result == BadValue) ? BadColor : result; + + FOR_NSCREENS_BACKWARD(j){ + stuff->cmap = cmap->info[j].id; + result = (* SavedProcVector[X_AllocNamedColor])(client); + if(result != Success) break; + } + return (result); +} + + +int PanoramiXAllocColorCells(ClientPtr client) +{ + int result, j; + PanoramiXRes *cmap; + REQUEST(xAllocColorCellsReq); + + REQUEST_SIZE_MATCH(xAllocColorCellsReq); + + client->errorValue = stuff->cmap; + + result = dixLookupResourceByType((pointer *)&cmap, stuff->cmap, + XRT_COLORMAP, client, DixWriteAccess); + if (result != Success) + return (result == BadValue) ? BadColor : result; + + FOR_NSCREENS_BACKWARD(j){ + stuff->cmap = cmap->info[j].id; + result = (* SavedProcVector[X_AllocColorCells])(client); + if(result != Success) break; + } + return (result); +} + + +int PanoramiXAllocColorPlanes(ClientPtr client) +{ + int result, j; + PanoramiXRes *cmap; + REQUEST(xAllocColorPlanesReq); + + REQUEST_SIZE_MATCH(xAllocColorPlanesReq); + + client->errorValue = stuff->cmap; + + result = dixLookupResourceByType((pointer *)&cmap, stuff->cmap, + XRT_COLORMAP, client, DixWriteAccess); + if (result != Success) + return (result == BadValue) ? BadColor : result; + + FOR_NSCREENS_BACKWARD(j){ + stuff->cmap = cmap->info[j].id; + result = (* SavedProcVector[X_AllocColorPlanes])(client); + if(result != Success) break; + } + return (result); +} + + + +int PanoramiXFreeColors(ClientPtr client) +{ + int result, j; + PanoramiXRes *cmap; + REQUEST(xFreeColorsReq); + + REQUEST_AT_LEAST_SIZE(xFreeColorsReq); + + client->errorValue = stuff->cmap; + + result = dixLookupResourceByType((pointer *)&cmap, stuff->cmap, + XRT_COLORMAP, client, DixWriteAccess); + if (result != Success) + return (result == BadValue) ? BadColor : result; + + FOR_NSCREENS_BACKWARD(j) { + stuff->cmap = cmap->info[j].id; + result = (* SavedProcVector[X_FreeColors])(client); + } + return (result); +} + + +int PanoramiXStoreColors(ClientPtr client) +{ + int result, j; + PanoramiXRes *cmap; + REQUEST(xStoreColorsReq); + + REQUEST_AT_LEAST_SIZE(xStoreColorsReq); + + client->errorValue = stuff->cmap; + + result = dixLookupResourceByType((pointer *)&cmap, stuff->cmap, + XRT_COLORMAP, client, DixWriteAccess); + if (result != Success) + return (result == BadValue) ? BadColor : result; + + FOR_NSCREENS_BACKWARD(j){ + stuff->cmap = cmap->info[j].id; + result = (* SavedProcVector[X_StoreColors])(client); + if(result != Success) break; + } + return (result); +} + + +int PanoramiXStoreNamedColor(ClientPtr client) +{ + int result, j; + PanoramiXRes *cmap; + REQUEST(xStoreNamedColorReq); + + REQUEST_FIXED_SIZE(xStoreNamedColorReq, stuff->nbytes); + + client->errorValue = stuff->cmap; + + result = dixLookupResourceByType((pointer *)&cmap, stuff->cmap, + XRT_COLORMAP, client, DixWriteAccess); + if (result != Success) + return (result == BadValue) ? BadColor : result; + + FOR_NSCREENS_BACKWARD(j){ + stuff->cmap = cmap->info[j].id; + result = (* SavedProcVector[X_StoreNamedColor])(client); + if(result != Success) break; + } + return (result); +} diff --git a/xorg-server/Xext/saver.c b/xorg-server/Xext/saver.c index aa2e61428..f82b4b51b 100644 --- a/xorg-server/Xext/saver.c +++ b/xorg-server/Xext/saver.c @@ -1,1539 +1,1539 @@ -/* - * -Copyright (c) 1992 X Consortium - -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 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 -X CONSORTIUM 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 X Consortium 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 X Consortium. - * - * Author: Keith Packard, MIT X Consortium - */ - - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include -#include -#include "misc.h" -#include "os.h" -#include "windowstr.h" -#include "scrnintstr.h" -#include "pixmapstr.h" -#include "extnsionst.h" -#include "dixstruct.h" -#include "resource.h" -#include "opaque.h" -#include -#include "gcstruct.h" -#include "cursorstr.h" -#include "colormapst.h" -#include "xace.h" -#ifdef PANORAMIX -#include "panoramiX.h" -#include "panoramiXsrv.h" -#endif -#ifdef DPMSExtension -#include -#endif -#include "protocol-versions.h" - -#include - -#include "modinit.h" - -static int ScreenSaverEventBase = 0; - -static DISPATCH_PROC(ProcScreenSaverQueryInfo); -static DISPATCH_PROC(ProcScreenSaverDispatch); -static DISPATCH_PROC(ProcScreenSaverQueryVersion); -static DISPATCH_PROC(ProcScreenSaverSelectInput); -static DISPATCH_PROC(ProcScreenSaverSetAttributes); -static DISPATCH_PROC(ProcScreenSaverUnsetAttributes); -static DISPATCH_PROC(ProcScreenSaverSuspend); -static DISPATCH_PROC(SProcScreenSaverDispatch); -static DISPATCH_PROC(SProcScreenSaverQueryInfo); -static DISPATCH_PROC(SProcScreenSaverQueryVersion); -static DISPATCH_PROC(SProcScreenSaverSelectInput); -static DISPATCH_PROC(SProcScreenSaverSetAttributes); -static DISPATCH_PROC(SProcScreenSaverUnsetAttributes); -static DISPATCH_PROC(SProcScreenSaverSuspend); - -static Bool ScreenSaverHandle ( - ScreenPtr /* pScreen */, - int /* xstate */, - Bool /* force */ - ); - -static Bool -CreateSaverWindow ( - ScreenPtr /* pScreen */ - ); - -static Bool -DestroySaverWindow ( - ScreenPtr /* pScreen */ - ); - -static void -UninstallSaverColormap ( - ScreenPtr /* pScreen */ - ); - -static void -CheckScreenPrivate ( - ScreenPtr /* pScreen */ - ); - -static void SScreenSaverNotifyEvent ( - xScreenSaverNotifyEvent * /* from */, - xScreenSaverNotifyEvent * /* to */ - ); - -static RESTYPE SuspendType; /* resource type for suspension records */ - -typedef struct _ScreenSaverSuspension *ScreenSaverSuspensionPtr; - -/* List of clients that are suspending the screensaver. */ -static ScreenSaverSuspensionPtr suspendingClients = NULL; - -/* - * clientResource is a resource ID that's added when the record is - * allocated, so the record is freed and the screensaver resumed when - * the client disconnects. count is the number of times the client has - * requested the screensaver be suspended. - */ -typedef struct _ScreenSaverSuspension -{ - ScreenSaverSuspensionPtr next; - ClientPtr pClient; - XID clientResource; - int count; -} ScreenSaverSuspensionRec; - -static int ScreenSaverFreeSuspend( - pointer /*value */, - XID /* id */ -); - -/* - * each screen has a list of clients requesting - * ScreenSaverNotify events. Each client has a resource - * for each screen it selects ScreenSaverNotify input for, - * this resource is used to delete the ScreenSaverNotifyRec - * entry from the per-screen queue. - */ - -static RESTYPE SaverEventType; /* resource type for event masks */ - -typedef struct _ScreenSaverEvent *ScreenSaverEventPtr; - -typedef struct _ScreenSaverEvent { - ScreenSaverEventPtr next; - ClientPtr client; - ScreenPtr screen; - XID resource; - CARD32 mask; -} ScreenSaverEventRec; - -static int ScreenSaverFreeEvents( - pointer /* value */, - XID /* id */ -); - -static Bool setEventMask ( - ScreenPtr /* pScreen */, - ClientPtr /* client */, - unsigned long /* mask */ -); - -static unsigned long getEventMask ( - ScreenPtr /* pScreen */, - ClientPtr /* client */ -); - -/* - * when a client sets the screen saver attributes, a resource is - * kept to be freed when the client exits - */ - -static RESTYPE AttrType; /* resource type for attributes */ - -typedef struct _ScreenSaverAttr { - ScreenPtr screen; - ClientPtr client; - XID resource; - short x, y; - unsigned short width, height, borderWidth; - unsigned char class; - unsigned char depth; - VisualID visual; - CursorPtr pCursor; - PixmapPtr pBackgroundPixmap; - PixmapPtr pBorderPixmap; - Colormap colormap; - unsigned long mask; /* no pixmaps or cursors */ - unsigned long *values; -} ScreenSaverAttrRec, *ScreenSaverAttrPtr; - -static int ScreenSaverFreeAttr ( - pointer /* value */, - XID /* id */ -); - -static void FreeAttrs ( - ScreenSaverAttrPtr /* pAttr */ -); - -static void FreeScreenAttr ( - ScreenSaverAttrPtr /* pAttr */ -); - -static void -SendScreenSaverNotify ( - ScreenPtr /* pScreen */, - int /* state */, - Bool /* forced */ -); - -typedef struct _ScreenSaverScreenPrivate { - ScreenSaverEventPtr events; - ScreenSaverAttrPtr attr; - Bool hasWindow; - Colormap installedMap; -} ScreenSaverScreenPrivateRec, *ScreenSaverScreenPrivatePtr; - -static ScreenSaverScreenPrivatePtr -MakeScreenPrivate ( - ScreenPtr /* pScreen */ - ); - -static int ScreenPrivateKeyIndex; -static DevPrivateKey ScreenPrivateKey = &ScreenPrivateKeyIndex; - -#define GetScreenPrivate(s) ((ScreenSaverScreenPrivatePtr) \ - dixLookupPrivate(&(s)->devPrivates, ScreenPrivateKey)) -#define SetScreenPrivate(s,v) \ - dixSetPrivate(&(s)->devPrivates, ScreenPrivateKey, v); -#define SetupScreen(s) ScreenSaverScreenPrivatePtr pPriv = (s ? GetScreenPrivate(s) : NULL) - -#define New(t) (xalloc (sizeof (t))) - -/**************** - * ScreenSaverExtensionInit - * - * Called from InitExtensions in main() or from QueryExtension() if the - * extension is dynamically loaded. - * - ****************/ - -void -ScreenSaverExtensionInit(INITARGS) -{ - ExtensionEntry *extEntry; - int i; - ScreenPtr pScreen; - - AttrType = CreateNewResourceType(ScreenSaverFreeAttr, "SaverAttr"); - SaverEventType = CreateNewResourceType(ScreenSaverFreeEvents, - "SaverEvent"); - SuspendType = CreateNewResourceType(ScreenSaverFreeSuspend, - "SaverSuspend"); - - for (i = 0; i < screenInfo.numScreens; i++) - { - pScreen = screenInfo.screens[i]; - SetScreenPrivate (pScreen, NULL); - } - if (AttrType && SaverEventType && SuspendType && - (extEntry = AddExtension(ScreenSaverName, ScreenSaverNumberEvents, 0, - ProcScreenSaverDispatch, SProcScreenSaverDispatch, - NULL, StandardMinorOpcode))) - { - ScreenSaverEventBase = extEntry->eventBase; - EventSwapVector[ScreenSaverEventBase] = (EventSwapPtr) SScreenSaverNotifyEvent; - } -} - -static void -CheckScreenPrivate (ScreenPtr pScreen) -{ - SetupScreen (pScreen); - - if (!pPriv) - return; - if (!pPriv->attr && !pPriv->events && - !pPriv->hasWindow && pPriv->installedMap == None) - { - xfree (pPriv); - SetScreenPrivate (pScreen, NULL); - savedScreenInfo[pScreen->myNum].ExternalScreenSaver = NULL; - } -} - -static ScreenSaverScreenPrivatePtr -MakeScreenPrivate (ScreenPtr pScreen) -{ - SetupScreen (pScreen); - - if (pPriv) - return pPriv; - pPriv = New (ScreenSaverScreenPrivateRec); - if (!pPriv) - return 0; - pPriv->events = 0; - pPriv->attr = 0; - pPriv->hasWindow = FALSE; - pPriv->installedMap = None; - SetScreenPrivate (pScreen, pPriv); - savedScreenInfo[pScreen->myNum].ExternalScreenSaver = ScreenSaverHandle; - return pPriv; -} - -static unsigned long -getEventMask (ScreenPtr pScreen, ClientPtr client) -{ - SetupScreen(pScreen); - ScreenSaverEventPtr pEv; - - if (!pPriv) - return 0; - for (pEv = pPriv->events; pEv; pEv = pEv->next) - if (pEv->client == client) - return pEv->mask; - return 0; -} - -static Bool -setEventMask (ScreenPtr pScreen, ClientPtr client, unsigned long mask) -{ - SetupScreen(pScreen); - ScreenSaverEventPtr pEv, *pPrev; - - if (getEventMask (pScreen, client) == mask) - return TRUE; - if (!pPriv) - { - pPriv = MakeScreenPrivate (pScreen); - if (!pPriv) - return FALSE; - } - for (pPrev = &pPriv->events; (pEv = *pPrev) != 0; pPrev = &pEv->next) - if (pEv->client == client) - break; - if (mask == 0) - { - FreeResource (pEv->resource, SaverEventType); - *pPrev = pEv->next; - xfree (pEv); - CheckScreenPrivate (pScreen); - } - else - { - if (!pEv) - { - pEv = New (ScreenSaverEventRec); - if (!pEv) - { - CheckScreenPrivate (pScreen); - return FALSE; - } - *pPrev = pEv; - pEv->next = NULL; - pEv->client = client; - pEv->screen = pScreen; - pEv->resource = FakeClientID (client->index); - if (!AddResource (pEv->resource, SaverEventType, (pointer) pEv)) - return FALSE; - } - pEv->mask = mask; - } - return TRUE; -} - -static void -FreeAttrs (ScreenSaverAttrPtr pAttr) -{ - PixmapPtr pPixmap; - CursorPtr pCursor; - - if ((pPixmap = pAttr->pBackgroundPixmap) != 0) - (*pPixmap->drawable.pScreen->DestroyPixmap)(pPixmap); - if ((pPixmap = pAttr->pBorderPixmap) != 0) - (*pPixmap->drawable.pScreen->DestroyPixmap)(pPixmap); - if ((pCursor = pAttr->pCursor) != 0) - FreeCursor (pCursor, (Cursor) 0); -} - -static void -FreeScreenAttr (ScreenSaverAttrPtr pAttr) -{ - FreeAttrs (pAttr); - xfree (pAttr->values); - xfree (pAttr); -} - -static int -ScreenSaverFreeEvents (pointer value, XID id) -{ - ScreenSaverEventPtr pOld = (ScreenSaverEventPtr)value; - ScreenPtr pScreen = pOld->screen; - SetupScreen (pScreen); - ScreenSaverEventPtr pEv, *pPrev; - - if (!pPriv) - return TRUE; - for (pPrev = &pPriv->events; (pEv = *pPrev) != 0; pPrev = &pEv->next) - if (pEv == pOld) - break; - if (!pEv) - return TRUE; - *pPrev = pEv->next; - xfree (pEv); - CheckScreenPrivate (pScreen); - return TRUE; -} - -static int -ScreenSaverFreeAttr (pointer value, XID id) -{ - ScreenSaverAttrPtr pOldAttr = (ScreenSaverAttrPtr)value; - ScreenPtr pScreen = pOldAttr->screen; - SetupScreen (pScreen); - - if (!pPriv) - return TRUE; - if (pPriv->attr != pOldAttr) - return TRUE; - FreeScreenAttr (pOldAttr); - pPriv->attr = NULL; - if (pPriv->hasWindow) - { - dixSaveScreens (serverClient, SCREEN_SAVER_FORCER, ScreenSaverReset); - dixSaveScreens (serverClient, SCREEN_SAVER_FORCER, ScreenSaverActive); - } - CheckScreenPrivate (pScreen); - return TRUE; -} - -static int -ScreenSaverFreeSuspend (pointer value, XID id) -{ - ScreenSaverSuspensionPtr data = (ScreenSaverSuspensionPtr) value; - ScreenSaverSuspensionPtr *prev, this; - - /* Unlink and free the suspension record for the client */ - for (prev = &suspendingClients; (this = *prev); prev = &this->next) - { - if (this == data) - { - *prev = this->next; - xfree (this); - break; - } - } - - /* Reenable the screensaver if this was the last client suspending it. */ - if (screenSaverSuspended && suspendingClients == NULL) - { - screenSaverSuspended = FALSE; - - /* The screensaver could be active, since suspending it (by design) - doesn't prevent it from being forceably activated */ -#ifdef DPMSExtension - if (screenIsSaved != SCREEN_SAVER_ON && DPMSPowerLevel == DPMSModeOn) -#else - if (screenIsSaved != SCREEN_SAVER_ON) -#endif - { - UpdateCurrentTimeIf(); - lastDeviceEventTime = currentTime; - SetScreenSaverTimer(); - } - } - - return Success; -} - -static void -SendScreenSaverNotify (ScreenPtr pScreen, int state, Bool forced) -{ - ScreenSaverScreenPrivatePtr pPriv; - ScreenSaverEventPtr pEv; - unsigned long mask; - xScreenSaverNotifyEvent ev; - ClientPtr client; - int kind; - - UpdateCurrentTimeIf (); - mask = ScreenSaverNotifyMask; - if (state == ScreenSaverCycle) - mask = ScreenSaverCycleMask; - pScreen = screenInfo.screens[pScreen->myNum]; - pPriv = GetScreenPrivate(pScreen); - if (!pPriv) - return; - if (pPriv->attr) - kind = ScreenSaverExternal; - else if (ScreenSaverBlanking != DontPreferBlanking) - kind = ScreenSaverBlanked; - else - kind = ScreenSaverInternal; - for (pEv = pPriv->events; pEv; pEv = pEv->next) - { - client = pEv->client; - if (client->clientGone) - continue; - if (!(pEv->mask & mask)) - continue; - ev.type = ScreenSaverNotify + ScreenSaverEventBase; - ev.state = state; - ev.sequenceNumber = client->sequence; - ev.timestamp = currentTime.milliseconds; - ev.root = WindowTable[pScreen->myNum]->drawable.id; - ev.window = savedScreenInfo[pScreen->myNum].wid; - ev.kind = kind; - ev.forced = forced; - WriteEventsToClient (client, 1, (xEvent *) &ev); - } -} - -static void -SScreenSaverNotifyEvent (xScreenSaverNotifyEvent *from, - xScreenSaverNotifyEvent *to) -{ - to->type = from->type; - to->state = from->state; - cpswaps (from->sequenceNumber, to->sequenceNumber); - cpswapl (from->timestamp, to->timestamp); - cpswapl (from->root, to->root); - cpswapl (from->window, to->window); - to->kind = from->kind; - to->forced = from->forced; -} - -static void -UninstallSaverColormap (ScreenPtr pScreen) -{ - SetupScreen(pScreen); - ColormapPtr pCmap; - int rc; - - if (pPriv && pPriv->installedMap != None) - { - rc = dixLookupResourceByType((pointer *)&pCmap, pPriv->installedMap, - RT_COLORMAP, serverClient, - DixUninstallAccess); - if (rc == Success) - (*pCmap->pScreen->UninstallColormap) (pCmap); - pPriv->installedMap = None; - CheckScreenPrivate (pScreen); - } -} - -static Bool -CreateSaverWindow (ScreenPtr pScreen) -{ - SetupScreen (pScreen); - ScreenSaverStuffPtr pSaver; - ScreenSaverAttrPtr pAttr; - WindowPtr pWin; - int result; - unsigned long mask; - Colormap *installedMaps; - int numInstalled; - int i; - Colormap wantMap; - ColormapPtr pCmap; - - pSaver = &savedScreenInfo[pScreen->myNum]; - if (pSaver->pWindow) - { - pSaver->pWindow = NullWindow; - FreeResource (pSaver->wid, RT_NONE); - if (pPriv) - { - UninstallSaverColormap (pScreen); - pPriv->hasWindow = FALSE; - CheckScreenPrivate (pScreen); - } - } - - if (!pPriv || !(pAttr = pPriv->attr)) - return FALSE; - - pPriv->installedMap = None; - - if (GrabInProgress && GrabInProgress != pAttr->client->index) - return FALSE; - - pWin = CreateWindow (pSaver->wid, WindowTable[pScreen->myNum], - pAttr->x, pAttr->y, pAttr->width, pAttr->height, - pAttr->borderWidth, pAttr->class, - pAttr->mask, (XID *)pAttr->values, - pAttr->depth, serverClient, pAttr->visual, - &result); - if (!pWin) - return FALSE; - - if (!AddResource(pWin->drawable.id, RT_WINDOW, pWin)) - return FALSE; - - mask = 0; - if (pAttr->pBackgroundPixmap) - { - pWin->backgroundState = BackgroundPixmap; - pWin->background.pixmap = pAttr->pBackgroundPixmap; - pAttr->pBackgroundPixmap->refcnt++; - mask |= CWBackPixmap; - } - if (pAttr->pBorderPixmap) - { - pWin->borderIsPixel = FALSE; - pWin->border.pixmap = pAttr->pBorderPixmap; - pAttr->pBorderPixmap->refcnt++; - mask |= CWBorderPixmap; - } - if (pAttr->pCursor) - { - if (!pWin->optional) - if (!MakeWindowOptional (pWin)) - { - FreeResource (pWin->drawable.id, RT_NONE); - return FALSE; - } - pAttr->pCursor->refcnt++; - if (pWin->optional->cursor) - FreeCursor (pWin->optional->cursor, (Cursor)0); - pWin->optional->cursor = pAttr->pCursor; - pWin->cursorIsNone = FALSE; - CheckWindowOptionalNeed (pWin); - mask |= CWCursor; - } - if (mask) - (*pScreen->ChangeWindowAttributes) (pWin, mask); - - if (pAttr->colormap != None) - (void) ChangeWindowAttributes (pWin, CWColormap, &pAttr->colormap, - serverClient); - - MapWindow (pWin, serverClient); - - pPriv->hasWindow = TRUE; - pSaver->pWindow = pWin; - - /* check and install our own colormap if it isn't installed now */ - wantMap = wColormap (pWin); - if (wantMap == None) - return TRUE; - installedMaps = xalloc (pScreen->maxInstalledCmaps * sizeof (Colormap)); - numInstalled = (*pWin->drawable.pScreen->ListInstalledColormaps) - (pScreen, installedMaps); - for (i = 0; i < numInstalled; i++) - if (installedMaps[i] == wantMap) - break; - - xfree ((char *) installedMaps); - - if (i < numInstalled) - return TRUE; - - result = dixLookupResourceByType((pointer *)&pCmap, wantMap, RT_COLORMAP, - serverClient, DixInstallAccess); - if (result != Success) - return TRUE; - - pPriv->installedMap = wantMap; - - (*pCmap->pScreen->InstallColormap) (pCmap); - - return TRUE; -} - -static Bool -DestroySaverWindow (ScreenPtr pScreen) -{ - SetupScreen(pScreen); - ScreenSaverStuffPtr pSaver; - - if (!pPriv || !pPriv->hasWindow) - return FALSE; - - pSaver = &savedScreenInfo[pScreen->myNum]; - if (pSaver->pWindow) - { - pSaver->pWindow = NullWindow; - FreeResource (pSaver->wid, RT_NONE); - } - pPriv->hasWindow = FALSE; - CheckScreenPrivate (pScreen); - UninstallSaverColormap (pScreen); - return TRUE; -} - -static Bool -ScreenSaverHandle (ScreenPtr pScreen, int xstate, Bool force) -{ - int state = 0; - Bool ret = FALSE; - ScreenSaverScreenPrivatePtr pPriv; - - switch (xstate) - { - case SCREEN_SAVER_ON: - state = ScreenSaverOn; - ret = CreateSaverWindow (pScreen); - break; - case SCREEN_SAVER_OFF: - state = ScreenSaverOff; - ret = DestroySaverWindow (pScreen); - break; - case SCREEN_SAVER_CYCLE: - state = ScreenSaverCycle; - pPriv = GetScreenPrivate (pScreen); - if (pPriv && pPriv->hasWindow) - ret = TRUE; - - } -#ifdef PANORAMIX - if(noPanoramiXExtension || !pScreen->myNum) -#endif - SendScreenSaverNotify (pScreen, state, force); - return ret; -} - -static int -ProcScreenSaverQueryVersion (ClientPtr client) -{ - xScreenSaverQueryVersionReply rep; - int n; - - REQUEST_SIZE_MATCH (xScreenSaverQueryVersionReq); - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.majorVersion = SERVER_SAVER_MAJOR_VERSION; - rep.minorVersion = SERVER_SAVER_MINOR_VERSION; - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - } - WriteToClient(client, sizeof (xScreenSaverQueryVersionReply), (char *)&rep); - return (client->noClientException); -} - -static int -ProcScreenSaverQueryInfo (ClientPtr client) -{ - REQUEST(xScreenSaverQueryInfoReq); - xScreenSaverQueryInfoReply rep; - int n, rc; - ScreenSaverStuffPtr pSaver; - DrawablePtr pDraw; - CARD32 lastInput; - ScreenSaverScreenPrivatePtr pPriv; - - REQUEST_SIZE_MATCH (xScreenSaverQueryInfoReq); - rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0, - DixGetAttrAccess); - if (rc != Success) - return rc; - rc = XaceHook(XACE_SCREENSAVER_ACCESS, client, pDraw->pScreen, - DixGetAttrAccess); - if (rc != Success) - return rc; - - pSaver = &savedScreenInfo[pDraw->pScreen->myNum]; - pPriv = GetScreenPrivate (pDraw->pScreen); - - UpdateCurrentTime (); - lastInput = GetTimeInMillis() - lastDeviceEventTime.milliseconds; - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.window = pSaver->wid; - if (screenIsSaved != SCREEN_SAVER_OFF) - { - rep.state = ScreenSaverOn; - if (ScreenSaverTime) - rep.tilOrSince = lastInput - ScreenSaverTime; - else - rep.tilOrSince = 0; - } - else - { - if (ScreenSaverTime) - { - rep.state = ScreenSaverOff; - if (ScreenSaverTime < lastInput) - rep.tilOrSince = 0; - else - rep.tilOrSince = ScreenSaverTime - lastInput; - } - else - { - rep.state = ScreenSaverDisabled; - rep.tilOrSince = 0; - } - } - rep.idle = lastInput; - rep.eventMask = getEventMask (pDraw->pScreen, client); - if (pPriv && pPriv->attr) - rep.kind = ScreenSaverExternal; - else if (ScreenSaverBlanking != DontPreferBlanking) - rep.kind = ScreenSaverBlanked; - else - rep.kind = ScreenSaverInternal; - if (client->swapped) - { - swaps (&rep.sequenceNumber, n); - swapl (&rep.length, n); - swapl (&rep.window, n); - swapl (&rep.tilOrSince, n); - swapl (&rep.idle, n); - swapl (&rep.eventMask, n); - } - WriteToClient(client, sizeof (xScreenSaverQueryInfoReply), (char *)&rep); - return (client->noClientException); -} - -static int -ProcScreenSaverSelectInput (ClientPtr client) -{ - REQUEST(xScreenSaverSelectInputReq); - DrawablePtr pDraw; - int rc; - - REQUEST_SIZE_MATCH (xScreenSaverSelectInputReq); - rc = dixLookupDrawable (&pDraw, stuff->drawable, client, 0, - DixGetAttrAccess); - if (rc != Success) - return rc; - - rc = XaceHook(XACE_SCREENSAVER_ACCESS, client, pDraw->pScreen, - DixSetAttrAccess); - if (rc != Success) - return rc; - - if (!setEventMask (pDraw->pScreen, client, stuff->eventMask)) - return BadAlloc; - return Success; -} - -static int -ScreenSaverSetAttributes (ClientPtr client) -{ - REQUEST(xScreenSaverSetAttributesReq); - DrawablePtr pDraw; - WindowPtr pParent; - ScreenPtr pScreen; - ScreenSaverScreenPrivatePtr pPriv = 0; - ScreenSaverAttrPtr pAttr = 0; - int ret, len, class, bw, depth; - unsigned long visual; - int idepth, ivisual; - Bool fOK; - DepthPtr pDepth; - WindowOptPtr ancwopt; - unsigned int *pVlist; - unsigned long *values = 0; - unsigned long tmask, imask; - unsigned long val; - Pixmap pixID; - PixmapPtr pPixmap; - Cursor cursorID; - CursorPtr pCursor; - Colormap cmap; - ColormapPtr pCmap; - - REQUEST_AT_LEAST_SIZE (xScreenSaverSetAttributesReq); - ret = dixLookupDrawable(&pDraw, stuff->drawable, client, 0, - DixGetAttrAccess); - if (ret != Success) - return ret; - pScreen = pDraw->pScreen; - pParent = WindowTable[pScreen->myNum]; - - ret = XaceHook(XACE_SCREENSAVER_ACCESS, client, pScreen, DixSetAttrAccess); - if (ret != Success) - return ret; - - len = stuff->length - bytes_to_int32(sizeof(xScreenSaverSetAttributesReq)); - if (Ones(stuff->mask) != len) - return BadLength; - if (!stuff->width || !stuff->height) - { - client->errorValue = 0; - return BadValue; - } - switch (class = stuff->c_class) - { - case CopyFromParent: - case InputOnly: - case InputOutput: - break; - default: - client->errorValue = class; - return BadValue; - } - bw = stuff->borderWidth; - depth = stuff->depth; - visual = stuff->visualID; - - /* copied directly from CreateWindow */ - - if (class == CopyFromParent) - class = pParent->drawable.class; - - if ((class != InputOutput) && (class != InputOnly)) - { - client->errorValue = class; - return BadValue; - } - - if ((class != InputOnly) && (pParent->drawable.class == InputOnly)) - return BadMatch; - - if ((class == InputOnly) && ((bw != 0) || (depth != 0))) - return BadMatch; - - if ((class == InputOutput) && (depth == 0)) - depth = pParent->drawable.depth; - ancwopt = pParent->optional; - if (!ancwopt) - ancwopt = FindWindowWithOptional(pParent)->optional; - if (visual == CopyFromParent) - visual = ancwopt->visual; - - /* Find out if the depth and visual are acceptable for this Screen */ - if ((visual != ancwopt->visual) || (depth != pParent->drawable.depth)) - { - fOK = FALSE; - for(idepth = 0; idepth < pScreen->numDepths; idepth++) - { - pDepth = (DepthPtr) &pScreen->allowedDepths[idepth]; - if ((depth == pDepth->depth) || (depth == 0)) - { - for (ivisual = 0; ivisual < pDepth->numVids; ivisual++) - { - if (visual == pDepth->vids[ivisual]) - { - fOK = TRUE; - break; - } - } - } - } - if (fOK == FALSE) - return BadMatch; - } - - if (((stuff->mask & (CWBorderPixmap | CWBorderPixel)) == 0) && - (class != InputOnly) && - (depth != pParent->drawable.depth)) - { - return BadMatch; - } - - if (((stuff->mask & CWColormap) == 0) && - (class != InputOnly) && - ((visual != ancwopt->visual) || (ancwopt->colormap == None))) - { - return BadMatch; - } - - /* end of errors from CreateWindow */ - - pPriv = GetScreenPrivate (pScreen); - if (pPriv && pPriv->attr) - { - if (pPriv->attr->client != client) - return BadAccess; - } - if (!pPriv) - { - pPriv = MakeScreenPrivate (pScreen); - if (!pPriv) - return FALSE; - } - pAttr = New (ScreenSaverAttrRec); - if (!pAttr) - { - ret = BadAlloc; - goto bail; - } - /* over allocate for override redirect */ - values = xalloc ((len + 1) * sizeof (unsigned long)); - if (!values) - { - ret = BadAlloc; - goto bail; - } - pAttr->screen = pScreen; - pAttr->client = client; - pAttr->x = stuff->x; - pAttr->y = stuff->y; - pAttr->width = stuff->width; - pAttr->height = stuff->height; - pAttr->borderWidth = stuff->borderWidth; - pAttr->class = stuff->c_class; - pAttr->depth = depth; - pAttr->visual = visual; - pAttr->colormap = None; - pAttr->pCursor = NullCursor; - pAttr->pBackgroundPixmap = NullPixmap; - pAttr->pBorderPixmap = NullPixmap; - pAttr->values = values; - /* - * go through the mask, checking the values, - * looking up pixmaps and cursors and hold a reference - * to them. - */ - pAttr->mask = tmask = stuff->mask | CWOverrideRedirect; - pVlist = (unsigned int *) (stuff + 1); - while (tmask) { - imask = lowbit (tmask); - tmask &= ~imask; - switch (imask) - { - case CWBackPixmap: - pixID = (Pixmap )*pVlist; - if (pixID == None) - { - *values++ = None; - } - else if (pixID == ParentRelative) - { - if (depth != pParent->drawable.depth) - { - ret = BadMatch; - goto PatchUp; - } - *values++ = ParentRelative; - } - else - { - ret = dixLookupResourceByType((pointer *)&pPixmap, pixID, RT_PIXMAP, - client, DixReadAccess); - if (ret == Success) - { - if ((pPixmap->drawable.depth != depth) || - (pPixmap->drawable.pScreen != pScreen)) - { - ret = BadMatch; - goto PatchUp; - } - pAttr->pBackgroundPixmap = pPixmap; - pPixmap->refcnt++; - pAttr->mask &= ~CWBackPixmap; - } - else - { - ret = (ret == BadValue) ? BadPixmap : ret; - client->errorValue = pixID; - goto PatchUp; - } - } - break; - case CWBackPixel: - *values++ = (CARD32) *pVlist; - break; - case CWBorderPixmap: - pixID = (Pixmap ) *pVlist; - if (pixID == CopyFromParent) - { - if (depth != pParent->drawable.depth) - { - ret = BadMatch; - goto PatchUp; - } - *values++ = CopyFromParent; - } - else - { - ret = dixLookupResourceByType((pointer *)&pPixmap, pixID, RT_PIXMAP, - client, DixReadAccess); - if (ret == Success) - { - if ((pPixmap->drawable.depth != depth) || - (pPixmap->drawable.pScreen != pScreen)) - { - ret = BadMatch; - goto PatchUp; - } - pAttr->pBorderPixmap = pPixmap; - pPixmap->refcnt++; - pAttr->mask &= ~CWBorderPixmap; - } - else - { - ret = (ret == BadValue) ? BadPixmap : ret; - client->errorValue = pixID; - goto PatchUp; - } - } - break; - case CWBorderPixel: - *values++ = (CARD32) *pVlist; - break; - case CWBitGravity: - val = (CARD8 )*pVlist; - if (val > StaticGravity) - { - ret = BadValue; - client->errorValue = val; - goto PatchUp; - } - *values++ = val; - break; - case CWWinGravity: - val = (CARD8 )*pVlist; - if (val > StaticGravity) - { - ret = BadValue; - client->errorValue = val; - goto PatchUp; - } - *values++ = val; - break; - case CWBackingStore: - val = (CARD8 )*pVlist; - if ((val != NotUseful) && (val != WhenMapped) && (val != Always)) - { - ret = BadValue; - client->errorValue = val; - goto PatchUp; - } - *values++ = val; - break; - case CWBackingPlanes: - *values++ = (CARD32) *pVlist; - break; - case CWBackingPixel: - *values++ = (CARD32) *pVlist; - break; - case CWSaveUnder: - val = (BOOL) *pVlist; - if ((val != xTrue) && (val != xFalse)) - { - ret = BadValue; - client->errorValue = val; - goto PatchUp; - } - *values++ = val; - break; - case CWEventMask: - *values++ = (CARD32) *pVlist; - break; - case CWDontPropagate: - *values++ = (CARD32) *pVlist; - break; - case CWOverrideRedirect: - if (!(stuff->mask & CWOverrideRedirect)) - pVlist--; - else - { - val = (BOOL ) *pVlist; - if ((val != xTrue) && (val != xFalse)) - { - ret = BadValue; - client->errorValue = val; - goto PatchUp; - } - } - *values++ = xTrue; - break; - case CWColormap: - cmap = (Colormap) *pVlist; - ret = dixLookupResourceByType((pointer *)&pCmap, cmap, RT_COLORMAP, - client, DixUseAccess); - if (ret != Success) - { - ret = (ret == BadValue) ? BadColor : ret; - client->errorValue = cmap; - goto PatchUp; - } - if (pCmap->pVisual->vid != visual || pCmap->pScreen != pScreen) - { - ret = BadMatch; - goto PatchUp; - } - pAttr->colormap = cmap; - pAttr->mask &= ~CWColormap; - break; - case CWCursor: - cursorID = (Cursor ) *pVlist; - if ( cursorID == None) - { - *values++ = None; - } - else - { - ret = dixLookupResourceByType((pointer *)&pCursor, cursorID, - RT_CURSOR, client, DixUseAccess); - if (ret != Success) - { - ret = (ret == BadValue) ? BadCursor : ret; - client->errorValue = cursorID; - goto PatchUp; - } - pCursor->refcnt++; - pAttr->pCursor = pCursor; - pAttr->mask &= ~CWCursor; - } - break; - default: - ret = BadValue; - client->errorValue = stuff->mask; - goto PatchUp; - } - pVlist++; - } - if (pPriv->attr) - FreeScreenAttr (pPriv->attr); - pPriv->attr = pAttr; - pAttr->resource = FakeClientID (client->index); - if (!AddResource (pAttr->resource, AttrType, (pointer) pAttr)) - return BadAlloc; - return Success; -PatchUp: - FreeAttrs (pAttr); -bail: - CheckScreenPrivate (pScreen); - if (pAttr) xfree (pAttr->values); - xfree (pAttr); - return ret; -} - -static int -ScreenSaverUnsetAttributes (ClientPtr client) -{ - REQUEST(xScreenSaverSetAttributesReq); - DrawablePtr pDraw; - ScreenSaverScreenPrivatePtr pPriv; - int rc; - - REQUEST_SIZE_MATCH (xScreenSaverUnsetAttributesReq); - rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0, - DixGetAttrAccess); - if (rc != Success) - return rc; - pPriv = GetScreenPrivate (pDraw->pScreen); - if (pPriv && pPriv->attr && pPriv->attr->client == client) - { - FreeResource (pPriv->attr->resource, AttrType); - FreeScreenAttr (pPriv->attr); - pPriv->attr = NULL; - CheckScreenPrivate (pDraw->pScreen); - } - return Success; -} - -static int -ProcScreenSaverSetAttributes (ClientPtr client) -{ -#ifdef PANORAMIX - if(!noPanoramiXExtension) { - REQUEST(xScreenSaverSetAttributesReq); - PanoramiXRes *draw; - PanoramiXRes *backPix = NULL; - PanoramiXRes *bordPix = NULL; - PanoramiXRes *cmap = NULL; - int i, status, len; - int pback_offset = 0, pbord_offset = 0, cmap_offset = 0; - XID orig_visual, tmp; - - REQUEST_AT_LEAST_SIZE (xScreenSaverSetAttributesReq); - - status = dixLookupResourceByClass((pointer *)&draw, stuff->drawable, - XRC_DRAWABLE, client, DixWriteAccess); - if (status != Success) - return (status == BadValue) ? BadDrawable : status; - - len = stuff->length - bytes_to_int32(sizeof(xScreenSaverSetAttributesReq)); - if (Ones(stuff->mask) != len) - return BadLength; - - if((Mask)stuff->mask & CWBackPixmap) { - pback_offset = Ones((Mask)stuff->mask & (CWBackPixmap - 1)); - tmp = *((CARD32 *) &stuff[1] + pback_offset); - if ((tmp != None) && (tmp != ParentRelative)) { - status = dixLookupResourceByType((pointer *)&backPix, tmp, - XRT_PIXMAP, client, - DixReadAccess); - if (status != Success) - return (status == BadValue) ? BadPixmap : status; - } - } - - if ((Mask)stuff->mask & CWBorderPixmap) { - pbord_offset = Ones((Mask)stuff->mask & (CWBorderPixmap - 1)); - tmp = *((CARD32 *) &stuff[1] + pbord_offset); - if (tmp != CopyFromParent) { - status = dixLookupResourceByType((pointer *)&bordPix, tmp, - XRT_PIXMAP, client, - DixReadAccess); - if (status != Success) - return (status == BadValue) ? BadPixmap : status; - } - } - - if ((Mask)stuff->mask & CWColormap) { - cmap_offset = Ones((Mask)stuff->mask & (CWColormap - 1)); - tmp = *((CARD32 *) &stuff[1] + cmap_offset); - if ((tmp != CopyFromParent) && (tmp != None)) { - status = dixLookupResourceByType((pointer *)&cmap, tmp, - XRT_COLORMAP, client, - DixReadAccess); - if (status != Success) - return (status == BadValue) ? BadColor : status; - } - } - - orig_visual = stuff->visualID; - - FOR_NSCREENS_BACKWARD(i) { - stuff->drawable = draw->info[i].id; - if (backPix) - *((CARD32 *) &stuff[1] + pback_offset) = backPix->info[i].id; - if (bordPix) - *((CARD32 *) &stuff[1] + pbord_offset) = bordPix->info[i].id; - if (cmap) - *((CARD32 *) &stuff[1] + cmap_offset) = cmap->info[i].id; - - if (orig_visual != CopyFromParent) - stuff->visualID = PanoramiXTranslateVisualID(i, orig_visual); - - status = ScreenSaverSetAttributes(client); - } - - return status; - } -#endif - - return ScreenSaverSetAttributes(client); -} - -static int -ProcScreenSaverUnsetAttributes (ClientPtr client) -{ -#ifdef PANORAMIX - if(!noPanoramiXExtension) { - REQUEST(xScreenSaverUnsetAttributesReq); - PanoramiXRes *draw; - int rc, i; - - rc = dixLookupResourceByClass((pointer *)&draw, stuff->drawable, - XRC_DRAWABLE, client, DixWriteAccess); - if (rc != Success) - return (rc == BadValue) ? BadDrawable : rc; - - for(i = PanoramiXNumScreens - 1; i > 0; i--) { - stuff->drawable = draw->info[i].id; - ScreenSaverUnsetAttributes(client); - } - - stuff->drawable = draw->info[0].id; - } -#endif - - return ScreenSaverUnsetAttributes(client); -} - -static int -ProcScreenSaverSuspend (ClientPtr client) -{ - ScreenSaverSuspensionPtr *prev, this; - - REQUEST(xScreenSaverSuspendReq); - REQUEST_SIZE_MATCH(xScreenSaverSuspendReq); - - /* Check if this client is suspending the screensaver */ - for (prev = &suspendingClients; (this = *prev); prev = &this->next) - if (this->pClient == client) - break; - - if (this) - { - if (stuff->suspend == TRUE) - this->count++; - else if (--this->count == 0) - FreeResource (this->clientResource, RT_NONE); - - return Success; - } - - /* If we get to this point, this client isn't suspending the screensaver */ - if (stuff->suspend == FALSE) - return Success; - - /* - * Allocate a suspension record for the client, and stop the screensaver - * if it isn't already suspended by another client. We attach a resource ID - * to the record, so the screensaver will be reenabled and the record freed - * if the client disconnects without reenabling it first. - */ - this = xalloc (sizeof (ScreenSaverSuspensionRec)); - - if (!this) - return BadAlloc; - - this->next = NULL; - this->pClient = client; - this->count = 1; - this->clientResource = FakeClientID (client->index); - - if (!AddResource (this->clientResource, SuspendType, (pointer) this)) - { - xfree (this); - return BadAlloc; - } - - *prev = this; - if (!screenSaverSuspended) - { - screenSaverSuspended = TRUE; - FreeScreenSaverTimer(); - } - - return (client->noClientException); -} - -static DISPATCH_PROC((*NormalVector[])) = { - ProcScreenSaverQueryVersion, - ProcScreenSaverQueryInfo, - ProcScreenSaverSelectInput, - ProcScreenSaverSetAttributes, - ProcScreenSaverUnsetAttributes, - ProcScreenSaverSuspend, -}; - -#define NUM_REQUESTS ((sizeof NormalVector) / (sizeof NormalVector[0])) - -static int -ProcScreenSaverDispatch (ClientPtr client) -{ - REQUEST(xReq); - - if (stuff->data < NUM_REQUESTS) - return (*NormalVector[stuff->data])(client); - return BadRequest; -} - -static int -SProcScreenSaverQueryVersion (ClientPtr client) -{ - REQUEST(xScreenSaverQueryVersionReq); - int n; - - swaps (&stuff->length, n); - REQUEST_SIZE_MATCH(xScreenSaverQueryVersionReq); - return ProcScreenSaverQueryVersion (client); -} - -static int -SProcScreenSaverQueryInfo (ClientPtr client) -{ - REQUEST(xScreenSaverQueryInfoReq); - int n; - - swaps (&stuff->length, n); - REQUEST_SIZE_MATCH(xScreenSaverQueryInfoReq); - swapl (&stuff->drawable, n); - return ProcScreenSaverQueryInfo (client); -} - -static int -SProcScreenSaverSelectInput (ClientPtr client) -{ - REQUEST(xScreenSaverSelectInputReq); - int n; - - swaps (&stuff->length, n); - REQUEST_SIZE_MATCH(xScreenSaverSelectInputReq); - swapl (&stuff->drawable, n); - swapl (&stuff->eventMask, n); - return ProcScreenSaverSelectInput (client); -} - -static int -SProcScreenSaverSetAttributes (ClientPtr client) -{ - REQUEST(xScreenSaverSetAttributesReq); - int n; - - swaps (&stuff->length, n); - REQUEST_AT_LEAST_SIZE(xScreenSaverSetAttributesReq); - swapl (&stuff->drawable, n); - swaps (&stuff->x, n); - swaps (&stuff->y, n); - swaps (&stuff->width, n); - swaps (&stuff->height, n); - swaps (&stuff->borderWidth, n); - swapl (&stuff->visualID, n); - swapl (&stuff->mask, n); - SwapRestL(stuff); - return ProcScreenSaverSetAttributes (client); -} - -static int -SProcScreenSaverUnsetAttributes (ClientPtr client) -{ - REQUEST(xScreenSaverUnsetAttributesReq); - int n; - - swaps (&stuff->length, n); - REQUEST_SIZE_MATCH(xScreenSaverUnsetAttributesReq); - swapl (&stuff->drawable, n); - return ProcScreenSaverUnsetAttributes (client); -} - -static int -SProcScreenSaverSuspend (ClientPtr client) -{ - int n; - REQUEST(xScreenSaverSuspendReq); - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH(xScreenSaverSuspendReq); - swapl(&stuff->suspend, n); - return ProcScreenSaverSuspend (client); -} - -static DISPATCH_PROC((*SwappedVector[])) = { - SProcScreenSaverQueryVersion, - SProcScreenSaverQueryInfo, - SProcScreenSaverSelectInput, - SProcScreenSaverSetAttributes, - SProcScreenSaverUnsetAttributes, - SProcScreenSaverSuspend, -}; - -static int -SProcScreenSaverDispatch (ClientPtr client) -{ - REQUEST(xReq); - - if (stuff->data < NUM_REQUESTS) - return (*SwappedVector[stuff->data])(client); - return BadRequest; -} +/* + * +Copyright (c) 1992 X Consortium + +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 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 +X CONSORTIUM 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 X Consortium 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 X Consortium. + * + * Author: Keith Packard, MIT X Consortium + */ + + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include +#include "misc.h" +#include "os.h" +#include "windowstr.h" +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "extnsionst.h" +#include "dixstruct.h" +#include "resource.h" +#include "opaque.h" +#include +#include "gcstruct.h" +#include "cursorstr.h" +#include "colormapst.h" +#include "xace.h" +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" +#endif +#ifdef DPMSExtension +#include +#endif +#include "protocol-versions.h" + +#include + +#include "modinit.h" + +static int ScreenSaverEventBase = 0; + +static DISPATCH_PROC(ProcScreenSaverQueryInfo); +static DISPATCH_PROC(ProcScreenSaverDispatch); +static DISPATCH_PROC(ProcScreenSaverQueryVersion); +static DISPATCH_PROC(ProcScreenSaverSelectInput); +static DISPATCH_PROC(ProcScreenSaverSetAttributes); +static DISPATCH_PROC(ProcScreenSaverUnsetAttributes); +static DISPATCH_PROC(ProcScreenSaverSuspend); +static DISPATCH_PROC(SProcScreenSaverDispatch); +static DISPATCH_PROC(SProcScreenSaverQueryInfo); +static DISPATCH_PROC(SProcScreenSaverQueryVersion); +static DISPATCH_PROC(SProcScreenSaverSelectInput); +static DISPATCH_PROC(SProcScreenSaverSetAttributes); +static DISPATCH_PROC(SProcScreenSaverUnsetAttributes); +static DISPATCH_PROC(SProcScreenSaverSuspend); + +static Bool ScreenSaverHandle ( + ScreenPtr /* pScreen */, + int /* xstate */, + Bool /* force */ + ); + +static Bool +CreateSaverWindow ( + ScreenPtr /* pScreen */ + ); + +static Bool +DestroySaverWindow ( + ScreenPtr /* pScreen */ + ); + +static void +UninstallSaverColormap ( + ScreenPtr /* pScreen */ + ); + +static void +CheckScreenPrivate ( + ScreenPtr /* pScreen */ + ); + +static void SScreenSaverNotifyEvent ( + xScreenSaverNotifyEvent * /* from */, + xScreenSaverNotifyEvent * /* to */ + ); + +static RESTYPE SuspendType; /* resource type for suspension records */ + +typedef struct _ScreenSaverSuspension *ScreenSaverSuspensionPtr; + +/* List of clients that are suspending the screensaver. */ +static ScreenSaverSuspensionPtr suspendingClients = NULL; + +/* + * clientResource is a resource ID that's added when the record is + * allocated, so the record is freed and the screensaver resumed when + * the client disconnects. count is the number of times the client has + * requested the screensaver be suspended. + */ +typedef struct _ScreenSaverSuspension +{ + ScreenSaverSuspensionPtr next; + ClientPtr pClient; + XID clientResource; + int count; +} ScreenSaverSuspensionRec; + +static int ScreenSaverFreeSuspend( + pointer /*value */, + XID /* id */ +); + +/* + * each screen has a list of clients requesting + * ScreenSaverNotify events. Each client has a resource + * for each screen it selects ScreenSaverNotify input for, + * this resource is used to delete the ScreenSaverNotifyRec + * entry from the per-screen queue. + */ + +static RESTYPE SaverEventType; /* resource type for event masks */ + +typedef struct _ScreenSaverEvent *ScreenSaverEventPtr; + +typedef struct _ScreenSaverEvent { + ScreenSaverEventPtr next; + ClientPtr client; + ScreenPtr screen; + XID resource; + CARD32 mask; +} ScreenSaverEventRec; + +static int ScreenSaverFreeEvents( + pointer /* value */, + XID /* id */ +); + +static Bool setEventMask ( + ScreenPtr /* pScreen */, + ClientPtr /* client */, + unsigned long /* mask */ +); + +static unsigned long getEventMask ( + ScreenPtr /* pScreen */, + ClientPtr /* client */ +); + +/* + * when a client sets the screen saver attributes, a resource is + * kept to be freed when the client exits + */ + +static RESTYPE AttrType; /* resource type for attributes */ + +typedef struct _ScreenSaverAttr { + ScreenPtr screen; + ClientPtr client; + XID resource; + short x, y; + unsigned short width, height, borderWidth; + unsigned char class; + unsigned char depth; + VisualID visual; + CursorPtr pCursor; + PixmapPtr pBackgroundPixmap; + PixmapPtr pBorderPixmap; + Colormap colormap; + unsigned long mask; /* no pixmaps or cursors */ + unsigned long *values; +} ScreenSaverAttrRec, *ScreenSaverAttrPtr; + +static int ScreenSaverFreeAttr ( + pointer /* value */, + XID /* id */ +); + +static void FreeAttrs ( + ScreenSaverAttrPtr /* pAttr */ +); + +static void FreeScreenAttr ( + ScreenSaverAttrPtr /* pAttr */ +); + +static void +SendScreenSaverNotify ( + ScreenPtr /* pScreen */, + int /* state */, + Bool /* forced */ +); + +typedef struct _ScreenSaverScreenPrivate { + ScreenSaverEventPtr events; + ScreenSaverAttrPtr attr; + Bool hasWindow; + Colormap installedMap; +} ScreenSaverScreenPrivateRec, *ScreenSaverScreenPrivatePtr; + +static ScreenSaverScreenPrivatePtr +MakeScreenPrivate ( + ScreenPtr /* pScreen */ + ); + +static int ScreenPrivateKeyIndex; +static DevPrivateKey ScreenPrivateKey = &ScreenPrivateKeyIndex; + +#define GetScreenPrivate(s) ((ScreenSaverScreenPrivatePtr) \ + dixLookupPrivate(&(s)->devPrivates, ScreenPrivateKey)) +#define SetScreenPrivate(s,v) \ + dixSetPrivate(&(s)->devPrivates, ScreenPrivateKey, v); +#define SetupScreen(s) ScreenSaverScreenPrivatePtr pPriv = (s ? GetScreenPrivate(s) : NULL) + +#define New(t) (malloc(sizeof (t))) + +/**************** + * ScreenSaverExtensionInit + * + * Called from InitExtensions in main() or from QueryExtension() if the + * extension is dynamically loaded. + * + ****************/ + +void +ScreenSaverExtensionInit(INITARGS) +{ + ExtensionEntry *extEntry; + int i; + ScreenPtr pScreen; + + AttrType = CreateNewResourceType(ScreenSaverFreeAttr, "SaverAttr"); + SaverEventType = CreateNewResourceType(ScreenSaverFreeEvents, + "SaverEvent"); + SuspendType = CreateNewResourceType(ScreenSaverFreeSuspend, + "SaverSuspend"); + + for (i = 0; i < screenInfo.numScreens; i++) + { + pScreen = screenInfo.screens[i]; + SetScreenPrivate (pScreen, NULL); + } + if (AttrType && SaverEventType && SuspendType && + (extEntry = AddExtension(ScreenSaverName, ScreenSaverNumberEvents, 0, + ProcScreenSaverDispatch, SProcScreenSaverDispatch, + NULL, StandardMinorOpcode))) + { + ScreenSaverEventBase = extEntry->eventBase; + EventSwapVector[ScreenSaverEventBase] = (EventSwapPtr) SScreenSaverNotifyEvent; + } +} + +static void +CheckScreenPrivate (ScreenPtr pScreen) +{ + SetupScreen (pScreen); + + if (!pPriv) + return; + if (!pPriv->attr && !pPriv->events && + !pPriv->hasWindow && pPriv->installedMap == None) + { + free(pPriv); + SetScreenPrivate (pScreen, NULL); + savedScreenInfo[pScreen->myNum].ExternalScreenSaver = NULL; + } +} + +static ScreenSaverScreenPrivatePtr +MakeScreenPrivate (ScreenPtr pScreen) +{ + SetupScreen (pScreen); + + if (pPriv) + return pPriv; + pPriv = New (ScreenSaverScreenPrivateRec); + if (!pPriv) + return 0; + pPriv->events = 0; + pPriv->attr = 0; + pPriv->hasWindow = FALSE; + pPriv->installedMap = None; + SetScreenPrivate (pScreen, pPriv); + savedScreenInfo[pScreen->myNum].ExternalScreenSaver = ScreenSaverHandle; + return pPriv; +} + +static unsigned long +getEventMask (ScreenPtr pScreen, ClientPtr client) +{ + SetupScreen(pScreen); + ScreenSaverEventPtr pEv; + + if (!pPriv) + return 0; + for (pEv = pPriv->events; pEv; pEv = pEv->next) + if (pEv->client == client) + return pEv->mask; + return 0; +} + +static Bool +setEventMask (ScreenPtr pScreen, ClientPtr client, unsigned long mask) +{ + SetupScreen(pScreen); + ScreenSaverEventPtr pEv, *pPrev; + + if (getEventMask (pScreen, client) == mask) + return TRUE; + if (!pPriv) + { + pPriv = MakeScreenPrivate (pScreen); + if (!pPriv) + return FALSE; + } + for (pPrev = &pPriv->events; (pEv = *pPrev) != 0; pPrev = &pEv->next) + if (pEv->client == client) + break; + if (mask == 0) + { + FreeResource (pEv->resource, SaverEventType); + *pPrev = pEv->next; + free(pEv); + CheckScreenPrivate (pScreen); + } + else + { + if (!pEv) + { + pEv = New (ScreenSaverEventRec); + if (!pEv) + { + CheckScreenPrivate (pScreen); + return FALSE; + } + *pPrev = pEv; + pEv->next = NULL; + pEv->client = client; + pEv->screen = pScreen; + pEv->resource = FakeClientID (client->index); + if (!AddResource (pEv->resource, SaverEventType, (pointer) pEv)) + return FALSE; + } + pEv->mask = mask; + } + return TRUE; +} + +static void +FreeAttrs (ScreenSaverAttrPtr pAttr) +{ + PixmapPtr pPixmap; + CursorPtr pCursor; + + if ((pPixmap = pAttr->pBackgroundPixmap) != 0) + (*pPixmap->drawable.pScreen->DestroyPixmap)(pPixmap); + if ((pPixmap = pAttr->pBorderPixmap) != 0) + (*pPixmap->drawable.pScreen->DestroyPixmap)(pPixmap); + if ((pCursor = pAttr->pCursor) != 0) + FreeCursor (pCursor, (Cursor) 0); +} + +static void +FreeScreenAttr (ScreenSaverAttrPtr pAttr) +{ + FreeAttrs (pAttr); + free(pAttr->values); + free(pAttr); +} + +static int +ScreenSaverFreeEvents (pointer value, XID id) +{ + ScreenSaverEventPtr pOld = (ScreenSaverEventPtr)value; + ScreenPtr pScreen = pOld->screen; + SetupScreen (pScreen); + ScreenSaverEventPtr pEv, *pPrev; + + if (!pPriv) + return TRUE; + for (pPrev = &pPriv->events; (pEv = *pPrev) != 0; pPrev = &pEv->next) + if (pEv == pOld) + break; + if (!pEv) + return TRUE; + *pPrev = pEv->next; + free(pEv); + CheckScreenPrivate (pScreen); + return TRUE; +} + +static int +ScreenSaverFreeAttr (pointer value, XID id) +{ + ScreenSaverAttrPtr pOldAttr = (ScreenSaverAttrPtr)value; + ScreenPtr pScreen = pOldAttr->screen; + SetupScreen (pScreen); + + if (!pPriv) + return TRUE; + if (pPriv->attr != pOldAttr) + return TRUE; + FreeScreenAttr (pOldAttr); + pPriv->attr = NULL; + if (pPriv->hasWindow) + { + dixSaveScreens (serverClient, SCREEN_SAVER_FORCER, ScreenSaverReset); + dixSaveScreens (serverClient, SCREEN_SAVER_FORCER, ScreenSaverActive); + } + CheckScreenPrivate (pScreen); + return TRUE; +} + +static int +ScreenSaverFreeSuspend (pointer value, XID id) +{ + ScreenSaverSuspensionPtr data = (ScreenSaverSuspensionPtr) value; + ScreenSaverSuspensionPtr *prev, this; + + /* Unlink and free the suspension record for the client */ + for (prev = &suspendingClients; (this = *prev); prev = &this->next) + { + if (this == data) + { + *prev = this->next; + free(this); + break; + } + } + + /* Reenable the screensaver if this was the last client suspending it. */ + if (screenSaverSuspended && suspendingClients == NULL) + { + screenSaverSuspended = FALSE; + + /* The screensaver could be active, since suspending it (by design) + doesn't prevent it from being forceably activated */ +#ifdef DPMSExtension + if (screenIsSaved != SCREEN_SAVER_ON && DPMSPowerLevel == DPMSModeOn) +#else + if (screenIsSaved != SCREEN_SAVER_ON) +#endif + { + UpdateCurrentTimeIf(); + lastDeviceEventTime = currentTime; + SetScreenSaverTimer(); + } + } + + return Success; +} + +static void +SendScreenSaverNotify (ScreenPtr pScreen, int state, Bool forced) +{ + ScreenSaverScreenPrivatePtr pPriv; + ScreenSaverEventPtr pEv; + unsigned long mask; + xScreenSaverNotifyEvent ev; + ClientPtr client; + int kind; + + UpdateCurrentTimeIf (); + mask = ScreenSaverNotifyMask; + if (state == ScreenSaverCycle) + mask = ScreenSaverCycleMask; + pScreen = screenInfo.screens[pScreen->myNum]; + pPriv = GetScreenPrivate(pScreen); + if (!pPriv) + return; + if (pPriv->attr) + kind = ScreenSaverExternal; + else if (ScreenSaverBlanking != DontPreferBlanking) + kind = ScreenSaverBlanked; + else + kind = ScreenSaverInternal; + for (pEv = pPriv->events; pEv; pEv = pEv->next) + { + client = pEv->client; + if (client->clientGone) + continue; + if (!(pEv->mask & mask)) + continue; + ev.type = ScreenSaverNotify + ScreenSaverEventBase; + ev.state = state; + ev.sequenceNumber = client->sequence; + ev.timestamp = currentTime.milliseconds; + ev.root = WindowTable[pScreen->myNum]->drawable.id; + ev.window = savedScreenInfo[pScreen->myNum].wid; + ev.kind = kind; + ev.forced = forced; + WriteEventsToClient (client, 1, (xEvent *) &ev); + } +} + +static void +SScreenSaverNotifyEvent (xScreenSaverNotifyEvent *from, + xScreenSaverNotifyEvent *to) +{ + to->type = from->type; + to->state = from->state; + cpswaps (from->sequenceNumber, to->sequenceNumber); + cpswapl (from->timestamp, to->timestamp); + cpswapl (from->root, to->root); + cpswapl (from->window, to->window); + to->kind = from->kind; + to->forced = from->forced; +} + +static void +UninstallSaverColormap (ScreenPtr pScreen) +{ + SetupScreen(pScreen); + ColormapPtr pCmap; + int rc; + + if (pPriv && pPriv->installedMap != None) + { + rc = dixLookupResourceByType((pointer *)&pCmap, pPriv->installedMap, + RT_COLORMAP, serverClient, + DixUninstallAccess); + if (rc == Success) + (*pCmap->pScreen->UninstallColormap) (pCmap); + pPriv->installedMap = None; + CheckScreenPrivate (pScreen); + } +} + +static Bool +CreateSaverWindow (ScreenPtr pScreen) +{ + SetupScreen (pScreen); + ScreenSaverStuffPtr pSaver; + ScreenSaverAttrPtr pAttr; + WindowPtr pWin; + int result; + unsigned long mask; + Colormap *installedMaps; + int numInstalled; + int i; + Colormap wantMap; + ColormapPtr pCmap; + + pSaver = &savedScreenInfo[pScreen->myNum]; + if (pSaver->pWindow) + { + pSaver->pWindow = NullWindow; + FreeResource (pSaver->wid, RT_NONE); + if (pPriv) + { + UninstallSaverColormap (pScreen); + pPriv->hasWindow = FALSE; + CheckScreenPrivate (pScreen); + } + } + + if (!pPriv || !(pAttr = pPriv->attr)) + return FALSE; + + pPriv->installedMap = None; + + if (GrabInProgress && GrabInProgress != pAttr->client->index) + return FALSE; + + pWin = CreateWindow (pSaver->wid, WindowTable[pScreen->myNum], + pAttr->x, pAttr->y, pAttr->width, pAttr->height, + pAttr->borderWidth, pAttr->class, + pAttr->mask, (XID *)pAttr->values, + pAttr->depth, serverClient, pAttr->visual, + &result); + if (!pWin) + return FALSE; + + if (!AddResource(pWin->drawable.id, RT_WINDOW, pWin)) + return FALSE; + + mask = 0; + if (pAttr->pBackgroundPixmap) + { + pWin->backgroundState = BackgroundPixmap; + pWin->background.pixmap = pAttr->pBackgroundPixmap; + pAttr->pBackgroundPixmap->refcnt++; + mask |= CWBackPixmap; + } + if (pAttr->pBorderPixmap) + { + pWin->borderIsPixel = FALSE; + pWin->border.pixmap = pAttr->pBorderPixmap; + pAttr->pBorderPixmap->refcnt++; + mask |= CWBorderPixmap; + } + if (pAttr->pCursor) + { + if (!pWin->optional) + if (!MakeWindowOptional (pWin)) + { + FreeResource (pWin->drawable.id, RT_NONE); + return FALSE; + } + pAttr->pCursor->refcnt++; + if (pWin->optional->cursor) + FreeCursor (pWin->optional->cursor, (Cursor)0); + pWin->optional->cursor = pAttr->pCursor; + pWin->cursorIsNone = FALSE; + CheckWindowOptionalNeed (pWin); + mask |= CWCursor; + } + if (mask) + (*pScreen->ChangeWindowAttributes) (pWin, mask); + + if (pAttr->colormap != None) + (void) ChangeWindowAttributes (pWin, CWColormap, &pAttr->colormap, + serverClient); + + MapWindow (pWin, serverClient); + + pPriv->hasWindow = TRUE; + pSaver->pWindow = pWin; + + /* check and install our own colormap if it isn't installed now */ + wantMap = wColormap (pWin); + if (wantMap == None) + return TRUE; + installedMaps = malloc(pScreen->maxInstalledCmaps * sizeof (Colormap)); + numInstalled = (*pWin->drawable.pScreen->ListInstalledColormaps) + (pScreen, installedMaps); + for (i = 0; i < numInstalled; i++) + if (installedMaps[i] == wantMap) + break; + + free((char *) installedMaps); + + if (i < numInstalled) + return TRUE; + + result = dixLookupResourceByType((pointer *)&pCmap, wantMap, RT_COLORMAP, + serverClient, DixInstallAccess); + if (result != Success) + return TRUE; + + pPriv->installedMap = wantMap; + + (*pCmap->pScreen->InstallColormap) (pCmap); + + return TRUE; +} + +static Bool +DestroySaverWindow (ScreenPtr pScreen) +{ + SetupScreen(pScreen); + ScreenSaverStuffPtr pSaver; + + if (!pPriv || !pPriv->hasWindow) + return FALSE; + + pSaver = &savedScreenInfo[pScreen->myNum]; + if (pSaver->pWindow) + { + pSaver->pWindow = NullWindow; + FreeResource (pSaver->wid, RT_NONE); + } + pPriv->hasWindow = FALSE; + CheckScreenPrivate (pScreen); + UninstallSaverColormap (pScreen); + return TRUE; +} + +static Bool +ScreenSaverHandle (ScreenPtr pScreen, int xstate, Bool force) +{ + int state = 0; + Bool ret = FALSE; + ScreenSaverScreenPrivatePtr pPriv; + + switch (xstate) + { + case SCREEN_SAVER_ON: + state = ScreenSaverOn; + ret = CreateSaverWindow (pScreen); + break; + case SCREEN_SAVER_OFF: + state = ScreenSaverOff; + ret = DestroySaverWindow (pScreen); + break; + case SCREEN_SAVER_CYCLE: + state = ScreenSaverCycle; + pPriv = GetScreenPrivate (pScreen); + if (pPriv && pPriv->hasWindow) + ret = TRUE; + + } +#ifdef PANORAMIX + if(noPanoramiXExtension || !pScreen->myNum) +#endif + SendScreenSaverNotify (pScreen, state, force); + return ret; +} + +static int +ProcScreenSaverQueryVersion (ClientPtr client) +{ + xScreenSaverQueryVersionReply rep; + int n; + + REQUEST_SIZE_MATCH (xScreenSaverQueryVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = SERVER_SAVER_MAJOR_VERSION; + rep.minorVersion = SERVER_SAVER_MINOR_VERSION; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + } + WriteToClient(client, sizeof (xScreenSaverQueryVersionReply), (char *)&rep); + return Success; +} + +static int +ProcScreenSaverQueryInfo (ClientPtr client) +{ + REQUEST(xScreenSaverQueryInfoReq); + xScreenSaverQueryInfoReply rep; + int n, rc; + ScreenSaverStuffPtr pSaver; + DrawablePtr pDraw; + CARD32 lastInput; + ScreenSaverScreenPrivatePtr pPriv; + + REQUEST_SIZE_MATCH (xScreenSaverQueryInfoReq); + rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0, + DixGetAttrAccess); + if (rc != Success) + return rc; + rc = XaceHook(XACE_SCREENSAVER_ACCESS, client, pDraw->pScreen, + DixGetAttrAccess); + if (rc != Success) + return rc; + + pSaver = &savedScreenInfo[pDraw->pScreen->myNum]; + pPriv = GetScreenPrivate (pDraw->pScreen); + + UpdateCurrentTime (); + lastInput = GetTimeInMillis() - lastDeviceEventTime.milliseconds; + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.window = pSaver->wid; + if (screenIsSaved != SCREEN_SAVER_OFF) + { + rep.state = ScreenSaverOn; + if (ScreenSaverTime) + rep.tilOrSince = lastInput - ScreenSaverTime; + else + rep.tilOrSince = 0; + } + else + { + if (ScreenSaverTime) + { + rep.state = ScreenSaverOff; + if (ScreenSaverTime < lastInput) + rep.tilOrSince = 0; + else + rep.tilOrSince = ScreenSaverTime - lastInput; + } + else + { + rep.state = ScreenSaverDisabled; + rep.tilOrSince = 0; + } + } + rep.idle = lastInput; + rep.eventMask = getEventMask (pDraw->pScreen, client); + if (pPriv && pPriv->attr) + rep.kind = ScreenSaverExternal; + else if (ScreenSaverBlanking != DontPreferBlanking) + rep.kind = ScreenSaverBlanked; + else + rep.kind = ScreenSaverInternal; + if (client->swapped) + { + swaps (&rep.sequenceNumber, n); + swapl (&rep.length, n); + swapl (&rep.window, n); + swapl (&rep.tilOrSince, n); + swapl (&rep.idle, n); + swapl (&rep.eventMask, n); + } + WriteToClient(client, sizeof (xScreenSaverQueryInfoReply), (char *)&rep); + return Success; +} + +static int +ProcScreenSaverSelectInput (ClientPtr client) +{ + REQUEST(xScreenSaverSelectInputReq); + DrawablePtr pDraw; + int rc; + + REQUEST_SIZE_MATCH (xScreenSaverSelectInputReq); + rc = dixLookupDrawable (&pDraw, stuff->drawable, client, 0, + DixGetAttrAccess); + if (rc != Success) + return rc; + + rc = XaceHook(XACE_SCREENSAVER_ACCESS, client, pDraw->pScreen, + DixSetAttrAccess); + if (rc != Success) + return rc; + + if (!setEventMask (pDraw->pScreen, client, stuff->eventMask)) + return BadAlloc; + return Success; +} + +static int +ScreenSaverSetAttributes (ClientPtr client) +{ + REQUEST(xScreenSaverSetAttributesReq); + DrawablePtr pDraw; + WindowPtr pParent; + ScreenPtr pScreen; + ScreenSaverScreenPrivatePtr pPriv = 0; + ScreenSaverAttrPtr pAttr = 0; + int ret, len, class, bw, depth; + unsigned long visual; + int idepth, ivisual; + Bool fOK; + DepthPtr pDepth; + WindowOptPtr ancwopt; + unsigned int *pVlist; + unsigned long *values = 0; + unsigned long tmask, imask; + unsigned long val; + Pixmap pixID; + PixmapPtr pPixmap; + Cursor cursorID; + CursorPtr pCursor; + Colormap cmap; + ColormapPtr pCmap; + + REQUEST_AT_LEAST_SIZE (xScreenSaverSetAttributesReq); + ret = dixLookupDrawable(&pDraw, stuff->drawable, client, 0, + DixGetAttrAccess); + if (ret != Success) + return ret; + pScreen = pDraw->pScreen; + pParent = WindowTable[pScreen->myNum]; + + ret = XaceHook(XACE_SCREENSAVER_ACCESS, client, pScreen, DixSetAttrAccess); + if (ret != Success) + return ret; + + len = stuff->length - bytes_to_int32(sizeof(xScreenSaverSetAttributesReq)); + if (Ones(stuff->mask) != len) + return BadLength; + if (!stuff->width || !stuff->height) + { + client->errorValue = 0; + return BadValue; + } + switch (class = stuff->c_class) + { + case CopyFromParent: + case InputOnly: + case InputOutput: + break; + default: + client->errorValue = class; + return BadValue; + } + bw = stuff->borderWidth; + depth = stuff->depth; + visual = stuff->visualID; + + /* copied directly from CreateWindow */ + + if (class == CopyFromParent) + class = pParent->drawable.class; + + if ((class != InputOutput) && (class != InputOnly)) + { + client->errorValue = class; + return BadValue; + } + + if ((class != InputOnly) && (pParent->drawable.class == InputOnly)) + return BadMatch; + + if ((class == InputOnly) && ((bw != 0) || (depth != 0))) + return BadMatch; + + if ((class == InputOutput) && (depth == 0)) + depth = pParent->drawable.depth; + ancwopt = pParent->optional; + if (!ancwopt) + ancwopt = FindWindowWithOptional(pParent)->optional; + if (visual == CopyFromParent) + visual = ancwopt->visual; + + /* Find out if the depth and visual are acceptable for this Screen */ + if ((visual != ancwopt->visual) || (depth != pParent->drawable.depth)) + { + fOK = FALSE; + for(idepth = 0; idepth < pScreen->numDepths; idepth++) + { + pDepth = (DepthPtr) &pScreen->allowedDepths[idepth]; + if ((depth == pDepth->depth) || (depth == 0)) + { + for (ivisual = 0; ivisual < pDepth->numVids; ivisual++) + { + if (visual == pDepth->vids[ivisual]) + { + fOK = TRUE; + break; + } + } + } + } + if (fOK == FALSE) + return BadMatch; + } + + if (((stuff->mask & (CWBorderPixmap | CWBorderPixel)) == 0) && + (class != InputOnly) && + (depth != pParent->drawable.depth)) + { + return BadMatch; + } + + if (((stuff->mask & CWColormap) == 0) && + (class != InputOnly) && + ((visual != ancwopt->visual) || (ancwopt->colormap == None))) + { + return BadMatch; + } + + /* end of errors from CreateWindow */ + + pPriv = GetScreenPrivate (pScreen); + if (pPriv && pPriv->attr) + { + if (pPriv->attr->client != client) + return BadAccess; + } + if (!pPriv) + { + pPriv = MakeScreenPrivate (pScreen); + if (!pPriv) + return FALSE; + } + pAttr = New (ScreenSaverAttrRec); + if (!pAttr) + { + ret = BadAlloc; + goto bail; + } + /* over allocate for override redirect */ + values = malloc((len + 1) * sizeof (unsigned long)); + if (!values) + { + ret = BadAlloc; + goto bail; + } + pAttr->screen = pScreen; + pAttr->client = client; + pAttr->x = stuff->x; + pAttr->y = stuff->y; + pAttr->width = stuff->width; + pAttr->height = stuff->height; + pAttr->borderWidth = stuff->borderWidth; + pAttr->class = stuff->c_class; + pAttr->depth = depth; + pAttr->visual = visual; + pAttr->colormap = None; + pAttr->pCursor = NullCursor; + pAttr->pBackgroundPixmap = NullPixmap; + pAttr->pBorderPixmap = NullPixmap; + pAttr->values = values; + /* + * go through the mask, checking the values, + * looking up pixmaps and cursors and hold a reference + * to them. + */ + pAttr->mask = tmask = stuff->mask | CWOverrideRedirect; + pVlist = (unsigned int *) (stuff + 1); + while (tmask) { + imask = lowbit (tmask); + tmask &= ~imask; + switch (imask) + { + case CWBackPixmap: + pixID = (Pixmap )*pVlist; + if (pixID == None) + { + *values++ = None; + } + else if (pixID == ParentRelative) + { + if (depth != pParent->drawable.depth) + { + ret = BadMatch; + goto PatchUp; + } + *values++ = ParentRelative; + } + else + { + ret = dixLookupResourceByType((pointer *)&pPixmap, pixID, RT_PIXMAP, + client, DixReadAccess); + if (ret == Success) + { + if ((pPixmap->drawable.depth != depth) || + (pPixmap->drawable.pScreen != pScreen)) + { + ret = BadMatch; + goto PatchUp; + } + pAttr->pBackgroundPixmap = pPixmap; + pPixmap->refcnt++; + pAttr->mask &= ~CWBackPixmap; + } + else + { + ret = (ret == BadValue) ? BadPixmap : ret; + client->errorValue = pixID; + goto PatchUp; + } + } + break; + case CWBackPixel: + *values++ = (CARD32) *pVlist; + break; + case CWBorderPixmap: + pixID = (Pixmap ) *pVlist; + if (pixID == CopyFromParent) + { + if (depth != pParent->drawable.depth) + { + ret = BadMatch; + goto PatchUp; + } + *values++ = CopyFromParent; + } + else + { + ret = dixLookupResourceByType((pointer *)&pPixmap, pixID, RT_PIXMAP, + client, DixReadAccess); + if (ret == Success) + { + if ((pPixmap->drawable.depth != depth) || + (pPixmap->drawable.pScreen != pScreen)) + { + ret = BadMatch; + goto PatchUp; + } + pAttr->pBorderPixmap = pPixmap; + pPixmap->refcnt++; + pAttr->mask &= ~CWBorderPixmap; + } + else + { + ret = (ret == BadValue) ? BadPixmap : ret; + client->errorValue = pixID; + goto PatchUp; + } + } + break; + case CWBorderPixel: + *values++ = (CARD32) *pVlist; + break; + case CWBitGravity: + val = (CARD8 )*pVlist; + if (val > StaticGravity) + { + ret = BadValue; + client->errorValue = val; + goto PatchUp; + } + *values++ = val; + break; + case CWWinGravity: + val = (CARD8 )*pVlist; + if (val > StaticGravity) + { + ret = BadValue; + client->errorValue = val; + goto PatchUp; + } + *values++ = val; + break; + case CWBackingStore: + val = (CARD8 )*pVlist; + if ((val != NotUseful) && (val != WhenMapped) && (val != Always)) + { + ret = BadValue; + client->errorValue = val; + goto PatchUp; + } + *values++ = val; + break; + case CWBackingPlanes: + *values++ = (CARD32) *pVlist; + break; + case CWBackingPixel: + *values++ = (CARD32) *pVlist; + break; + case CWSaveUnder: + val = (BOOL) *pVlist; + if ((val != xTrue) && (val != xFalse)) + { + ret = BadValue; + client->errorValue = val; + goto PatchUp; + } + *values++ = val; + break; + case CWEventMask: + *values++ = (CARD32) *pVlist; + break; + case CWDontPropagate: + *values++ = (CARD32) *pVlist; + break; + case CWOverrideRedirect: + if (!(stuff->mask & CWOverrideRedirect)) + pVlist--; + else + { + val = (BOOL ) *pVlist; + if ((val != xTrue) && (val != xFalse)) + { + ret = BadValue; + client->errorValue = val; + goto PatchUp; + } + } + *values++ = xTrue; + break; + case CWColormap: + cmap = (Colormap) *pVlist; + ret = dixLookupResourceByType((pointer *)&pCmap, cmap, RT_COLORMAP, + client, DixUseAccess); + if (ret != Success) + { + ret = (ret == BadValue) ? BadColor : ret; + client->errorValue = cmap; + goto PatchUp; + } + if (pCmap->pVisual->vid != visual || pCmap->pScreen != pScreen) + { + ret = BadMatch; + goto PatchUp; + } + pAttr->colormap = cmap; + pAttr->mask &= ~CWColormap; + break; + case CWCursor: + cursorID = (Cursor ) *pVlist; + if ( cursorID == None) + { + *values++ = None; + } + else + { + ret = dixLookupResourceByType((pointer *)&pCursor, cursorID, + RT_CURSOR, client, DixUseAccess); + if (ret != Success) + { + ret = (ret == BadValue) ? BadCursor : ret; + client->errorValue = cursorID; + goto PatchUp; + } + pCursor->refcnt++; + pAttr->pCursor = pCursor; + pAttr->mask &= ~CWCursor; + } + break; + default: + ret = BadValue; + client->errorValue = stuff->mask; + goto PatchUp; + } + pVlist++; + } + if (pPriv->attr) + FreeScreenAttr (pPriv->attr); + pPriv->attr = pAttr; + pAttr->resource = FakeClientID (client->index); + if (!AddResource (pAttr->resource, AttrType, (pointer) pAttr)) + return BadAlloc; + return Success; +PatchUp: + FreeAttrs (pAttr); +bail: + CheckScreenPrivate (pScreen); + if (pAttr) free(pAttr->values); + free(pAttr); + return ret; +} + +static int +ScreenSaverUnsetAttributes (ClientPtr client) +{ + REQUEST(xScreenSaverSetAttributesReq); + DrawablePtr pDraw; + ScreenSaverScreenPrivatePtr pPriv; + int rc; + + REQUEST_SIZE_MATCH (xScreenSaverUnsetAttributesReq); + rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0, + DixGetAttrAccess); + if (rc != Success) + return rc; + pPriv = GetScreenPrivate (pDraw->pScreen); + if (pPriv && pPriv->attr && pPriv->attr->client == client) + { + FreeResource (pPriv->attr->resource, AttrType); + FreeScreenAttr (pPriv->attr); + pPriv->attr = NULL; + CheckScreenPrivate (pDraw->pScreen); + } + return Success; +} + +static int +ProcScreenSaverSetAttributes (ClientPtr client) +{ +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + REQUEST(xScreenSaverSetAttributesReq); + PanoramiXRes *draw; + PanoramiXRes *backPix = NULL; + PanoramiXRes *bordPix = NULL; + PanoramiXRes *cmap = NULL; + int i, status, len; + int pback_offset = 0, pbord_offset = 0, cmap_offset = 0; + XID orig_visual, tmp; + + REQUEST_AT_LEAST_SIZE (xScreenSaverSetAttributesReq); + + status = dixLookupResourceByClass((pointer *)&draw, stuff->drawable, + XRC_DRAWABLE, client, DixWriteAccess); + if (status != Success) + return (status == BadValue) ? BadDrawable : status; + + len = stuff->length - bytes_to_int32(sizeof(xScreenSaverSetAttributesReq)); + if (Ones(stuff->mask) != len) + return BadLength; + + if((Mask)stuff->mask & CWBackPixmap) { + pback_offset = Ones((Mask)stuff->mask & (CWBackPixmap - 1)); + tmp = *((CARD32 *) &stuff[1] + pback_offset); + if ((tmp != None) && (tmp != ParentRelative)) { + status = dixLookupResourceByType((pointer *)&backPix, tmp, + XRT_PIXMAP, client, + DixReadAccess); + if (status != Success) + return (status == BadValue) ? BadPixmap : status; + } + } + + if ((Mask)stuff->mask & CWBorderPixmap) { + pbord_offset = Ones((Mask)stuff->mask & (CWBorderPixmap - 1)); + tmp = *((CARD32 *) &stuff[1] + pbord_offset); + if (tmp != CopyFromParent) { + status = dixLookupResourceByType((pointer *)&bordPix, tmp, + XRT_PIXMAP, client, + DixReadAccess); + if (status != Success) + return (status == BadValue) ? BadPixmap : status; + } + } + + if ((Mask)stuff->mask & CWColormap) { + cmap_offset = Ones((Mask)stuff->mask & (CWColormap - 1)); + tmp = *((CARD32 *) &stuff[1] + cmap_offset); + if ((tmp != CopyFromParent) && (tmp != None)) { + status = dixLookupResourceByType((pointer *)&cmap, tmp, + XRT_COLORMAP, client, + DixReadAccess); + if (status != Success) + return (status == BadValue) ? BadColor : status; + } + } + + orig_visual = stuff->visualID; + + FOR_NSCREENS_BACKWARD(i) { + stuff->drawable = draw->info[i].id; + if (backPix) + *((CARD32 *) &stuff[1] + pback_offset) = backPix->info[i].id; + if (bordPix) + *((CARD32 *) &stuff[1] + pbord_offset) = bordPix->info[i].id; + if (cmap) + *((CARD32 *) &stuff[1] + cmap_offset) = cmap->info[i].id; + + if (orig_visual != CopyFromParent) + stuff->visualID = PanoramiXTranslateVisualID(i, orig_visual); + + status = ScreenSaverSetAttributes(client); + } + + return status; + } +#endif + + return ScreenSaverSetAttributes(client); +} + +static int +ProcScreenSaverUnsetAttributes (ClientPtr client) +{ +#ifdef PANORAMIX + if(!noPanoramiXExtension) { + REQUEST(xScreenSaverUnsetAttributesReq); + PanoramiXRes *draw; + int rc, i; + + rc = dixLookupResourceByClass((pointer *)&draw, stuff->drawable, + XRC_DRAWABLE, client, DixWriteAccess); + if (rc != Success) + return (rc == BadValue) ? BadDrawable : rc; + + for(i = PanoramiXNumScreens - 1; i > 0; i--) { + stuff->drawable = draw->info[i].id; + ScreenSaverUnsetAttributes(client); + } + + stuff->drawable = draw->info[0].id; + } +#endif + + return ScreenSaverUnsetAttributes(client); +} + +static int +ProcScreenSaverSuspend (ClientPtr client) +{ + ScreenSaverSuspensionPtr *prev, this; + + REQUEST(xScreenSaverSuspendReq); + REQUEST_SIZE_MATCH(xScreenSaverSuspendReq); + + /* Check if this client is suspending the screensaver */ + for (prev = &suspendingClients; (this = *prev); prev = &this->next) + if (this->pClient == client) + break; + + if (this) + { + if (stuff->suspend == TRUE) + this->count++; + else if (--this->count == 0) + FreeResource (this->clientResource, RT_NONE); + + return Success; + } + + /* If we get to this point, this client isn't suspending the screensaver */ + if (stuff->suspend == FALSE) + return Success; + + /* + * Allocate a suspension record for the client, and stop the screensaver + * if it isn't already suspended by another client. We attach a resource ID + * to the record, so the screensaver will be reenabled and the record freed + * if the client disconnects without reenabling it first. + */ + this = malloc(sizeof (ScreenSaverSuspensionRec)); + + if (!this) + return BadAlloc; + + this->next = NULL; + this->pClient = client; + this->count = 1; + this->clientResource = FakeClientID (client->index); + + if (!AddResource (this->clientResource, SuspendType, (pointer) this)) + { + free(this); + return BadAlloc; + } + + *prev = this; + if (!screenSaverSuspended) + { + screenSaverSuspended = TRUE; + FreeScreenSaverTimer(); + } + + return Success; +} + +static DISPATCH_PROC((*NormalVector[])) = { + ProcScreenSaverQueryVersion, + ProcScreenSaverQueryInfo, + ProcScreenSaverSelectInput, + ProcScreenSaverSetAttributes, + ProcScreenSaverUnsetAttributes, + ProcScreenSaverSuspend, +}; + +#define NUM_REQUESTS ((sizeof NormalVector) / (sizeof NormalVector[0])) + +static int +ProcScreenSaverDispatch (ClientPtr client) +{ + REQUEST(xReq); + + if (stuff->data < NUM_REQUESTS) + return (*NormalVector[stuff->data])(client); + return BadRequest; +} + +static int +SProcScreenSaverQueryVersion (ClientPtr client) +{ + REQUEST(xScreenSaverQueryVersionReq); + int n; + + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH(xScreenSaverQueryVersionReq); + return ProcScreenSaverQueryVersion (client); +} + +static int +SProcScreenSaverQueryInfo (ClientPtr client) +{ + REQUEST(xScreenSaverQueryInfoReq); + int n; + + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH(xScreenSaverQueryInfoReq); + swapl (&stuff->drawable, n); + return ProcScreenSaverQueryInfo (client); +} + +static int +SProcScreenSaverSelectInput (ClientPtr client) +{ + REQUEST(xScreenSaverSelectInputReq); + int n; + + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH(xScreenSaverSelectInputReq); + swapl (&stuff->drawable, n); + swapl (&stuff->eventMask, n); + return ProcScreenSaverSelectInput (client); +} + +static int +SProcScreenSaverSetAttributes (ClientPtr client) +{ + REQUEST(xScreenSaverSetAttributesReq); + int n; + + swaps (&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xScreenSaverSetAttributesReq); + swapl (&stuff->drawable, n); + swaps (&stuff->x, n); + swaps (&stuff->y, n); + swaps (&stuff->width, n); + swaps (&stuff->height, n); + swaps (&stuff->borderWidth, n); + swapl (&stuff->visualID, n); + swapl (&stuff->mask, n); + SwapRestL(stuff); + return ProcScreenSaverSetAttributes (client); +} + +static int +SProcScreenSaverUnsetAttributes (ClientPtr client) +{ + REQUEST(xScreenSaverUnsetAttributesReq); + int n; + + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH(xScreenSaverUnsetAttributesReq); + swapl (&stuff->drawable, n); + return ProcScreenSaverUnsetAttributes (client); +} + +static int +SProcScreenSaverSuspend (ClientPtr client) +{ + int n; + REQUEST(xScreenSaverSuspendReq); + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xScreenSaverSuspendReq); + swapl(&stuff->suspend, n); + return ProcScreenSaverSuspend (client); +} + +static DISPATCH_PROC((*SwappedVector[])) = { + SProcScreenSaverQueryVersion, + SProcScreenSaverQueryInfo, + SProcScreenSaverSelectInput, + SProcScreenSaverSetAttributes, + SProcScreenSaverUnsetAttributes, + SProcScreenSaverSuspend, +}; + +static int +SProcScreenSaverDispatch (ClientPtr client) +{ + REQUEST(xReq); + + if (stuff->data < NUM_REQUESTS) + return (*SwappedVector[stuff->data])(client); + return BadRequest; +} diff --git a/xorg-server/Xext/security.c b/xorg-server/Xext/security.c index af8d2052f..289f9597d 100644 --- a/xorg-server/Xext/security.c +++ b/xorg-server/Xext/security.c @@ -1,1154 +1,1151 @@ -/* - -Copyright 1996, 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. - -*/ - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include "scrnintstr.h" -#include "inputstr.h" -#include "windowstr.h" -#include "propertyst.h" -#include "colormapst.h" -#include "privates.h" -#include "registry.h" -#include "xacestr.h" -#include "securitysrv.h" -#include -#include "modinit.h" -#include "protocol-versions.h" - -/* Extension stuff */ -static int SecurityErrorBase; /* first Security error number */ -static int SecurityEventBase; /* first Security event number */ - -RESTYPE SecurityAuthorizationResType; /* resource type for authorizations */ -static RESTYPE RTEventClient; - -static CallbackListPtr SecurityValidateGroupCallback = NULL; - -/* Private state record */ -static int stateKeyIndex; -static DevPrivateKey stateKey = &stateKeyIndex; - -/* This is what we store as client security state */ -typedef struct { - int haveState; - unsigned int trustLevel; - XID authId; -} SecurityStateRec; - -/* Extensions that untrusted clients shouldn't have access to */ -static char *SecurityTrustedExtensions[] = { - "XC-MISC", - "BIG-REQUESTS", - "XpExtension", - NULL -}; - -/* - * Access modes that untrusted clients are allowed on trusted objects. - */ -static const Mask SecurityResourceMask = - DixGetAttrAccess | DixReceiveAccess | DixListPropAccess | - DixGetPropAccess | DixListAccess; -static const Mask SecurityWindowExtraMask = DixRemoveAccess; -static const Mask SecurityRootWindowExtraMask = - DixReceiveAccess | DixSendAccess | DixAddAccess | DixRemoveAccess; -static const Mask SecurityDeviceMask = - DixGetAttrAccess | DixReceiveAccess | DixGetFocusAccess | - DixGrabAccess | DixSetAttrAccess | DixUseAccess; -static const Mask SecurityServerMask = DixGetAttrAccess | DixGrabAccess; -static const Mask SecurityClientMask = DixGetAttrAccess; - - -/* SecurityAudit - * - * Arguments: - * format is the formatting string to be used to interpret the - * remaining arguments. - * - * Returns: nothing. - * - * Side Effects: - * Writes the message to the log file if security logging is on. - */ - -static void -SecurityAudit(char *format, ...) -{ - va_list args; - - if (auditTrailLevel < SECURITY_AUDIT_LEVEL) - return; - va_start(args, format); - VAuditF(format, args); - va_end(args); -} /* SecurityAudit */ - -/* - * Performs a Security permission check. - */ -static int -SecurityDoCheck(SecurityStateRec *subj, SecurityStateRec *obj, - Mask requested, Mask allowed) -{ - if (!subj->haveState || !obj->haveState) - return Success; - if (subj->trustLevel == XSecurityClientTrusted) - return Success; - if (obj->trustLevel != XSecurityClientTrusted) - return Success; - if ((requested | allowed) == allowed) - return Success; - - return BadAccess; -} - -/* - * Labels initial server objects. - */ -static void -SecurityLabelInitial(void) -{ - SecurityStateRec *state; - - /* Do the serverClient */ - state = dixLookupPrivate(&serverClient->devPrivates, stateKey); - state->trustLevel = XSecurityClientTrusted; - state->haveState = TRUE; -} - -/* - * Looks up a request name - */ -static _X_INLINE const char * -SecurityLookupRequestName(ClientPtr client) -{ - int major = ((xReq *)client->requestBuffer)->reqType; - int minor = MinorOpcodeOfRequest(client); - return LookupRequestName(major, minor); -} - - -#define rClient(obj) (clients[CLIENT_ID((obj)->resource)]) - -/* SecurityDeleteAuthorization - * - * Arguments: - * value is the authorization to delete. - * id is its resource ID. - * - * Returns: Success. - * - * Side Effects: - * Frees everything associated with the authorization. - */ - -static int -SecurityDeleteAuthorization( - pointer value, - XID id) -{ - SecurityAuthorizationPtr pAuth = (SecurityAuthorizationPtr)value; - unsigned short name_len, data_len; - char *name, *data; - int status; - int i; - OtherClientsPtr pEventClient; - - /* Remove the auth using the os layer auth manager */ - - status = AuthorizationFromID(pAuth->id, &name_len, &name, - &data_len, &data); - assert(status); - status = RemoveAuthorization(name_len, name, data_len, data); - assert(status); - (void)status; - - /* free the auth timer if there is one */ - - if (pAuth->timer) TimerFree(pAuth->timer); - - /* send revoke events */ - - while ((pEventClient = pAuth->eventClients)) - { - /* send revocation event event */ - ClientPtr client = rClient(pEventClient); - - if (!client->clientGone) - { - xSecurityAuthorizationRevokedEvent are; - are.type = SecurityEventBase + XSecurityAuthorizationRevoked; - are.sequenceNumber = client->sequence; - are.authId = pAuth->id; - WriteEventsToClient(client, 1, (xEvent *)&are); - } - FreeResource(pEventClient->resource, RT_NONE); - } - - /* kill all clients using this auth */ - - for (i = 1; idevPrivates, stateKey); - if (state->haveState && state->authId == pAuth->id) - CloseDownClient(clients[i]); - } - - SecurityAudit("revoked authorization ID %d\n", pAuth->id); - xfree(pAuth); - return Success; - -} /* SecurityDeleteAuthorization */ - - -/* resource delete function for RTEventClient */ -static int -SecurityDeleteAuthorizationEventClient( - pointer value, - XID id) -{ - OtherClientsPtr pEventClient, prev = NULL; - SecurityAuthorizationPtr pAuth = (SecurityAuthorizationPtr)value; - - for (pEventClient = pAuth->eventClients; - pEventClient; - pEventClient = pEventClient->next) - { - if (pEventClient->resource == id) - { - if (prev) - prev->next = pEventClient->next; - else - pAuth->eventClients = pEventClient->next; - xfree(pEventClient); - return(Success); - } - prev = pEventClient; - } - /*NOTREACHED*/ - return -1; /* make compiler happy */ -} /* SecurityDeleteAuthorizationEventClient */ - - -/* SecurityComputeAuthorizationTimeout - * - * Arguments: - * pAuth is the authorization for which we are computing the timeout - * seconds is the number of seconds we want to wait - * - * Returns: - * the number of milliseconds that the auth timer should be set to - * - * Side Effects: - * Sets pAuth->secondsRemaining to any "overflow" amount of time - * that didn't fit in 32 bits worth of milliseconds - */ - -static CARD32 -SecurityComputeAuthorizationTimeout( - SecurityAuthorizationPtr pAuth, - unsigned int seconds) -{ - /* maxSecs is the number of full seconds that can be expressed in - * 32 bits worth of milliseconds - */ - CARD32 maxSecs = (CARD32)(~0) / (CARD32)MILLI_PER_SECOND; - - if (seconds > maxSecs) - { /* only come here if we want to wait more than 49 days */ - pAuth->secondsRemaining = seconds - maxSecs; - return maxSecs * MILLI_PER_SECOND; - } - else - { /* by far the common case */ - pAuth->secondsRemaining = 0; - return seconds * MILLI_PER_SECOND; - } -} /* SecurityStartAuthorizationTimer */ - -/* SecurityAuthorizationExpired - * - * This function is passed as an argument to TimerSet and gets called from - * the timer manager in the os layer when its time is up. - * - * Arguments: - * timer is the timer for this authorization. - * time is the current time. - * pval is the authorization whose time is up. - * - * Returns: - * A new time delay in milliseconds if the timer should wait some - * more, else zero. - * - * Side Effects: - * Frees the authorization resource if the timeout period is really - * over, otherwise recomputes pAuth->secondsRemaining. - */ - -static CARD32 -SecurityAuthorizationExpired( - OsTimerPtr timer, - CARD32 time, - pointer pval) -{ - SecurityAuthorizationPtr pAuth = (SecurityAuthorizationPtr)pval; - - assert(pAuth->timer == timer); - - if (pAuth->secondsRemaining) - { - return SecurityComputeAuthorizationTimeout(pAuth, - pAuth->secondsRemaining); - } - else - { - FreeResource(pAuth->id, RT_NONE); - return 0; - } -} /* SecurityAuthorizationExpired */ - -/* SecurityStartAuthorizationTimer - * - * Arguments: - * pAuth is the authorization whose timer should be started. - * - * Returns: nothing. - * - * Side Effects: - * A timer is started, set to expire after the timeout period for - * this authorization. When it expires, the function - * SecurityAuthorizationExpired will be called. - */ - -static void -SecurityStartAuthorizationTimer( - SecurityAuthorizationPtr pAuth) -{ - pAuth->timer = TimerSet(pAuth->timer, 0, - SecurityComputeAuthorizationTimeout(pAuth, pAuth->timeout), - SecurityAuthorizationExpired, pAuth); -} /* SecurityStartAuthorizationTimer */ - - -/* Proc functions all take a client argument, execute the request in - * client->requestBuffer, and return a protocol error status. - */ - -static int -ProcSecurityQueryVersion( - ClientPtr client) -{ - /* REQUEST(xSecurityQueryVersionReq); */ - xSecurityQueryVersionReply rep; - - REQUEST_SIZE_MATCH(xSecurityQueryVersionReq); - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.length = 0; - rep.majorVersion = SERVER_SECURITY_MAJOR_VERSION; - rep.minorVersion = SERVER_SECURITY_MINOR_VERSION; - if(client->swapped) - { - char n; - swaps(&rep.sequenceNumber, n); - swaps(&rep.majorVersion, n); - swaps(&rep.minorVersion, n); - } - (void)WriteToClient(client, SIZEOF(xSecurityQueryVersionReply), - (char *)&rep); - return (client->noClientException); -} /* ProcSecurityQueryVersion */ - - -static int -SecurityEventSelectForAuthorization( - SecurityAuthorizationPtr pAuth, - ClientPtr client, - Mask mask) -{ - OtherClients *pEventClient; - - for (pEventClient = pAuth->eventClients; - pEventClient; - pEventClient = pEventClient->next) - { - if (SameClient(pEventClient, client)) - { - if (mask == 0) - FreeResource(pEventClient->resource, RT_NONE); - else - pEventClient->mask = mask; - return Success; - } - } - - pEventClient = xalloc(sizeof(OtherClients)); - if (!pEventClient) - return BadAlloc; - pEventClient->mask = mask; - pEventClient->resource = FakeClientID(client->index); - pEventClient->next = pAuth->eventClients; - if (!AddResource(pEventClient->resource, RTEventClient, - (pointer)pAuth)) - { - xfree(pEventClient); - return BadAlloc; - } - pAuth->eventClients = pEventClient; - - return Success; -} /* SecurityEventSelectForAuthorization */ - - -static int -ProcSecurityGenerateAuthorization( - ClientPtr client) -{ - REQUEST(xSecurityGenerateAuthorizationReq); - int len; /* request length in CARD32s*/ - Bool removeAuth = FALSE; /* if bailout, call RemoveAuthorization? */ - SecurityAuthorizationPtr pAuth = NULL; /* auth we are creating */ - int err; /* error to return from this function */ - XID authId; /* authorization ID assigned by os layer */ - xSecurityGenerateAuthorizationReply rep; /* reply struct */ - unsigned int trustLevel; /* trust level of new auth */ - XID group; /* group of new auth */ - CARD32 timeout; /* timeout of new auth */ - CARD32 *values; /* list of supplied attributes */ - char *protoname; /* auth proto name sent in request */ - char *protodata; /* auth proto data sent in request */ - unsigned int authdata_len; /* # bytes of generated auth data */ - char *pAuthdata; /* generated auth data */ - Mask eventMask; /* what events on this auth does client want */ - - /* check request length */ - - REQUEST_AT_LEAST_SIZE(xSecurityGenerateAuthorizationReq); - len = bytes_to_int32(SIZEOF(xSecurityGenerateAuthorizationReq)); - len += bytes_to_int32(stuff->nbytesAuthProto); - len += bytes_to_int32(stuff->nbytesAuthData); - values = ((CARD32 *)stuff) + len; - len += Ones(stuff->valueMask); - if (client->req_len != len) - return BadLength; - - /* check valuemask */ - if (stuff->valueMask & ~XSecurityAllAuthorizationAttributes) - { - client->errorValue = stuff->valueMask; - return BadValue; - } - - /* check timeout */ - timeout = 60; - if (stuff->valueMask & XSecurityTimeout) - { - timeout = *values++; - } - - /* check trustLevel */ - trustLevel = XSecurityClientUntrusted; - if (stuff->valueMask & XSecurityTrustLevel) - { - trustLevel = *values++; - if (trustLevel != XSecurityClientTrusted && - trustLevel != XSecurityClientUntrusted) - { - client->errorValue = trustLevel; - return BadValue; - } - } - - /* check group */ - group = None; - if (stuff->valueMask & XSecurityGroup) - { - group = *values++; - if (SecurityValidateGroupCallback) - { - SecurityValidateGroupInfoRec vgi; - vgi.group = group; - vgi.valid = FALSE; - CallCallbacks(&SecurityValidateGroupCallback, (pointer)&vgi); - - /* if nobody said they recognized it, it's an error */ - - if (!vgi.valid) - { - client->errorValue = group; - return BadValue; - } - } - } - - /* check event mask */ - eventMask = 0; - if (stuff->valueMask & XSecurityEventMask) - { - eventMask = *values++; - if (eventMask & ~XSecurityAllEventMasks) - { - client->errorValue = eventMask; - return BadValue; - } - } - - protoname = (char *)&stuff[1]; - protodata = protoname + bytes_to_int32(stuff->nbytesAuthProto); - - /* call os layer to generate the authorization */ - - authId = GenerateAuthorization(stuff->nbytesAuthProto, protoname, - stuff->nbytesAuthData, protodata, - &authdata_len, &pAuthdata); - if ((XID) ~0L == authId) - { - err = SecurityErrorBase + XSecurityBadAuthorizationProtocol; - goto bailout; - } - - /* now that we've added the auth, remember to remove it if we have to - * abort the request for some reason (like allocation failure) - */ - removeAuth = TRUE; - - /* associate additional information with this auth ID */ - - pAuth = xalloc(sizeof(SecurityAuthorizationRec)); - if (!pAuth) - { - err = BadAlloc; - goto bailout; - } - - /* fill in the auth fields */ - - pAuth->id = authId; - pAuth->timeout = timeout; - pAuth->group = group; - pAuth->trustLevel = trustLevel; - pAuth->refcnt = 0; /* the auth was just created; nobody's using it yet */ - pAuth->secondsRemaining = 0; - pAuth->timer = NULL; - pAuth->eventClients = NULL; - - /* handle event selection */ - if (eventMask) - { - err = SecurityEventSelectForAuthorization(pAuth, client, eventMask); - if (err != Success) - goto bailout; - } - - if (!AddResource(authId, SecurityAuthorizationResType, pAuth)) - { - err = BadAlloc; - goto bailout; - } - - /* start the timer ticking */ - - if (pAuth->timeout != 0) - SecurityStartAuthorizationTimer(pAuth); - - /* tell client the auth id and data */ - - rep.type = X_Reply; - rep.length = bytes_to_int32(authdata_len); - rep.sequenceNumber = client->sequence; - rep.authId = authId; - rep.dataLength = authdata_len; - - if (client->swapped) - { - char n; - swapl(&rep.length, n); - swaps(&rep.sequenceNumber, n); - swapl(&rep.authId, n); - swaps(&rep.dataLength, n); - } - - WriteToClient(client, SIZEOF(xSecurityGenerateAuthorizationReply), - (char *)&rep); - WriteToClient(client, authdata_len, pAuthdata); - - SecurityAudit("client %d generated authorization %d trust %d timeout %d group %d events %d\n", - client->index, pAuth->id, pAuth->trustLevel, pAuth->timeout, - pAuth->group, eventMask); - - /* the request succeeded; don't call RemoveAuthorization or free pAuth */ - - removeAuth = FALSE; - pAuth = NULL; - err = client->noClientException; - -bailout: - if (removeAuth) - RemoveAuthorization(stuff->nbytesAuthProto, protoname, - authdata_len, pAuthdata); - if (pAuth) xfree(pAuth); - return err; - -} /* ProcSecurityGenerateAuthorization */ - -static int -ProcSecurityRevokeAuthorization( - ClientPtr client) -{ - REQUEST(xSecurityRevokeAuthorizationReq); - SecurityAuthorizationPtr pAuth; - int rc; - - REQUEST_SIZE_MATCH(xSecurityRevokeAuthorizationReq); - - rc = dixLookupResourceByType((pointer *)&pAuth, stuff->authId, - SecurityAuthorizationResType, client, - DixDestroyAccess); - if (rc != Success) - return (rc == BadValue) ? - SecurityErrorBase + XSecurityBadAuthorization : rc; - - FreeResource(stuff->authId, RT_NONE); - return Success; -} /* ProcSecurityRevokeAuthorization */ - - -static int -ProcSecurityDispatch( - ClientPtr client) -{ - REQUEST(xReq); - - switch (stuff->data) - { - case X_SecurityQueryVersion: - return ProcSecurityQueryVersion(client); - case X_SecurityGenerateAuthorization: - return ProcSecurityGenerateAuthorization(client); - case X_SecurityRevokeAuthorization: - return ProcSecurityRevokeAuthorization(client); - default: - return BadRequest; - } -} /* ProcSecurityDispatch */ - -static int -SProcSecurityQueryVersion( - ClientPtr client) -{ - REQUEST(xSecurityQueryVersionReq); - char n; - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH(xSecurityQueryVersionReq); - swaps(&stuff->majorVersion, n); - swaps(&stuff->minorVersion,n); - return ProcSecurityQueryVersion(client); -} /* SProcSecurityQueryVersion */ - - -static int -SProcSecurityGenerateAuthorization( - ClientPtr client) -{ - REQUEST(xSecurityGenerateAuthorizationReq); - char n; - CARD32 *values; - unsigned long nvalues; - int values_offset; - - swaps(&stuff->length, n); - REQUEST_AT_LEAST_SIZE(xSecurityGenerateAuthorizationReq); - swaps(&stuff->nbytesAuthProto, n); - swaps(&stuff->nbytesAuthData, n); - swapl(&stuff->valueMask, n); - values_offset = bytes_to_int32(stuff->nbytesAuthProto) + - bytes_to_int32(stuff->nbytesAuthData); - if (values_offset > - stuff->length - bytes_to_int32(sz_xSecurityGenerateAuthorizationReq)) - return BadLength; - values = (CARD32 *)(&stuff[1]) + values_offset; - nvalues = (((CARD32 *)stuff) + stuff->length) - values; - SwapLongs(values, nvalues); - return ProcSecurityGenerateAuthorization(client); -} /* SProcSecurityGenerateAuthorization */ - - -static int -SProcSecurityRevokeAuthorization( - ClientPtr client) -{ - REQUEST(xSecurityRevokeAuthorizationReq); - char n; - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH(xSecurityRevokeAuthorizationReq); - swapl(&stuff->authId, n); - return ProcSecurityRevokeAuthorization(client); -} /* SProcSecurityRevokeAuthorization */ - - -static int -SProcSecurityDispatch( - ClientPtr client) -{ - REQUEST(xReq); - - switch (stuff->data) - { - case X_SecurityQueryVersion: - return SProcSecurityQueryVersion(client); - case X_SecurityGenerateAuthorization: - return SProcSecurityGenerateAuthorization(client); - case X_SecurityRevokeAuthorization: - return SProcSecurityRevokeAuthorization(client); - default: - return BadRequest; - } -} /* SProcSecurityDispatch */ - -static void -SwapSecurityAuthorizationRevokedEvent( - xSecurityAuthorizationRevokedEvent *from, - xSecurityAuthorizationRevokedEvent *to) -{ - to->type = from->type; - to->detail = from->detail; - cpswaps(from->sequenceNumber, to->sequenceNumber); - cpswapl(from->authId, to->authId); -} - -/* SecurityCheckDeviceAccess - * - * Arguments: - * client is the client attempting to access a device. - * dev is the device being accessed. - * fromRequest is TRUE if the device access is a direct result of - * the client executing some request and FALSE if it is a - * result of the server trying to send an event (e.g. KeymapNotify) - * to the client. - * Returns: - * TRUE if the device access should be allowed, else FALSE. - * - * Side Effects: - * An audit message is generated if access is denied. - */ - -static void -SecurityDevice(CallbackListPtr *pcbl, pointer unused, pointer calldata) -{ - XaceDeviceAccessRec *rec = calldata; - SecurityStateRec *subj, *obj; - Mask requested = rec->access_mode; - Mask allowed = SecurityDeviceMask; - - subj = dixLookupPrivate(&rec->client->devPrivates, stateKey); - obj = dixLookupPrivate(&serverClient->devPrivates, stateKey); - - if (rec->dev != inputInfo.keyboard) - /* this extension only supports the core keyboard */ - allowed = requested; - - if (SecurityDoCheck(subj, obj, requested, allowed) != Success) { - SecurityAudit("Security denied client %d keyboard access on request " - "%s\n", rec->client->index, - SecurityLookupRequestName(rec->client)); - rec->status = BadAccess; - } -} - -/* SecurityResource - * - * This function gets plugged into client->CheckAccess and is called from - * SecurityLookupIDByType/Class to determine if the client can access the - * resource. - * - * Arguments: - * client is the client doing the resource access. - * id is the resource id. - * rtype is its type or class. - * access_mode represents the intended use of the resource; see - * resource.h. - * res is a pointer to the resource structure for this resource. - * - * Returns: - * If access is granted, the value of rval that was passed in, else FALSE. - * - * Side Effects: - * Disallowed resource accesses are audited. - */ - -static void -SecurityResource(CallbackListPtr *pcbl, pointer unused, pointer calldata) -{ - XaceResourceAccessRec *rec = calldata; - SecurityStateRec *subj, *obj; - int cid = CLIENT_ID(rec->id); - Mask requested = rec->access_mode; - Mask allowed = SecurityResourceMask; - - subj = dixLookupPrivate(&rec->client->devPrivates, stateKey); - obj = dixLookupPrivate(&clients[cid]->devPrivates, stateKey); - - /* disable background None for untrusted windows */ - if ((requested & DixCreateAccess) && (rec->rtype == RT_WINDOW)) - if (subj->haveState && subj->trustLevel != XSecurityClientTrusted) - ((WindowPtr)rec->res)->forcedBG = TRUE; - - /* additional permissions for specific resource types */ - if (rec->rtype == RT_WINDOW) - allowed |= SecurityWindowExtraMask; - - /* special checks for server-owned resources */ - if (cid == 0) { - if (rec->rtype & RC_DRAWABLE) - /* additional operations allowed on root windows */ - allowed |= SecurityRootWindowExtraMask; - - else if (rec->rtype == RT_COLORMAP) - /* allow access to default colormaps */ - allowed = requested; - - else - /* allow read access to other server-owned resources */ - allowed |= DixReadAccess; - } - - if (SecurityDoCheck(subj, obj, requested, allowed) == Success) - return; - - SecurityAudit("Security: denied client %d access %x to resource 0x%x " - "of client %d on request %s\n", rec->client->index, - requested, rec->id, cid, - SecurityLookupRequestName(rec->client)); - rec->status = BadAccess; /* deny access */ -} - - -static void -SecurityExtension(CallbackListPtr *pcbl, pointer unused, pointer calldata) -{ - XaceExtAccessRec *rec = calldata; - SecurityStateRec *subj; - int i = 0; - - subj = dixLookupPrivate(&rec->client->devPrivates, stateKey); - - if (subj->haveState && subj->trustLevel == XSecurityClientTrusted) - return; - - while (SecurityTrustedExtensions[i]) - if (!strcmp(SecurityTrustedExtensions[i++], rec->ext->name)) - return; - - SecurityAudit("Security: denied client %d access to extension " - "%s on request %s\n", - rec->client->index, rec->ext->name, - SecurityLookupRequestName(rec->client)); - rec->status = BadAccess; -} - -static void -SecurityServer(CallbackListPtr *pcbl, pointer unused, pointer calldata) -{ - XaceServerAccessRec *rec = calldata; - SecurityStateRec *subj, *obj; - Mask requested = rec->access_mode; - Mask allowed = SecurityServerMask; - - subj = dixLookupPrivate(&rec->client->devPrivates, stateKey); - obj = dixLookupPrivate(&serverClient->devPrivates, stateKey); - - if (SecurityDoCheck(subj, obj, requested, allowed) != Success) { - SecurityAudit("Security: denied client %d access to server " - "configuration request %s\n", rec->client->index, - SecurityLookupRequestName(rec->client)); - rec->status = BadAccess; - } -} - -static void -SecurityClient(CallbackListPtr *pcbl, pointer unused, pointer calldata) -{ - XaceClientAccessRec *rec = calldata; - SecurityStateRec *subj, *obj; - Mask requested = rec->access_mode; - Mask allowed = SecurityClientMask; - - subj = dixLookupPrivate(&rec->client->devPrivates, stateKey); - obj = dixLookupPrivate(&rec->target->devPrivates, stateKey); - - if (SecurityDoCheck(subj, obj, requested, allowed) != Success) { - SecurityAudit("Security: denied client %d access to client %d on " - "request %s\n", rec->client->index, rec->target->index, - SecurityLookupRequestName(rec->client)); - rec->status = BadAccess; - } -} - -static void -SecurityProperty(CallbackListPtr *pcbl, pointer unused, pointer calldata) -{ - XacePropertyAccessRec *rec = calldata; - SecurityStateRec *subj, *obj; - ATOM name = (*rec->ppProp)->propertyName; - Mask requested = rec->access_mode; - Mask allowed = SecurityResourceMask | DixReadAccess; - - subj = dixLookupPrivate(&rec->client->devPrivates, stateKey); - obj = dixLookupPrivate(&wClient(rec->pWin)->devPrivates, stateKey); - - if (SecurityDoCheck(subj, obj, requested, allowed) != Success) { - SecurityAudit("Security: denied client %d access to property %s " - "(atom 0x%x) window 0x%x of client %d on request %s\n", - rec->client->index, NameForAtom(name), name, - rec->pWin->drawable.id, wClient(rec->pWin)->index, - SecurityLookupRequestName(rec->client)); - rec->status = BadAccess; - } -} - -static void -SecuritySend(CallbackListPtr *pcbl, pointer unused, pointer calldata) -{ - XaceSendAccessRec *rec = calldata; - SecurityStateRec *subj, *obj; - - if (rec->client) { - int i; - - subj = dixLookupPrivate(&rec->client->devPrivates, stateKey); - obj = dixLookupPrivate(&wClient(rec->pWin)->devPrivates, stateKey); - - if (SecurityDoCheck(subj, obj, DixSendAccess, 0) == Success) - return; - - for (i = 0; i < rec->count; i++) - if (rec->events[i].u.u.type != UnmapNotify && - rec->events[i].u.u.type != ConfigureRequest && - rec->events[i].u.u.type != ClientMessage) { - - SecurityAudit("Security: denied client %d from sending event " - "of type %s to window 0x%x of client %d\n", - rec->client->index, - LookupEventName(rec->events[i].u.u.type), - rec->pWin->drawable.id, - wClient(rec->pWin)->index); - rec->status = BadAccess; - return; - } - } -} - -static void -SecurityReceive(CallbackListPtr *pcbl, pointer unused, pointer calldata) -{ - XaceReceiveAccessRec *rec = calldata; - SecurityStateRec *subj, *obj; - - subj = dixLookupPrivate(&rec->client->devPrivates, stateKey); - obj = dixLookupPrivate(&wClient(rec->pWin)->devPrivates, stateKey); - - if (SecurityDoCheck(subj, obj, DixReceiveAccess, 0) == Success) - return; - - SecurityAudit("Security: denied client %d from receiving an event " - "sent to window 0x%x of client %d\n", - rec->client->index, rec->pWin->drawable.id, - wClient(rec->pWin)->index); - rec->status = BadAccess; -} - -/* SecurityClientStateCallback - * - * Arguments: - * pcbl is &ClientStateCallback. - * nullata is NULL. - * calldata is a pointer to a NewClientInfoRec (include/dixstruct.h) - * which contains information about client state changes. - * - * Returns: nothing. - * - * Side Effects: - * - * If a new client is connecting, its authorization ID is copied to - * client->authID. If this is a generated authorization, its reference - * count is bumped, its timer is cancelled if it was running, and its - * trustlevel is copied to TRUSTLEVEL(client). - * - * If a client is disconnecting and the client was using a generated - * authorization, the authorization's reference count is decremented, and - * if it is now zero, the timer for this authorization is started. - */ - -static void -SecurityClientState(CallbackListPtr *pcbl, pointer unused, pointer calldata) -{ - NewClientInfoRec *pci = calldata; - SecurityStateRec *state; - SecurityAuthorizationPtr pAuth; - int rc; - - state = dixLookupPrivate(&pci->client->devPrivates, stateKey); - - switch (pci->client->clientState) { - case ClientStateInitial: - state->trustLevel = XSecurityClientTrusted; - state->authId = None; - state->haveState = TRUE; - break; - - case ClientStateRunning: - state->authId = AuthorizationIDOfClient(pci->client); - rc = dixLookupResourceByType((pointer *)&pAuth, state->authId, - SecurityAuthorizationResType, serverClient, - DixGetAttrAccess); - if (rc == Success) { - /* it is a generated authorization */ - pAuth->refcnt++; - if (pAuth->refcnt == 1 && pAuth->timer) - TimerCancel(pAuth->timer); - - state->trustLevel = pAuth->trustLevel; - } - break; - - case ClientStateGone: - case ClientStateRetained: - rc = dixLookupResourceByType((pointer *)&pAuth, state->authId, - SecurityAuthorizationResType, serverClient, - DixGetAttrAccess); - if (rc == Success) { - /* it is a generated authorization */ - pAuth->refcnt--; - if (pAuth->refcnt == 0) - SecurityStartAuthorizationTimer(pAuth); - } - break; - - default: - break; - } -} - -/* SecurityResetProc - * - * Arguments: - * extEntry is the extension information for the security extension. - * - * Returns: nothing. - * - * Side Effects: - * Performs any cleanup needed by Security at server shutdown time. - */ - -static void -SecurityResetProc( - ExtensionEntry *extEntry) -{ - /* Unregister callbacks */ - DeleteCallback(&ClientStateCallback, SecurityClientState, NULL); - - XaceDeleteCallback(XACE_EXT_DISPATCH, SecurityExtension, NULL); - XaceDeleteCallback(XACE_RESOURCE_ACCESS, SecurityResource, NULL); - XaceDeleteCallback(XACE_DEVICE_ACCESS, SecurityDevice, NULL); - XaceDeleteCallback(XACE_PROPERTY_ACCESS, SecurityProperty, NULL); - XaceDeleteCallback(XACE_SEND_ACCESS, SecuritySend, NULL); - XaceDeleteCallback(XACE_RECEIVE_ACCESS, SecurityReceive, NULL); - XaceDeleteCallback(XACE_CLIENT_ACCESS, SecurityClient, NULL); - XaceDeleteCallback(XACE_EXT_ACCESS, SecurityExtension, NULL); - XaceDeleteCallback(XACE_SERVER_ACCESS, SecurityServer, NULL); -} - - -/* SecurityExtensionInit - * - * Arguments: none. - * - * Returns: nothing. - * - * Side Effects: - * Enables the Security extension if possible. - */ - -void -SecurityExtensionInit(INITARGS) -{ - ExtensionEntry *extEntry; - int ret = TRUE; - - SecurityAuthorizationResType = - CreateNewResourceType(SecurityDeleteAuthorization, - "SecurityAuthorization"); - - RTEventClient = - CreateNewResourceType(SecurityDeleteAuthorizationEventClient, - "SecurityEventClient"); - - if (!SecurityAuthorizationResType || !RTEventClient) - return; - - RTEventClient |= RC_NEVERRETAIN; - - /* Allocate the private storage */ - if (!dixRequestPrivate(stateKey, sizeof(SecurityStateRec))) - FatalError("SecurityExtensionSetup: Can't allocate client private.\n"); - - /* Register callbacks */ - ret &= AddCallback(&ClientStateCallback, SecurityClientState, NULL); - - ret &= XaceRegisterCallback(XACE_EXT_DISPATCH, SecurityExtension, NULL); - ret &= XaceRegisterCallback(XACE_RESOURCE_ACCESS, SecurityResource, NULL); - ret &= XaceRegisterCallback(XACE_DEVICE_ACCESS, SecurityDevice, NULL); - ret &= XaceRegisterCallback(XACE_PROPERTY_ACCESS, SecurityProperty, NULL); - ret &= XaceRegisterCallback(XACE_SEND_ACCESS, SecuritySend, NULL); - ret &= XaceRegisterCallback(XACE_RECEIVE_ACCESS, SecurityReceive, NULL); - ret &= XaceRegisterCallback(XACE_CLIENT_ACCESS, SecurityClient, NULL); - ret &= XaceRegisterCallback(XACE_EXT_ACCESS, SecurityExtension, NULL); - ret &= XaceRegisterCallback(XACE_SERVER_ACCESS, SecurityServer, NULL); - - if (!ret) - FatalError("SecurityExtensionSetup: Failed to register callbacks\n"); - - /* Add extension to server */ - extEntry = AddExtension(SECURITY_EXTENSION_NAME, - XSecurityNumberEvents, XSecurityNumberErrors, - ProcSecurityDispatch, SProcSecurityDispatch, - SecurityResetProc, StandardMinorOpcode); - - SecurityErrorBase = extEntry->errorBase; - SecurityEventBase = extEntry->eventBase; - - EventSwapVector[SecurityEventBase + XSecurityAuthorizationRevoked] = - (EventSwapPtr)SwapSecurityAuthorizationRevokedEvent; - - /* Label objects that were created before we could register ourself */ - SecurityLabelInitial(); -} +/* + +Copyright 1996, 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. + +*/ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "scrnintstr.h" +#include "inputstr.h" +#include "windowstr.h" +#include "propertyst.h" +#include "colormapst.h" +#include "privates.h" +#include "registry.h" +#include "xacestr.h" +#include "securitysrv.h" +#include +#include "modinit.h" +#include "protocol-versions.h" + +/* Extension stuff */ +static int SecurityErrorBase; /* first Security error number */ +static int SecurityEventBase; /* first Security event number */ + +RESTYPE SecurityAuthorizationResType; /* resource type for authorizations */ +static RESTYPE RTEventClient; + +static CallbackListPtr SecurityValidateGroupCallback = NULL; + +/* Private state record */ +static int stateKeyIndex; +static DevPrivateKey stateKey = &stateKeyIndex; + +/* This is what we store as client security state */ +typedef struct { + int haveState; + unsigned int trustLevel; + XID authId; +} SecurityStateRec; + +/* Extensions that untrusted clients shouldn't have access to */ +static char *SecurityTrustedExtensions[] = { + "XC-MISC", + "BIG-REQUESTS", + "XpExtension", + NULL +}; + +/* + * Access modes that untrusted clients are allowed on trusted objects. + */ +static const Mask SecurityResourceMask = + DixGetAttrAccess | DixReceiveAccess | DixListPropAccess | + DixGetPropAccess | DixListAccess; +static const Mask SecurityWindowExtraMask = DixRemoveAccess; +static const Mask SecurityRootWindowExtraMask = + DixReceiveAccess | DixSendAccess | DixAddAccess | DixRemoveAccess; +static const Mask SecurityDeviceMask = + DixGetAttrAccess | DixReceiveAccess | DixGetFocusAccess | + DixGrabAccess | DixSetAttrAccess | DixUseAccess; +static const Mask SecurityServerMask = DixGetAttrAccess | DixGrabAccess; +static const Mask SecurityClientMask = DixGetAttrAccess; + + +/* SecurityAudit + * + * Arguments: + * format is the formatting string to be used to interpret the + * remaining arguments. + * + * Returns: nothing. + * + * Side Effects: + * Writes the message to the log file if security logging is on. + */ + +static void +SecurityAudit(char *format, ...) +{ + va_list args; + + if (auditTrailLevel < SECURITY_AUDIT_LEVEL) + return; + va_start(args, format); + VAuditF(format, args); + va_end(args); +} /* SecurityAudit */ + +/* + * Performs a Security permission check. + */ +static int +SecurityDoCheck(SecurityStateRec *subj, SecurityStateRec *obj, + Mask requested, Mask allowed) +{ + if (!subj->haveState || !obj->haveState) + return Success; + if (subj->trustLevel == XSecurityClientTrusted) + return Success; + if (obj->trustLevel != XSecurityClientTrusted) + return Success; + if ((requested | allowed) == allowed) + return Success; + + return BadAccess; +} + +/* + * Labels initial server objects. + */ +static void +SecurityLabelInitial(void) +{ + SecurityStateRec *state; + + /* Do the serverClient */ + state = dixLookupPrivate(&serverClient->devPrivates, stateKey); + state->trustLevel = XSecurityClientTrusted; + state->haveState = TRUE; +} + +/* + * Looks up a request name + */ +static _X_INLINE const char * +SecurityLookupRequestName(ClientPtr client) +{ + int major = ((xReq *)client->requestBuffer)->reqType; + int minor = MinorOpcodeOfRequest(client); + return LookupRequestName(major, minor); +} + + +#define rClient(obj) (clients[CLIENT_ID((obj)->resource)]) + +/* SecurityDeleteAuthorization + * + * Arguments: + * value is the authorization to delete. + * id is its resource ID. + * + * Returns: Success. + * + * Side Effects: + * Frees everything associated with the authorization. + */ + +static int +SecurityDeleteAuthorization( + pointer value, + XID id) +{ + SecurityAuthorizationPtr pAuth = (SecurityAuthorizationPtr)value; + unsigned short name_len, data_len; + char *name, *data; + int status; + int i; + OtherClientsPtr pEventClient; + + /* Remove the auth using the os layer auth manager */ + + status = AuthorizationFromID(pAuth->id, &name_len, &name, + &data_len, &data); + assert(status); + status = RemoveAuthorization(name_len, name, data_len, data); + assert(status); + (void)status; + + /* free the auth timer if there is one */ + + if (pAuth->timer) TimerFree(pAuth->timer); + + /* send revoke events */ + + while ((pEventClient = pAuth->eventClients)) + { + /* send revocation event event */ + ClientPtr client = rClient(pEventClient); + + if (!client->clientGone) + { + xSecurityAuthorizationRevokedEvent are; + are.type = SecurityEventBase + XSecurityAuthorizationRevoked; + are.sequenceNumber = client->sequence; + are.authId = pAuth->id; + WriteEventsToClient(client, 1, (xEvent *)&are); + } + FreeResource(pEventClient->resource, RT_NONE); + } + + /* kill all clients using this auth */ + + for (i = 1; idevPrivates, stateKey); + if (state->haveState && state->authId == pAuth->id) + CloseDownClient(clients[i]); + } + + SecurityAudit("revoked authorization ID %d\n", pAuth->id); + free(pAuth); + return Success; + +} /* SecurityDeleteAuthorization */ + + +/* resource delete function for RTEventClient */ +static int +SecurityDeleteAuthorizationEventClient( + pointer value, + XID id) +{ + OtherClientsPtr pEventClient, prev = NULL; + SecurityAuthorizationPtr pAuth = (SecurityAuthorizationPtr)value; + + for (pEventClient = pAuth->eventClients; + pEventClient; + pEventClient = pEventClient->next) + { + if (pEventClient->resource == id) + { + if (prev) + prev->next = pEventClient->next; + else + pAuth->eventClients = pEventClient->next; + free(pEventClient); + return(Success); + } + prev = pEventClient; + } + /*NOTREACHED*/ + return -1; /* make compiler happy */ +} /* SecurityDeleteAuthorizationEventClient */ + + +/* SecurityComputeAuthorizationTimeout + * + * Arguments: + * pAuth is the authorization for which we are computing the timeout + * seconds is the number of seconds we want to wait + * + * Returns: + * the number of milliseconds that the auth timer should be set to + * + * Side Effects: + * Sets pAuth->secondsRemaining to any "overflow" amount of time + * that didn't fit in 32 bits worth of milliseconds + */ + +static CARD32 +SecurityComputeAuthorizationTimeout( + SecurityAuthorizationPtr pAuth, + unsigned int seconds) +{ + /* maxSecs is the number of full seconds that can be expressed in + * 32 bits worth of milliseconds + */ + CARD32 maxSecs = (CARD32)(~0) / (CARD32)MILLI_PER_SECOND; + + if (seconds > maxSecs) + { /* only come here if we want to wait more than 49 days */ + pAuth->secondsRemaining = seconds - maxSecs; + return maxSecs * MILLI_PER_SECOND; + } + else + { /* by far the common case */ + pAuth->secondsRemaining = 0; + return seconds * MILLI_PER_SECOND; + } +} /* SecurityStartAuthorizationTimer */ + +/* SecurityAuthorizationExpired + * + * This function is passed as an argument to TimerSet and gets called from + * the timer manager in the os layer when its time is up. + * + * Arguments: + * timer is the timer for this authorization. + * time is the current time. + * pval is the authorization whose time is up. + * + * Returns: + * A new time delay in milliseconds if the timer should wait some + * more, else zero. + * + * Side Effects: + * Frees the authorization resource if the timeout period is really + * over, otherwise recomputes pAuth->secondsRemaining. + */ + +static CARD32 +SecurityAuthorizationExpired( + OsTimerPtr timer, + CARD32 time, + pointer pval) +{ + SecurityAuthorizationPtr pAuth = (SecurityAuthorizationPtr)pval; + + assert(pAuth->timer == timer); + + if (pAuth->secondsRemaining) + { + return SecurityComputeAuthorizationTimeout(pAuth, + pAuth->secondsRemaining); + } + else + { + FreeResource(pAuth->id, RT_NONE); + return 0; + } +} /* SecurityAuthorizationExpired */ + +/* SecurityStartAuthorizationTimer + * + * Arguments: + * pAuth is the authorization whose timer should be started. + * + * Returns: nothing. + * + * Side Effects: + * A timer is started, set to expire after the timeout period for + * this authorization. When it expires, the function + * SecurityAuthorizationExpired will be called. + */ + +static void +SecurityStartAuthorizationTimer( + SecurityAuthorizationPtr pAuth) +{ + pAuth->timer = TimerSet(pAuth->timer, 0, + SecurityComputeAuthorizationTimeout(pAuth, pAuth->timeout), + SecurityAuthorizationExpired, pAuth); +} /* SecurityStartAuthorizationTimer */ + + +/* Proc functions all take a client argument, execute the request in + * client->requestBuffer, and return a protocol error status. + */ + +static int +ProcSecurityQueryVersion( + ClientPtr client) +{ + /* REQUEST(xSecurityQueryVersionReq); */ + xSecurityQueryVersionReply rep; + + REQUEST_SIZE_MATCH(xSecurityQueryVersionReq); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.majorVersion = SERVER_SECURITY_MAJOR_VERSION; + rep.minorVersion = SERVER_SECURITY_MINOR_VERSION; + if(client->swapped) + { + char n; + swaps(&rep.sequenceNumber, n); + swaps(&rep.majorVersion, n); + swaps(&rep.minorVersion, n); + } + (void)WriteToClient(client, SIZEOF(xSecurityQueryVersionReply), + (char *)&rep); + return Success; +} /* ProcSecurityQueryVersion */ + + +static int +SecurityEventSelectForAuthorization( + SecurityAuthorizationPtr pAuth, + ClientPtr client, + Mask mask) +{ + OtherClients *pEventClient; + + for (pEventClient = pAuth->eventClients; + pEventClient; + pEventClient = pEventClient->next) + { + if (SameClient(pEventClient, client)) + { + if (mask == 0) + FreeResource(pEventClient->resource, RT_NONE); + else + pEventClient->mask = mask; + return Success; + } + } + + pEventClient = malloc(sizeof(OtherClients)); + if (!pEventClient) + return BadAlloc; + pEventClient->mask = mask; + pEventClient->resource = FakeClientID(client->index); + pEventClient->next = pAuth->eventClients; + if (!AddResource(pEventClient->resource, RTEventClient, + (pointer)pAuth)) + { + free(pEventClient); + return BadAlloc; + } + pAuth->eventClients = pEventClient; + + return Success; +} /* SecurityEventSelectForAuthorization */ + + +static int +ProcSecurityGenerateAuthorization( + ClientPtr client) +{ + REQUEST(xSecurityGenerateAuthorizationReq); + int len; /* request length in CARD32s*/ + Bool removeAuth = FALSE; /* if bailout, call RemoveAuthorization? */ + SecurityAuthorizationPtr pAuth = NULL; /* auth we are creating */ + int err; /* error to return from this function */ + XID authId; /* authorization ID assigned by os layer */ + xSecurityGenerateAuthorizationReply rep; /* reply struct */ + unsigned int trustLevel; /* trust level of new auth */ + XID group; /* group of new auth */ + CARD32 timeout; /* timeout of new auth */ + CARD32 *values; /* list of supplied attributes */ + char *protoname; /* auth proto name sent in request */ + char *protodata; /* auth proto data sent in request */ + unsigned int authdata_len; /* # bytes of generated auth data */ + char *pAuthdata; /* generated auth data */ + Mask eventMask; /* what events on this auth does client want */ + + /* check request length */ + + REQUEST_AT_LEAST_SIZE(xSecurityGenerateAuthorizationReq); + len = bytes_to_int32(SIZEOF(xSecurityGenerateAuthorizationReq)); + len += bytes_to_int32(stuff->nbytesAuthProto); + len += bytes_to_int32(stuff->nbytesAuthData); + values = ((CARD32 *)stuff) + len; + len += Ones(stuff->valueMask); + if (client->req_len != len) + return BadLength; + + /* check valuemask */ + if (stuff->valueMask & ~XSecurityAllAuthorizationAttributes) + { + client->errorValue = stuff->valueMask; + return BadValue; + } + + /* check timeout */ + timeout = 60; + if (stuff->valueMask & XSecurityTimeout) + { + timeout = *values++; + } + + /* check trustLevel */ + trustLevel = XSecurityClientUntrusted; + if (stuff->valueMask & XSecurityTrustLevel) + { + trustLevel = *values++; + if (trustLevel != XSecurityClientTrusted && + trustLevel != XSecurityClientUntrusted) + { + client->errorValue = trustLevel; + return BadValue; + } + } + + /* check group */ + group = None; + if (stuff->valueMask & XSecurityGroup) + { + group = *values++; + if (SecurityValidateGroupCallback) + { + SecurityValidateGroupInfoRec vgi; + vgi.group = group; + vgi.valid = FALSE; + CallCallbacks(&SecurityValidateGroupCallback, (pointer)&vgi); + + /* if nobody said they recognized it, it's an error */ + + if (!vgi.valid) + { + client->errorValue = group; + return BadValue; + } + } + } + + /* check event mask */ + eventMask = 0; + if (stuff->valueMask & XSecurityEventMask) + { + eventMask = *values++; + if (eventMask & ~XSecurityAllEventMasks) + { + client->errorValue = eventMask; + return BadValue; + } + } + + protoname = (char *)&stuff[1]; + protodata = protoname + bytes_to_int32(stuff->nbytesAuthProto); + + /* call os layer to generate the authorization */ + + authId = GenerateAuthorization(stuff->nbytesAuthProto, protoname, + stuff->nbytesAuthData, protodata, + &authdata_len, &pAuthdata); + if ((XID) ~0L == authId) + { + err = SecurityErrorBase + XSecurityBadAuthorizationProtocol; + goto bailout; + } + + /* now that we've added the auth, remember to remove it if we have to + * abort the request for some reason (like allocation failure) + */ + removeAuth = TRUE; + + /* associate additional information with this auth ID */ + + pAuth = malloc(sizeof(SecurityAuthorizationRec)); + if (!pAuth) + { + err = BadAlloc; + goto bailout; + } + + /* fill in the auth fields */ + + pAuth->id = authId; + pAuth->timeout = timeout; + pAuth->group = group; + pAuth->trustLevel = trustLevel; + pAuth->refcnt = 0; /* the auth was just created; nobody's using it yet */ + pAuth->secondsRemaining = 0; + pAuth->timer = NULL; + pAuth->eventClients = NULL; + + /* handle event selection */ + if (eventMask) + { + err = SecurityEventSelectForAuthorization(pAuth, client, eventMask); + if (err != Success) + goto bailout; + } + + if (!AddResource(authId, SecurityAuthorizationResType, pAuth)) + { + err = BadAlloc; + goto bailout; + } + + /* start the timer ticking */ + + if (pAuth->timeout != 0) + SecurityStartAuthorizationTimer(pAuth); + + /* tell client the auth id and data */ + + rep.type = X_Reply; + rep.length = bytes_to_int32(authdata_len); + rep.sequenceNumber = client->sequence; + rep.authId = authId; + rep.dataLength = authdata_len; + + if (client->swapped) + { + char n; + swapl(&rep.length, n); + swaps(&rep.sequenceNumber, n); + swapl(&rep.authId, n); + swaps(&rep.dataLength, n); + } + + WriteToClient(client, SIZEOF(xSecurityGenerateAuthorizationReply), + (char *)&rep); + WriteToClient(client, authdata_len, pAuthdata); + + SecurityAudit("client %d generated authorization %d trust %d timeout %d group %d events %d\n", + client->index, pAuth->id, pAuth->trustLevel, pAuth->timeout, + pAuth->group, eventMask); + + /* the request succeeded; don't call RemoveAuthorization or free pAuth */ + return Success; + +bailout: + if (removeAuth) + RemoveAuthorization(stuff->nbytesAuthProto, protoname, + authdata_len, pAuthdata); + if (pAuth) free(pAuth); + return err; + +} /* ProcSecurityGenerateAuthorization */ + +static int +ProcSecurityRevokeAuthorization( + ClientPtr client) +{ + REQUEST(xSecurityRevokeAuthorizationReq); + SecurityAuthorizationPtr pAuth; + int rc; + + REQUEST_SIZE_MATCH(xSecurityRevokeAuthorizationReq); + + rc = dixLookupResourceByType((pointer *)&pAuth, stuff->authId, + SecurityAuthorizationResType, client, + DixDestroyAccess); + if (rc != Success) + return (rc == BadValue) ? + SecurityErrorBase + XSecurityBadAuthorization : rc; + + FreeResource(stuff->authId, RT_NONE); + return Success; +} /* ProcSecurityRevokeAuthorization */ + + +static int +ProcSecurityDispatch( + ClientPtr client) +{ + REQUEST(xReq); + + switch (stuff->data) + { + case X_SecurityQueryVersion: + return ProcSecurityQueryVersion(client); + case X_SecurityGenerateAuthorization: + return ProcSecurityGenerateAuthorization(client); + case X_SecurityRevokeAuthorization: + return ProcSecurityRevokeAuthorization(client); + default: + return BadRequest; + } +} /* ProcSecurityDispatch */ + +static int +SProcSecurityQueryVersion( + ClientPtr client) +{ + REQUEST(xSecurityQueryVersionReq); + char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xSecurityQueryVersionReq); + swaps(&stuff->majorVersion, n); + swaps(&stuff->minorVersion,n); + return ProcSecurityQueryVersion(client); +} /* SProcSecurityQueryVersion */ + + +static int +SProcSecurityGenerateAuthorization( + ClientPtr client) +{ + REQUEST(xSecurityGenerateAuthorizationReq); + char n; + CARD32 *values; + unsigned long nvalues; + int values_offset; + + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xSecurityGenerateAuthorizationReq); + swaps(&stuff->nbytesAuthProto, n); + swaps(&stuff->nbytesAuthData, n); + swapl(&stuff->valueMask, n); + values_offset = bytes_to_int32(stuff->nbytesAuthProto) + + bytes_to_int32(stuff->nbytesAuthData); + if (values_offset > + stuff->length - bytes_to_int32(sz_xSecurityGenerateAuthorizationReq)) + return BadLength; + values = (CARD32 *)(&stuff[1]) + values_offset; + nvalues = (((CARD32 *)stuff) + stuff->length) - values; + SwapLongs(values, nvalues); + return ProcSecurityGenerateAuthorization(client); +} /* SProcSecurityGenerateAuthorization */ + + +static int +SProcSecurityRevokeAuthorization( + ClientPtr client) +{ + REQUEST(xSecurityRevokeAuthorizationReq); + char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xSecurityRevokeAuthorizationReq); + swapl(&stuff->authId, n); + return ProcSecurityRevokeAuthorization(client); +} /* SProcSecurityRevokeAuthorization */ + + +static int +SProcSecurityDispatch( + ClientPtr client) +{ + REQUEST(xReq); + + switch (stuff->data) + { + case X_SecurityQueryVersion: + return SProcSecurityQueryVersion(client); + case X_SecurityGenerateAuthorization: + return SProcSecurityGenerateAuthorization(client); + case X_SecurityRevokeAuthorization: + return SProcSecurityRevokeAuthorization(client); + default: + return BadRequest; + } +} /* SProcSecurityDispatch */ + +static void +SwapSecurityAuthorizationRevokedEvent( + xSecurityAuthorizationRevokedEvent *from, + xSecurityAuthorizationRevokedEvent *to) +{ + to->type = from->type; + to->detail = from->detail; + cpswaps(from->sequenceNumber, to->sequenceNumber); + cpswapl(from->authId, to->authId); +} + +/* SecurityCheckDeviceAccess + * + * Arguments: + * client is the client attempting to access a device. + * dev is the device being accessed. + * fromRequest is TRUE if the device access is a direct result of + * the client executing some request and FALSE if it is a + * result of the server trying to send an event (e.g. KeymapNotify) + * to the client. + * Returns: + * TRUE if the device access should be allowed, else FALSE. + * + * Side Effects: + * An audit message is generated if access is denied. + */ + +static void +SecurityDevice(CallbackListPtr *pcbl, pointer unused, pointer calldata) +{ + XaceDeviceAccessRec *rec = calldata; + SecurityStateRec *subj, *obj; + Mask requested = rec->access_mode; + Mask allowed = SecurityDeviceMask; + + subj = dixLookupPrivate(&rec->client->devPrivates, stateKey); + obj = dixLookupPrivate(&serverClient->devPrivates, stateKey); + + if (rec->dev != inputInfo.keyboard) + /* this extension only supports the core keyboard */ + allowed = requested; + + if (SecurityDoCheck(subj, obj, requested, allowed) != Success) { + SecurityAudit("Security denied client %d keyboard access on request " + "%s\n", rec->client->index, + SecurityLookupRequestName(rec->client)); + rec->status = BadAccess; + } +} + +/* SecurityResource + * + * This function gets plugged into client->CheckAccess and is called from + * SecurityLookupIDByType/Class to determine if the client can access the + * resource. + * + * Arguments: + * client is the client doing the resource access. + * id is the resource id. + * rtype is its type or class. + * access_mode represents the intended use of the resource; see + * resource.h. + * res is a pointer to the resource structure for this resource. + * + * Returns: + * If access is granted, the value of rval that was passed in, else FALSE. + * + * Side Effects: + * Disallowed resource accesses are audited. + */ + +static void +SecurityResource(CallbackListPtr *pcbl, pointer unused, pointer calldata) +{ + XaceResourceAccessRec *rec = calldata; + SecurityStateRec *subj, *obj; + int cid = CLIENT_ID(rec->id); + Mask requested = rec->access_mode; + Mask allowed = SecurityResourceMask; + + subj = dixLookupPrivate(&rec->client->devPrivates, stateKey); + obj = dixLookupPrivate(&clients[cid]->devPrivates, stateKey); + + /* disable background None for untrusted windows */ + if ((requested & DixCreateAccess) && (rec->rtype == RT_WINDOW)) + if (subj->haveState && subj->trustLevel != XSecurityClientTrusted) + ((WindowPtr)rec->res)->forcedBG = TRUE; + + /* additional permissions for specific resource types */ + if (rec->rtype == RT_WINDOW) + allowed |= SecurityWindowExtraMask; + + /* special checks for server-owned resources */ + if (cid == 0) { + if (rec->rtype & RC_DRAWABLE) + /* additional operations allowed on root windows */ + allowed |= SecurityRootWindowExtraMask; + + else if (rec->rtype == RT_COLORMAP) + /* allow access to default colormaps */ + allowed = requested; + + else + /* allow read access to other server-owned resources */ + allowed |= DixReadAccess; + } + + if (SecurityDoCheck(subj, obj, requested, allowed) == Success) + return; + + SecurityAudit("Security: denied client %d access %x to resource 0x%x " + "of client %d on request %s\n", rec->client->index, + requested, rec->id, cid, + SecurityLookupRequestName(rec->client)); + rec->status = BadAccess; /* deny access */ +} + + +static void +SecurityExtension(CallbackListPtr *pcbl, pointer unused, pointer calldata) +{ + XaceExtAccessRec *rec = calldata; + SecurityStateRec *subj; + int i = 0; + + subj = dixLookupPrivate(&rec->client->devPrivates, stateKey); + + if (subj->haveState && subj->trustLevel == XSecurityClientTrusted) + return; + + while (SecurityTrustedExtensions[i]) + if (!strcmp(SecurityTrustedExtensions[i++], rec->ext->name)) + return; + + SecurityAudit("Security: denied client %d access to extension " + "%s on request %s\n", + rec->client->index, rec->ext->name, + SecurityLookupRequestName(rec->client)); + rec->status = BadAccess; +} + +static void +SecurityServer(CallbackListPtr *pcbl, pointer unused, pointer calldata) +{ + XaceServerAccessRec *rec = calldata; + SecurityStateRec *subj, *obj; + Mask requested = rec->access_mode; + Mask allowed = SecurityServerMask; + + subj = dixLookupPrivate(&rec->client->devPrivates, stateKey); + obj = dixLookupPrivate(&serverClient->devPrivates, stateKey); + + if (SecurityDoCheck(subj, obj, requested, allowed) != Success) { + SecurityAudit("Security: denied client %d access to server " + "configuration request %s\n", rec->client->index, + SecurityLookupRequestName(rec->client)); + rec->status = BadAccess; + } +} + +static void +SecurityClient(CallbackListPtr *pcbl, pointer unused, pointer calldata) +{ + XaceClientAccessRec *rec = calldata; + SecurityStateRec *subj, *obj; + Mask requested = rec->access_mode; + Mask allowed = SecurityClientMask; + + subj = dixLookupPrivate(&rec->client->devPrivates, stateKey); + obj = dixLookupPrivate(&rec->target->devPrivates, stateKey); + + if (SecurityDoCheck(subj, obj, requested, allowed) != Success) { + SecurityAudit("Security: denied client %d access to client %d on " + "request %s\n", rec->client->index, rec->target->index, + SecurityLookupRequestName(rec->client)); + rec->status = BadAccess; + } +} + +static void +SecurityProperty(CallbackListPtr *pcbl, pointer unused, pointer calldata) +{ + XacePropertyAccessRec *rec = calldata; + SecurityStateRec *subj, *obj; + ATOM name = (*rec->ppProp)->propertyName; + Mask requested = rec->access_mode; + Mask allowed = SecurityResourceMask | DixReadAccess; + + subj = dixLookupPrivate(&rec->client->devPrivates, stateKey); + obj = dixLookupPrivate(&wClient(rec->pWin)->devPrivates, stateKey); + + if (SecurityDoCheck(subj, obj, requested, allowed) != Success) { + SecurityAudit("Security: denied client %d access to property %s " + "(atom 0x%x) window 0x%x of client %d on request %s\n", + rec->client->index, NameForAtom(name), name, + rec->pWin->drawable.id, wClient(rec->pWin)->index, + SecurityLookupRequestName(rec->client)); + rec->status = BadAccess; + } +} + +static void +SecuritySend(CallbackListPtr *pcbl, pointer unused, pointer calldata) +{ + XaceSendAccessRec *rec = calldata; + SecurityStateRec *subj, *obj; + + if (rec->client) { + int i; + + subj = dixLookupPrivate(&rec->client->devPrivates, stateKey); + obj = dixLookupPrivate(&wClient(rec->pWin)->devPrivates, stateKey); + + if (SecurityDoCheck(subj, obj, DixSendAccess, 0) == Success) + return; + + for (i = 0; i < rec->count; i++) + if (rec->events[i].u.u.type != UnmapNotify && + rec->events[i].u.u.type != ConfigureRequest && + rec->events[i].u.u.type != ClientMessage) { + + SecurityAudit("Security: denied client %d from sending event " + "of type %s to window 0x%x of client %d\n", + rec->client->index, + LookupEventName(rec->events[i].u.u.type), + rec->pWin->drawable.id, + wClient(rec->pWin)->index); + rec->status = BadAccess; + return; + } + } +} + +static void +SecurityReceive(CallbackListPtr *pcbl, pointer unused, pointer calldata) +{ + XaceReceiveAccessRec *rec = calldata; + SecurityStateRec *subj, *obj; + + subj = dixLookupPrivate(&rec->client->devPrivates, stateKey); + obj = dixLookupPrivate(&wClient(rec->pWin)->devPrivates, stateKey); + + if (SecurityDoCheck(subj, obj, DixReceiveAccess, 0) == Success) + return; + + SecurityAudit("Security: denied client %d from receiving an event " + "sent to window 0x%x of client %d\n", + rec->client->index, rec->pWin->drawable.id, + wClient(rec->pWin)->index); + rec->status = BadAccess; +} + +/* SecurityClientStateCallback + * + * Arguments: + * pcbl is &ClientStateCallback. + * nullata is NULL. + * calldata is a pointer to a NewClientInfoRec (include/dixstruct.h) + * which contains information about client state changes. + * + * Returns: nothing. + * + * Side Effects: + * + * If a new client is connecting, its authorization ID is copied to + * client->authID. If this is a generated authorization, its reference + * count is bumped, its timer is cancelled if it was running, and its + * trustlevel is copied to TRUSTLEVEL(client). + * + * If a client is disconnecting and the client was using a generated + * authorization, the authorization's reference count is decremented, and + * if it is now zero, the timer for this authorization is started. + */ + +static void +SecurityClientState(CallbackListPtr *pcbl, pointer unused, pointer calldata) +{ + NewClientInfoRec *pci = calldata; + SecurityStateRec *state; + SecurityAuthorizationPtr pAuth; + int rc; + + state = dixLookupPrivate(&pci->client->devPrivates, stateKey); + + switch (pci->client->clientState) { + case ClientStateInitial: + state->trustLevel = XSecurityClientTrusted; + state->authId = None; + state->haveState = TRUE; + break; + + case ClientStateRunning: + state->authId = AuthorizationIDOfClient(pci->client); + rc = dixLookupResourceByType((pointer *)&pAuth, state->authId, + SecurityAuthorizationResType, serverClient, + DixGetAttrAccess); + if (rc == Success) { + /* it is a generated authorization */ + pAuth->refcnt++; + if (pAuth->refcnt == 1 && pAuth->timer) + TimerCancel(pAuth->timer); + + state->trustLevel = pAuth->trustLevel; + } + break; + + case ClientStateGone: + case ClientStateRetained: + rc = dixLookupResourceByType((pointer *)&pAuth, state->authId, + SecurityAuthorizationResType, serverClient, + DixGetAttrAccess); + if (rc == Success) { + /* it is a generated authorization */ + pAuth->refcnt--; + if (pAuth->refcnt == 0) + SecurityStartAuthorizationTimer(pAuth); + } + break; + + default: + break; + } +} + +/* SecurityResetProc + * + * Arguments: + * extEntry is the extension information for the security extension. + * + * Returns: nothing. + * + * Side Effects: + * Performs any cleanup needed by Security at server shutdown time. + */ + +static void +SecurityResetProc( + ExtensionEntry *extEntry) +{ + /* Unregister callbacks */ + DeleteCallback(&ClientStateCallback, SecurityClientState, NULL); + + XaceDeleteCallback(XACE_EXT_DISPATCH, SecurityExtension, NULL); + XaceDeleteCallback(XACE_RESOURCE_ACCESS, SecurityResource, NULL); + XaceDeleteCallback(XACE_DEVICE_ACCESS, SecurityDevice, NULL); + XaceDeleteCallback(XACE_PROPERTY_ACCESS, SecurityProperty, NULL); + XaceDeleteCallback(XACE_SEND_ACCESS, SecuritySend, NULL); + XaceDeleteCallback(XACE_RECEIVE_ACCESS, SecurityReceive, NULL); + XaceDeleteCallback(XACE_CLIENT_ACCESS, SecurityClient, NULL); + XaceDeleteCallback(XACE_EXT_ACCESS, SecurityExtension, NULL); + XaceDeleteCallback(XACE_SERVER_ACCESS, SecurityServer, NULL); +} + + +/* SecurityExtensionInit + * + * Arguments: none. + * + * Returns: nothing. + * + * Side Effects: + * Enables the Security extension if possible. + */ + +void +SecurityExtensionInit(INITARGS) +{ + ExtensionEntry *extEntry; + int ret = TRUE; + + SecurityAuthorizationResType = + CreateNewResourceType(SecurityDeleteAuthorization, + "SecurityAuthorization"); + + RTEventClient = + CreateNewResourceType(SecurityDeleteAuthorizationEventClient, + "SecurityEventClient"); + + if (!SecurityAuthorizationResType || !RTEventClient) + return; + + RTEventClient |= RC_NEVERRETAIN; + + /* Allocate the private storage */ + if (!dixRequestPrivate(stateKey, sizeof(SecurityStateRec))) + FatalError("SecurityExtensionSetup: Can't allocate client private.\n"); + + /* Register callbacks */ + ret &= AddCallback(&ClientStateCallback, SecurityClientState, NULL); + + ret &= XaceRegisterCallback(XACE_EXT_DISPATCH, SecurityExtension, NULL); + ret &= XaceRegisterCallback(XACE_RESOURCE_ACCESS, SecurityResource, NULL); + ret &= XaceRegisterCallback(XACE_DEVICE_ACCESS, SecurityDevice, NULL); + ret &= XaceRegisterCallback(XACE_PROPERTY_ACCESS, SecurityProperty, NULL); + ret &= XaceRegisterCallback(XACE_SEND_ACCESS, SecuritySend, NULL); + ret &= XaceRegisterCallback(XACE_RECEIVE_ACCESS, SecurityReceive, NULL); + ret &= XaceRegisterCallback(XACE_CLIENT_ACCESS, SecurityClient, NULL); + ret &= XaceRegisterCallback(XACE_EXT_ACCESS, SecurityExtension, NULL); + ret &= XaceRegisterCallback(XACE_SERVER_ACCESS, SecurityServer, NULL); + + if (!ret) + FatalError("SecurityExtensionSetup: Failed to register callbacks\n"); + + /* Add extension to server */ + extEntry = AddExtension(SECURITY_EXTENSION_NAME, + XSecurityNumberEvents, XSecurityNumberErrors, + ProcSecurityDispatch, SProcSecurityDispatch, + SecurityResetProc, StandardMinorOpcode); + + SecurityErrorBase = extEntry->errorBase; + SecurityEventBase = extEntry->eventBase; + + EventSwapVector[SecurityEventBase + XSecurityAuthorizationRevoked] = + (EventSwapPtr)SwapSecurityAuthorizationRevokedEvent; + + /* Label objects that were created before we could register ourself */ + SecurityLabelInitial(); +} diff --git a/xorg-server/Xext/shape.c b/xorg-server/Xext/shape.c index 58b5c23c0..edecc51ed 100644 --- a/xorg-server/Xext/shape.c +++ b/xorg-server/Xext/shape.c @@ -1,1293 +1,1293 @@ -/************************************************************ - -Copyright 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. - -********************************************************/ - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include - -#include -#include -#include "misc.h" -#include "os.h" -#include "windowstr.h" -#include "scrnintstr.h" -#include "pixmapstr.h" -#include "extnsionst.h" -#include "dixstruct.h" -#include "resource.h" -#include "opaque.h" -#include -#include "regionstr.h" -#include "gcstruct.h" -#include "modinit.h" -#include "protocol-versions.h" - -typedef RegionPtr (*CreateDftPtr)( - WindowPtr /* pWin */ - ); - -static int ShapeFreeClient( - pointer /* data */, - XID /* id */ - ); -static int ShapeFreeEvents( - pointer /* data */, - XID /* id */ - ); -static void SShapeNotifyEvent( - xShapeNotifyEvent * /* from */, - xShapeNotifyEvent * /* to */ - ); - -/* SendShapeNotify, CreateBoundingShape and CreateClipShape are used - * externally by the Xfixes extension and are now defined in window.h - */ - -static DISPATCH_PROC(ProcShapeCombine); -static DISPATCH_PROC(ProcShapeDispatch); -static DISPATCH_PROC(ProcShapeGetRectangles); -static DISPATCH_PROC(ProcShapeInputSelected); -static DISPATCH_PROC(ProcShapeMask); -static DISPATCH_PROC(ProcShapeOffset); -static DISPATCH_PROC(ProcShapeQueryExtents); -static DISPATCH_PROC(ProcShapeQueryVersion); -static DISPATCH_PROC(ProcShapeRectangles); -static DISPATCH_PROC(ProcShapeSelectInput); -static DISPATCH_PROC(SProcShapeCombine); -static DISPATCH_PROC(SProcShapeDispatch); -static DISPATCH_PROC(SProcShapeGetRectangles); -static DISPATCH_PROC(SProcShapeInputSelected); -static DISPATCH_PROC(SProcShapeMask); -static DISPATCH_PROC(SProcShapeOffset); -static DISPATCH_PROC(SProcShapeQueryExtents); -static DISPATCH_PROC(SProcShapeQueryVersion); -static DISPATCH_PROC(SProcShapeRectangles); -static DISPATCH_PROC(SProcShapeSelectInput); - -#ifdef PANORAMIX -#include "panoramiX.h" -#include "panoramiXsrv.h" -#endif - -static int ShapeEventBase = 0; -static RESTYPE ClientType, ShapeEventType; /* resource types for event masks */ - -/* - * each window has a list of clients requesting - * ShapeNotify events. Each client has a resource - * for each window it selects ShapeNotify input for, - * this resource is used to delete the ShapeNotifyRec - * entry from the per-window queue. - */ - -typedef struct _ShapeEvent *ShapeEventPtr; - -typedef struct _ShapeEvent { - ShapeEventPtr next; - ClientPtr client; - WindowPtr window; - XID clientResource; -} ShapeEventRec; - -/**************** - * ShapeExtensionInit - * - * Called from InitExtensions in main() or from QueryExtension() if the - * extension is dynamically loaded. - * - ****************/ - -void -ShapeExtensionInit(void) -{ - ExtensionEntry *extEntry; - - ClientType = CreateNewResourceType(ShapeFreeClient, "ShapeClient"); - ShapeEventType = CreateNewResourceType(ShapeFreeEvents, "ShapeEvent"); - if (ClientType && ShapeEventType && - (extEntry = AddExtension(SHAPENAME, ShapeNumberEvents, 0, - ProcShapeDispatch, SProcShapeDispatch, - NULL, StandardMinorOpcode))) - { - ShapeEventBase = extEntry->eventBase; - EventSwapVector[ShapeEventBase] = (EventSwapPtr) SShapeNotifyEvent; - } -} - -static int -RegionOperate ( - ClientPtr client, - WindowPtr pWin, - int kind, - RegionPtr *destRgnp, - RegionPtr srcRgn, - int op, - int xoff, int yoff, - CreateDftPtr create) -{ - ScreenPtr pScreen = pWin->drawable.pScreen; - - if (srcRgn && (xoff || yoff)) - REGION_TRANSLATE(pScreen, srcRgn, xoff, yoff); - if (!pWin->parent) - { - if (srcRgn) - REGION_DESTROY(pScreen, srcRgn); - return Success; - } - - /* May/30/2001: - * The shape.PS specs say if src is None, existing shape is to be - * removed (and so the op-code has no meaning in such removal); - * see shape.PS, page 3, ShapeMask. - */ - if (srcRgn == NULL) { - if (*destRgnp != NULL) { - REGION_DESTROY (pScreen, *destRgnp); - *destRgnp = 0; - /* go on to remove shape and generate ShapeNotify */ - } - else { - /* May/30/2001: - * The target currently has no shape in effect, so nothing to - * do here. The specs say that ShapeNotify is generated whenever - * the client region is "modified"; since no modification is done - * here, we do not generate that event. The specs does not say - * "it is an error to request removal when there is no shape in - * effect", so we return good status. - */ - return Success; - } - } - else switch (op) { - case ShapeSet: - if (*destRgnp) - REGION_DESTROY(pScreen, *destRgnp); - *destRgnp = srcRgn; - srcRgn = 0; - break; - case ShapeUnion: - if (*destRgnp) - REGION_UNION(pScreen, *destRgnp, *destRgnp, srcRgn); - break; - case ShapeIntersect: - if (*destRgnp) - REGION_INTERSECT(pScreen, *destRgnp, *destRgnp, srcRgn); - else { - *destRgnp = srcRgn; - srcRgn = 0; - } - break; - case ShapeSubtract: - if (!*destRgnp) - *destRgnp = (*create)(pWin); - REGION_SUBTRACT(pScreen, *destRgnp, *destRgnp, srcRgn); - break; - case ShapeInvert: - if (!*destRgnp) - *destRgnp = REGION_CREATE(pScreen, (BoxPtr) 0, 0); - else - REGION_SUBTRACT(pScreen, *destRgnp, srcRgn, *destRgnp); - break; - default: - client->errorValue = op; - return BadValue; - } - if (srcRgn) - REGION_DESTROY(pScreen, srcRgn); - (*pScreen->SetShape) (pWin); - SendShapeNotify (pWin, kind); - return Success; -} - -RegionPtr -CreateBoundingShape (WindowPtr pWin) -{ - BoxRec extents; - - extents.x1 = -wBorderWidth (pWin); - extents.y1 = -wBorderWidth (pWin); - extents.x2 = pWin->drawable.width + wBorderWidth (pWin); - extents.y2 = pWin->drawable.height + wBorderWidth (pWin); - return REGION_CREATE(pWin->drawable.pScreen, &extents, 1); -} - -RegionPtr -CreateClipShape (WindowPtr pWin) -{ - BoxRec extents; - - extents.x1 = 0; - extents.y1 = 0; - extents.x2 = pWin->drawable.width; - extents.y2 = pWin->drawable.height; - return REGION_CREATE(pWin->drawable.pScreen, &extents, 1); -} - -static int -ProcShapeQueryVersion (ClientPtr client) -{ - xShapeQueryVersionReply rep; - int n; - - REQUEST_SIZE_MATCH (xShapeQueryVersionReq); - memset(&rep, 0, sizeof(xShapeQueryVersionReply)); - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.majorVersion = SERVER_SHAPE_MAJOR_VERSION; - rep.minorVersion = SERVER_SHAPE_MINOR_VERSION; - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swaps(&rep.majorVersion, n); - swaps(&rep.minorVersion, n); - } - WriteToClient(client, sizeof (xShapeQueryVersionReply), (char *)&rep); - return (client->noClientException); -} - -/***************** - * ProcShapeRectangles - * - *****************/ - -static int -ProcShapeRectangles (ClientPtr client) -{ - WindowPtr pWin; - ScreenPtr pScreen; - REQUEST(xShapeRectanglesReq); - xRectangle *prects; - int nrects, ctype, rc; - RegionPtr srcRgn; - RegionPtr *destRgn; - CreateDftPtr createDefault; - - REQUEST_AT_LEAST_SIZE (xShapeRectanglesReq); - UpdateCurrentTime(); - rc = dixLookupWindow(&pWin, stuff->dest, client, DixSetAttrAccess); - if (rc != Success) - return rc; - switch (stuff->destKind) { - case ShapeBounding: - createDefault = CreateBoundingShape; - break; - case ShapeClip: - createDefault = CreateClipShape; - break; - case ShapeInput: - createDefault = CreateBoundingShape; - break; - default: - client->errorValue = stuff->destKind; - return BadValue; - } - if ((stuff->ordering != Unsorted) && (stuff->ordering != YSorted) && - (stuff->ordering != YXSorted) && (stuff->ordering != YXBanded)) - { - client->errorValue = stuff->ordering; - return BadValue; - } - pScreen = pWin->drawable.pScreen; - nrects = ((stuff->length << 2) - sizeof(xShapeRectanglesReq)); - if (nrects & 4) - return BadLength; - nrects >>= 3; - prects = (xRectangle *) &stuff[1]; - ctype = VerifyRectOrder(nrects, prects, (int)stuff->ordering); - if (ctype < 0) - return BadMatch; - srcRgn = RECTS_TO_REGION(pScreen, nrects, prects, ctype); - - if (!pWin->optional) - MakeWindowOptional (pWin); - switch (stuff->destKind) { - case ShapeBounding: - destRgn = &pWin->optional->boundingShape; - break; - case ShapeClip: - destRgn = &pWin->optional->clipShape; - break; - case ShapeInput: - destRgn = &pWin->optional->inputShape; - break; - default: - return BadValue; - } - - return RegionOperate (client, pWin, (int)stuff->destKind, - destRgn, srcRgn, (int)stuff->op, - stuff->xOff, stuff->yOff, createDefault); -} - -#ifdef PANORAMIX -static int -ProcPanoramiXShapeRectangles( - ClientPtr client) -{ - REQUEST(xShapeRectanglesReq); - PanoramiXRes *win; - int j, result; - - REQUEST_AT_LEAST_SIZE (xShapeRectanglesReq); - - result = dixLookupResourceByType((pointer *)&win, stuff->dest, XRT_WINDOW, - client, DixWriteAccess); - if (result != Success) - return (result == BadValue) ? BadWindow : result; - - FOR_NSCREENS(j) { - stuff->dest = win->info[j].id; - result = ProcShapeRectangles (client); - if (result != Success) break; - } - return (result); -} -#endif - - -/************** - * ProcShapeMask - **************/ - - -static int -ProcShapeMask (ClientPtr client) -{ - WindowPtr pWin; - ScreenPtr pScreen; - REQUEST(xShapeMaskReq); - RegionPtr srcRgn; - RegionPtr *destRgn; - PixmapPtr pPixmap; - CreateDftPtr createDefault; - int rc; - - REQUEST_SIZE_MATCH (xShapeMaskReq); - UpdateCurrentTime(); - rc = dixLookupWindow(&pWin, stuff->dest, client, DixSetAttrAccess); - if (rc != Success) - return rc; - switch (stuff->destKind) { - case ShapeBounding: - createDefault = CreateBoundingShape; - break; - case ShapeClip: - createDefault = CreateClipShape; - break; - case ShapeInput: - createDefault = CreateBoundingShape; - break; - default: - client->errorValue = stuff->destKind; - return BadValue; - } - pScreen = pWin->drawable.pScreen; - if (stuff->src == None) - srcRgn = 0; - else { - rc = dixLookupResourceByType((pointer *)&pPixmap, stuff->src, RT_PIXMAP, - client, DixReadAccess); - if (rc != Success) - return (rc == BadValue) ? BadPixmap : rc; - if (pPixmap->drawable.pScreen != pScreen || - pPixmap->drawable.depth != 1) - return BadMatch; - srcRgn = BITMAP_TO_REGION(pScreen, pPixmap); - if (!srcRgn) - return BadAlloc; - } - - if (!pWin->optional) - MakeWindowOptional (pWin); - switch (stuff->destKind) { - case ShapeBounding: - destRgn = &pWin->optional->boundingShape; - break; - case ShapeClip: - destRgn = &pWin->optional->clipShape; - break; - case ShapeInput: - destRgn = &pWin->optional->inputShape; - break; - default: - return BadValue; - } - - return RegionOperate (client, pWin, (int)stuff->destKind, - destRgn, srcRgn, (int)stuff->op, - stuff->xOff, stuff->yOff, createDefault); -} - -#ifdef PANORAMIX -static int -ProcPanoramiXShapeMask( - ClientPtr client) -{ - REQUEST(xShapeMaskReq); - PanoramiXRes *win, *pmap; - int j, result; - - REQUEST_SIZE_MATCH (xShapeMaskReq); - - result = dixLookupResourceByType((pointer *)&win, stuff->dest, XRT_WINDOW, - client, DixWriteAccess); - if (result != Success) - return (result == BadValue) ? BadWindow : result; - - if(stuff->src != None) { - result = dixLookupResourceByType((pointer *)&pmap, stuff->src, - XRT_PIXMAP, client, DixReadAccess); - if (result != Success) - return (result == BadValue) ? BadPixmap : result; - } else - pmap = NULL; - - FOR_NSCREENS(j) { - stuff->dest = win->info[j].id; - if(pmap) - stuff->src = pmap->info[j].id; - result = ProcShapeMask (client); - if (result != Success) break; - } - return (result); -} -#endif - - -/************ - * ProcShapeCombine - ************/ - -static int -ProcShapeCombine (ClientPtr client) -{ - WindowPtr pSrcWin, pDestWin; - ScreenPtr pScreen; - REQUEST(xShapeCombineReq); - RegionPtr srcRgn; - RegionPtr *destRgn; - CreateDftPtr createDefault; - CreateDftPtr createSrc; - RegionPtr tmp; - int rc; - - REQUEST_SIZE_MATCH (xShapeCombineReq); - UpdateCurrentTime(); - rc = dixLookupWindow(&pDestWin, stuff->dest, client, DixSetAttrAccess); - if (rc != Success) - return rc; - if (!pDestWin->optional) - MakeWindowOptional (pDestWin); - switch (stuff->destKind) { - case ShapeBounding: - createDefault = CreateBoundingShape; - break; - case ShapeClip: - createDefault = CreateClipShape; - break; - case ShapeInput: - createDefault = CreateBoundingShape; - break; - default: - client->errorValue = stuff->destKind; - return BadValue; - } - pScreen = pDestWin->drawable.pScreen; - - rc = dixLookupWindow(&pSrcWin, stuff->src, client, DixGetAttrAccess); - if (rc != Success) - return rc; - switch (stuff->srcKind) { - case ShapeBounding: - srcRgn = wBoundingShape (pSrcWin); - createSrc = CreateBoundingShape; - break; - case ShapeClip: - srcRgn = wClipShape (pSrcWin); - createSrc = CreateClipShape; - break; - case ShapeInput: - srcRgn = wInputShape (pSrcWin); - createSrc = CreateBoundingShape; - break; - default: - client->errorValue = stuff->srcKind; - return BadValue; - } - if (pSrcWin->drawable.pScreen != pScreen) - { - return BadMatch; - } - - if (srcRgn) { - tmp = REGION_CREATE(pScreen, (BoxPtr) 0, 0); - REGION_COPY(pScreen, tmp, srcRgn); - srcRgn = tmp; - } else - srcRgn = (*createSrc) (pSrcWin); - - if (!pDestWin->optional) - MakeWindowOptional (pDestWin); - switch (stuff->destKind) { - case ShapeBounding: - destRgn = &pDestWin->optional->boundingShape; - break; - case ShapeClip: - destRgn = &pDestWin->optional->clipShape; - break; - case ShapeInput: - destRgn = &pDestWin->optional->inputShape; - break; - default: - return BadValue; - } - - return RegionOperate (client, pDestWin, (int)stuff->destKind, - destRgn, srcRgn, (int)stuff->op, - stuff->xOff, stuff->yOff, createDefault); -} - - -#ifdef PANORAMIX -static int -ProcPanoramiXShapeCombine( - ClientPtr client) -{ - REQUEST(xShapeCombineReq); - PanoramiXRes *win, *win2; - int j, result; - - REQUEST_AT_LEAST_SIZE (xShapeCombineReq); - - result = dixLookupResourceByType((pointer *)&win, stuff->dest, XRT_WINDOW, - client, DixWriteAccess); - if (result != Success) - return (result == BadValue) ? BadWindow : result; - - result = dixLookupResourceByType((pointer *)&win2, stuff->src, XRT_WINDOW, - client, DixReadAccess); - if (result != Success) - return (result == BadValue) ? BadWindow : result; - - FOR_NSCREENS(j) { - stuff->dest = win->info[j].id; - stuff->src = win2->info[j].id; - result = ProcShapeCombine (client); - if (result != Success) break; - } - return (result); -} -#endif - -/************* - * ProcShapeOffset - *************/ - -static int -ProcShapeOffset (ClientPtr client) -{ - WindowPtr pWin; - ScreenPtr pScreen; - REQUEST(xShapeOffsetReq); - RegionPtr srcRgn; - int rc; - - REQUEST_SIZE_MATCH (xShapeOffsetReq); - UpdateCurrentTime(); - rc = dixLookupWindow(&pWin, stuff->dest, client, DixSetAttrAccess); - if (rc != Success) - return rc; - switch (stuff->destKind) { - case ShapeBounding: - srcRgn = wBoundingShape (pWin); - break; - case ShapeClip: - srcRgn = wClipShape(pWin); - break; - case ShapeInput: - srcRgn = wInputShape (pWin); - break; - default: - client->errorValue = stuff->destKind; - return BadValue; - } - pScreen = pWin->drawable.pScreen; - if (srcRgn) - { - REGION_TRANSLATE(pScreen, srcRgn, stuff->xOff, stuff->yOff); - (*pScreen->SetShape) (pWin); - } - SendShapeNotify (pWin, (int)stuff->destKind); - return Success; -} - - -#ifdef PANORAMIX -static int -ProcPanoramiXShapeOffset( - ClientPtr client) -{ - REQUEST(xShapeOffsetReq); - PanoramiXRes *win; - int j, result; - - REQUEST_AT_LEAST_SIZE (xShapeOffsetReq); - - result = dixLookupResourceByType((pointer *)&win, stuff->dest, XRT_WINDOW, - client, DixWriteAccess); - if (result != Success) - return (result == BadValue) ? BadWindow : result; - - FOR_NSCREENS(j) { - stuff->dest = win->info[j].id; - result = ProcShapeOffset (client); - if(result != Success) break; - } - return (result); -} -#endif - - -static int -ProcShapeQueryExtents (ClientPtr client) -{ - REQUEST(xShapeQueryExtentsReq); - WindowPtr pWin; - xShapeQueryExtentsReply rep; - BoxRec extents, *pExtents; - int n, rc; - RegionPtr region; - - REQUEST_SIZE_MATCH (xShapeQueryExtentsReq); - rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); - if (rc != Success) - return rc; - memset(&rep, 0, sizeof(xShapeQueryExtentsReply)); - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.boundingShaped = (wBoundingShape(pWin) != 0); - rep.clipShaped = (wClipShape(pWin) != 0); - if ((region = wBoundingShape(pWin))) { - /* this is done in two steps because of a compiler bug on SunOS 4.1.3 */ - pExtents = REGION_EXTENTS(pWin->drawable.pScreen, region); - extents = *pExtents; - } else { - extents.x1 = -wBorderWidth (pWin); - extents.y1 = -wBorderWidth (pWin); - extents.x2 = pWin->drawable.width + wBorderWidth (pWin); - extents.y2 = pWin->drawable.height + wBorderWidth (pWin); - } - rep.xBoundingShape = extents.x1; - rep.yBoundingShape = extents.y1; - rep.widthBoundingShape = extents.x2 - extents.x1; - rep.heightBoundingShape = extents.y2 - extents.y1; - if ((region = wClipShape(pWin))) { - /* this is done in two steps because of a compiler bug on SunOS 4.1.3 */ - pExtents = REGION_EXTENTS(pWin->drawable.pScreen, region); - extents = *pExtents; - } else { - extents.x1 = 0; - extents.y1 = 0; - extents.x2 = pWin->drawable.width; - extents.y2 = pWin->drawable.height; - } - rep.xClipShape = extents.x1; - rep.yClipShape = extents.y1; - rep.widthClipShape = extents.x2 - extents.x1; - rep.heightClipShape = extents.y2 - extents.y1; - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swaps(&rep.xBoundingShape, n); - swaps(&rep.yBoundingShape, n); - swaps(&rep.widthBoundingShape, n); - swaps(&rep.heightBoundingShape, n); - swaps(&rep.xClipShape, n); - swaps(&rep.yClipShape, n); - swaps(&rep.widthClipShape, n); - swaps(&rep.heightClipShape, n); - } - WriteToClient(client, sizeof (xShapeQueryExtentsReply), (char *)&rep); - return (client->noClientException); -} - -/*ARGSUSED*/ -static int -ShapeFreeClient (pointer data, XID id) -{ - ShapeEventPtr pShapeEvent; - WindowPtr pWin; - ShapeEventPtr *pHead, pCur, pPrev; - int rc; - - pShapeEvent = (ShapeEventPtr) data; - pWin = pShapeEvent->window; - rc = dixLookupResourceByType((pointer *)&pHead, pWin->drawable.id, - ShapeEventType, serverClient, DixReadAccess); - if (rc == Success) { - pPrev = 0; - for (pCur = *pHead; pCur && pCur != pShapeEvent; pCur=pCur->next) - pPrev = pCur; - if (pCur) - { - if (pPrev) - pPrev->next = pShapeEvent->next; - else - *pHead = pShapeEvent->next; - } - } - xfree ((pointer) pShapeEvent); - return 1; -} - -/*ARGSUSED*/ -static int -ShapeFreeEvents (pointer data, XID id) -{ - ShapeEventPtr *pHead, pCur, pNext; - - pHead = (ShapeEventPtr *) data; - for (pCur = *pHead; pCur; pCur = pNext) { - pNext = pCur->next; - FreeResource (pCur->clientResource, ClientType); - xfree ((pointer) pCur); - } - xfree ((pointer) pHead); - return 1; -} - -static int -ProcShapeSelectInput (ClientPtr client) -{ - REQUEST(xShapeSelectInputReq); - WindowPtr pWin; - ShapeEventPtr pShapeEvent, pNewShapeEvent, *pHead; - XID clientResource; - int rc; - - REQUEST_SIZE_MATCH (xShapeSelectInputReq); - rc = dixLookupWindow(&pWin, stuff->window, client, DixReceiveAccess); - if (rc != Success) - return rc; - rc = dixLookupResourceByType((pointer *)&pHead, pWin->drawable.id, - ShapeEventType, client, DixWriteAccess); - if (rc != Success && rc != BadValue) - return rc; - - switch (stuff->enable) { - case xTrue: - if (pHead) { - - /* check for existing entry. */ - for (pShapeEvent = *pHead; - pShapeEvent; - pShapeEvent = pShapeEvent->next) - { - if (pShapeEvent->client == client) - return Success; - } - } - - /* build the entry */ - pNewShapeEvent = xalloc (sizeof (ShapeEventRec)); - if (!pNewShapeEvent) - return BadAlloc; - pNewShapeEvent->next = 0; - pNewShapeEvent->client = client; - pNewShapeEvent->window = pWin; - /* - * add a resource that will be deleted when - * the client goes away - */ - clientResource = FakeClientID (client->index); - pNewShapeEvent->clientResource = clientResource; - if (!AddResource (clientResource, ClientType, (pointer)pNewShapeEvent)) - return BadAlloc; - /* - * create a resource to contain a pointer to the list - * of clients selecting input. This must be indirect as - * the list may be arbitrarily rearranged which cannot be - * done through the resource database. - */ - if (!pHead) - { - pHead = xalloc (sizeof (ShapeEventPtr)); - if (!pHead || - !AddResource (pWin->drawable.id, ShapeEventType, (pointer)pHead)) - { - FreeResource (clientResource, RT_NONE); - return BadAlloc; - } - *pHead = 0; - } - pNewShapeEvent->next = *pHead; - *pHead = pNewShapeEvent; - break; - case xFalse: - /* delete the interest */ - if (pHead) { - pNewShapeEvent = 0; - for (pShapeEvent = *pHead; pShapeEvent; pShapeEvent = pShapeEvent->next) { - if (pShapeEvent->client == client) - break; - pNewShapeEvent = pShapeEvent; - } - if (pShapeEvent) { - FreeResource (pShapeEvent->clientResource, ClientType); - if (pNewShapeEvent) - pNewShapeEvent->next = pShapeEvent->next; - else - *pHead = pShapeEvent->next; - xfree (pShapeEvent); - } - } - break; - default: - client->errorValue = stuff->enable; - return BadValue; - } - return Success; -} - -/* - * deliver the event - */ - -void -SendShapeNotify (WindowPtr pWin, int which) -{ - ShapeEventPtr *pHead, pShapeEvent; - ClientPtr client; - xShapeNotifyEvent se; - BoxRec extents; - RegionPtr region; - BYTE shaped; - int rc; - - rc = dixLookupResourceByType((pointer *)&pHead, pWin->drawable.id, - ShapeEventType, serverClient, DixReadAccess); - if (rc != Success) - return; - switch (which) { - case ShapeBounding: - region = wBoundingShape(pWin); - if (region) { - extents = *REGION_EXTENTS(pWin->drawable.pScreen, region); - shaped = xTrue; - } else { - extents.x1 = -wBorderWidth (pWin); - extents.y1 = -wBorderWidth (pWin); - extents.x2 = pWin->drawable.width + wBorderWidth (pWin); - extents.y2 = pWin->drawable.height + wBorderWidth (pWin); - shaped = xFalse; - } - break; - case ShapeClip: - region = wClipShape(pWin); - if (region) { - extents = *REGION_EXTENTS(pWin->drawable.pScreen, region); - shaped = xTrue; - } else { - extents.x1 = 0; - extents.y1 = 0; - extents.x2 = pWin->drawable.width; - extents.y2 = pWin->drawable.height; - shaped = xFalse; - } - break; - case ShapeInput: - region = wInputShape(pWin); - if (region) { - extents = *REGION_EXTENTS(pWin->drawable.pScreen, region); - shaped = xTrue; - } else { - extents.x1 = -wBorderWidth (pWin); - extents.y1 = -wBorderWidth (pWin); - extents.x2 = pWin->drawable.width + wBorderWidth (pWin); - extents.y2 = pWin->drawable.height + wBorderWidth (pWin); - shaped = xFalse; - } - break; - default: - return; - } - for (pShapeEvent = *pHead; pShapeEvent; pShapeEvent = pShapeEvent->next) { - client = pShapeEvent->client; - if (client == serverClient || client->clientGone) - continue; - se.type = ShapeNotify + ShapeEventBase; - se.kind = which; - se.window = pWin->drawable.id; - se.sequenceNumber = client->sequence; - se.x = extents.x1; - se.y = extents.y1; - se.width = extents.x2 - extents.x1; - se.height = extents.y2 - extents.y1; - se.time = currentTime.milliseconds; - se.shaped = shaped; - WriteEventsToClient (client, 1, (xEvent *) &se); - } -} - -static int -ProcShapeInputSelected (ClientPtr client) -{ - REQUEST(xShapeInputSelectedReq); - WindowPtr pWin; - ShapeEventPtr pShapeEvent, *pHead; - int enabled, rc; - xShapeInputSelectedReply rep; - int n; - - REQUEST_SIZE_MATCH (xShapeInputSelectedReq); - rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); - if (rc != Success) - return rc; - rc = dixLookupResourceByType((pointer *)&pHead, pWin->drawable.id, - ShapeEventType, client, DixReadAccess); - if (rc != Success && rc != BadValue) - return rc; - enabled = xFalse; - if (pHead) { - for (pShapeEvent = *pHead; - pShapeEvent; - pShapeEvent = pShapeEvent->next) - { - if (pShapeEvent->client == client) { - enabled = xTrue; - break; - } - } - } - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.enabled = enabled; - if (client->swapped) { - swaps (&rep.sequenceNumber, n); - swapl (&rep.length, n); - } - WriteToClient (client, sizeof (xShapeInputSelectedReply), (char *) &rep); - return (client->noClientException); -} - -static int -ProcShapeGetRectangles (ClientPtr client) -{ - REQUEST(xShapeGetRectanglesReq); - WindowPtr pWin; - xShapeGetRectanglesReply rep; - xRectangle *rects; - int nrects, i, rc; - RegionPtr region; - int n; - - REQUEST_SIZE_MATCH(xShapeGetRectanglesReq); - rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); - if (rc != Success) - return rc; - switch (stuff->kind) { - case ShapeBounding: - region = wBoundingShape(pWin); - break; - case ShapeClip: - region = wClipShape(pWin); - break; - case ShapeInput: - region = wInputShape (pWin); - break; - default: - client->errorValue = stuff->kind; - return BadValue; - } - if (!region) { - nrects = 1; - rects = xalloc (sizeof (xRectangle)); - if (!rects) - return BadAlloc; - switch (stuff->kind) { - case ShapeBounding: - rects->x = - (int) wBorderWidth (pWin); - rects->y = - (int) wBorderWidth (pWin); - rects->width = pWin->drawable.width + wBorderWidth (pWin); - rects->height = pWin->drawable.height + wBorderWidth (pWin); - break; - case ShapeClip: - rects->x = 0; - rects->y = 0; - rects->width = pWin->drawable.width; - rects->height = pWin->drawable.height; - break; - case ShapeInput: - rects->x = - (int) wBorderWidth (pWin); - rects->y = - (int) wBorderWidth (pWin); - rects->width = pWin->drawable.width + wBorderWidth (pWin); - rects->height = pWin->drawable.height + wBorderWidth (pWin); - break; - } - } else { - BoxPtr box; - nrects = REGION_NUM_RECTS(region); - box = REGION_RECTS(region); - rects = xalloc (nrects * sizeof (xRectangle)); - if (!rects && nrects) - return BadAlloc; - for (i = 0; i < nrects; i++, box++) { - rects[i].x = box->x1; - rects[i].y = box->y1; - rects[i].width = box->x2 - box->x1; - rects[i].height = box->y2 - box->y1; - } - } - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.length = bytes_to_int32(nrects * sizeof (xRectangle)); - rep.ordering = YXBanded; - rep.nrects = nrects; - if (client->swapped) { - swaps (&rep.sequenceNumber, n); - swapl (&rep.length, n); - swapl (&rep.nrects, n); - SwapShorts ((short *)rects, (unsigned long)nrects * 4); - } - WriteToClient (client, sizeof (rep), (char *) &rep); - WriteToClient (client, nrects * sizeof (xRectangle), (char *) rects); - xfree (rects); - return client->noClientException; -} - -static int -ProcShapeDispatch (ClientPtr client) -{ - REQUEST(xReq); - switch (stuff->data) { - case X_ShapeQueryVersion: - return ProcShapeQueryVersion (client); - case X_ShapeRectangles: -#ifdef PANORAMIX - if ( !noPanoramiXExtension ) - return ProcPanoramiXShapeRectangles (client); - else -#endif - return ProcShapeRectangles (client); - case X_ShapeMask: -#ifdef PANORAMIX - if ( !noPanoramiXExtension ) - return ProcPanoramiXShapeMask (client); - else -#endif - return ProcShapeMask (client); - case X_ShapeCombine: -#ifdef PANORAMIX - if ( !noPanoramiXExtension ) - return ProcPanoramiXShapeCombine (client); - else -#endif - return ProcShapeCombine (client); - case X_ShapeOffset: -#ifdef PANORAMIX - if ( !noPanoramiXExtension ) - return ProcPanoramiXShapeOffset (client); - else -#endif - return ProcShapeOffset (client); - case X_ShapeQueryExtents: - return ProcShapeQueryExtents (client); - case X_ShapeSelectInput: - return ProcShapeSelectInput (client); - case X_ShapeInputSelected: - return ProcShapeInputSelected (client); - case X_ShapeGetRectangles: - return ProcShapeGetRectangles (client); - default: - return BadRequest; - } -} - -static void -SShapeNotifyEvent(xShapeNotifyEvent *from, xShapeNotifyEvent *to) -{ - to->type = from->type; - to->kind = from->kind; - cpswapl (from->window, to->window); - cpswaps (from->sequenceNumber, to->sequenceNumber); - cpswaps (from->x, to->x); - cpswaps (from->y, to->y); - cpswaps (from->width, to->width); - cpswaps (from->height, to->height); - cpswapl (from->time, to->time); - to->shaped = from->shaped; -} - -static int -SProcShapeQueryVersion (ClientPtr client) -{ - int n; - REQUEST (xShapeQueryVersionReq); - - swaps (&stuff->length, n); - return ProcShapeQueryVersion (client); -} - -static int -SProcShapeRectangles (ClientPtr client) -{ - char n; - REQUEST (xShapeRectanglesReq); - - swaps (&stuff->length, n); - REQUEST_AT_LEAST_SIZE (xShapeRectanglesReq); - swapl (&stuff->dest, n); - swaps (&stuff->xOff, n); - swaps (&stuff->yOff, n); - SwapRestS(stuff); - return ProcShapeRectangles (client); -} - -static int -SProcShapeMask (ClientPtr client) -{ - char n; - REQUEST (xShapeMaskReq); - - swaps (&stuff->length, n); - REQUEST_SIZE_MATCH (xShapeMaskReq); - swapl (&stuff->dest, n); - swaps (&stuff->xOff, n); - swaps (&stuff->yOff, n); - swapl (&stuff->src, n); - return ProcShapeMask (client); -} - -static int -SProcShapeCombine (ClientPtr client) -{ - char n; - REQUEST (xShapeCombineReq); - - swaps (&stuff->length, n); - REQUEST_SIZE_MATCH (xShapeCombineReq); - swapl (&stuff->dest, n); - swaps (&stuff->xOff, n); - swaps (&stuff->yOff, n); - swapl (&stuff->src, n); - return ProcShapeCombine (client); -} - -static int -SProcShapeOffset (ClientPtr client) -{ - char n; - REQUEST (xShapeOffsetReq); - - swaps (&stuff->length, n); - REQUEST_SIZE_MATCH (xShapeOffsetReq); - swapl (&stuff->dest, n); - swaps (&stuff->xOff, n); - swaps (&stuff->yOff, n); - return ProcShapeOffset (client); -} - -static int -SProcShapeQueryExtents (ClientPtr client) -{ - char n; - REQUEST (xShapeQueryExtentsReq); - - swaps (&stuff->length, n); - REQUEST_SIZE_MATCH (xShapeQueryExtentsReq); - swapl (&stuff->window, n); - return ProcShapeQueryExtents (client); -} - -static int -SProcShapeSelectInput (ClientPtr client) -{ - char n; - REQUEST (xShapeSelectInputReq); - - swaps (&stuff->length, n); - REQUEST_SIZE_MATCH (xShapeSelectInputReq); - swapl (&stuff->window, n); - return ProcShapeSelectInput (client); -} - -static int -SProcShapeInputSelected (ClientPtr client) -{ - int n; - REQUEST (xShapeInputSelectedReq); - - swaps (&stuff->length, n); - REQUEST_SIZE_MATCH (xShapeInputSelectedReq); - swapl (&stuff->window, n); - return ProcShapeInputSelected (client); -} - -static int -SProcShapeGetRectangles (ClientPtr client) -{ - REQUEST(xShapeGetRectanglesReq); - char n; - - swaps (&stuff->length, n); - REQUEST_SIZE_MATCH(xShapeGetRectanglesReq); - swapl (&stuff->window, n); - return ProcShapeGetRectangles (client); -} - -static int -SProcShapeDispatch (ClientPtr client) -{ - REQUEST(xReq); - switch (stuff->data) { - case X_ShapeQueryVersion: - return SProcShapeQueryVersion (client); - case X_ShapeRectangles: - return SProcShapeRectangles (client); - case X_ShapeMask: - return SProcShapeMask (client); - case X_ShapeCombine: - return SProcShapeCombine (client); - case X_ShapeOffset: - return SProcShapeOffset (client); - case X_ShapeQueryExtents: - return SProcShapeQueryExtents (client); - case X_ShapeSelectInput: - return SProcShapeSelectInput (client); - case X_ShapeInputSelected: - return SProcShapeInputSelected (client); - case X_ShapeGetRectangles: - return SProcShapeGetRectangles (client); - default: - return BadRequest; - } -} +/************************************************************ + +Copyright 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. + +********************************************************/ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include + +#include +#include +#include "misc.h" +#include "os.h" +#include "windowstr.h" +#include "scrnintstr.h" +#include "pixmapstr.h" +#include "extnsionst.h" +#include "dixstruct.h" +#include "resource.h" +#include "opaque.h" +#include +#include "regionstr.h" +#include "gcstruct.h" +#include "modinit.h" +#include "protocol-versions.h" + +typedef RegionPtr (*CreateDftPtr)( + WindowPtr /* pWin */ + ); + +static int ShapeFreeClient( + pointer /* data */, + XID /* id */ + ); +static int ShapeFreeEvents( + pointer /* data */, + XID /* id */ + ); +static void SShapeNotifyEvent( + xShapeNotifyEvent * /* from */, + xShapeNotifyEvent * /* to */ + ); + +/* SendShapeNotify, CreateBoundingShape and CreateClipShape are used + * externally by the Xfixes extension and are now defined in window.h + */ + +static DISPATCH_PROC(ProcShapeCombine); +static DISPATCH_PROC(ProcShapeDispatch); +static DISPATCH_PROC(ProcShapeGetRectangles); +static DISPATCH_PROC(ProcShapeInputSelected); +static DISPATCH_PROC(ProcShapeMask); +static DISPATCH_PROC(ProcShapeOffset); +static DISPATCH_PROC(ProcShapeQueryExtents); +static DISPATCH_PROC(ProcShapeQueryVersion); +static DISPATCH_PROC(ProcShapeRectangles); +static DISPATCH_PROC(ProcShapeSelectInput); +static DISPATCH_PROC(SProcShapeCombine); +static DISPATCH_PROC(SProcShapeDispatch); +static DISPATCH_PROC(SProcShapeGetRectangles); +static DISPATCH_PROC(SProcShapeInputSelected); +static DISPATCH_PROC(SProcShapeMask); +static DISPATCH_PROC(SProcShapeOffset); +static DISPATCH_PROC(SProcShapeQueryExtents); +static DISPATCH_PROC(SProcShapeQueryVersion); +static DISPATCH_PROC(SProcShapeRectangles); +static DISPATCH_PROC(SProcShapeSelectInput); + +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" +#endif + +static int ShapeEventBase = 0; +static RESTYPE ClientType, ShapeEventType; /* resource types for event masks */ + +/* + * each window has a list of clients requesting + * ShapeNotify events. Each client has a resource + * for each window it selects ShapeNotify input for, + * this resource is used to delete the ShapeNotifyRec + * entry from the per-window queue. + */ + +typedef struct _ShapeEvent *ShapeEventPtr; + +typedef struct _ShapeEvent { + ShapeEventPtr next; + ClientPtr client; + WindowPtr window; + XID clientResource; +} ShapeEventRec; + +/**************** + * ShapeExtensionInit + * + * Called from InitExtensions in main() or from QueryExtension() if the + * extension is dynamically loaded. + * + ****************/ + +void +ShapeExtensionInit(void) +{ + ExtensionEntry *extEntry; + + ClientType = CreateNewResourceType(ShapeFreeClient, "ShapeClient"); + ShapeEventType = CreateNewResourceType(ShapeFreeEvents, "ShapeEvent"); + if (ClientType && ShapeEventType && + (extEntry = AddExtension(SHAPENAME, ShapeNumberEvents, 0, + ProcShapeDispatch, SProcShapeDispatch, + NULL, StandardMinorOpcode))) + { + ShapeEventBase = extEntry->eventBase; + EventSwapVector[ShapeEventBase] = (EventSwapPtr) SShapeNotifyEvent; + } +} + +static int +RegionOperate ( + ClientPtr client, + WindowPtr pWin, + int kind, + RegionPtr *destRgnp, + RegionPtr srcRgn, + int op, + int xoff, int yoff, + CreateDftPtr create) +{ + ScreenPtr pScreen = pWin->drawable.pScreen; + + if (srcRgn && (xoff || yoff)) + REGION_TRANSLATE(pScreen, srcRgn, xoff, yoff); + if (!pWin->parent) + { + if (srcRgn) + REGION_DESTROY(pScreen, srcRgn); + return Success; + } + + /* May/30/2001: + * The shape.PS specs say if src is None, existing shape is to be + * removed (and so the op-code has no meaning in such removal); + * see shape.PS, page 3, ShapeMask. + */ + if (srcRgn == NULL) { + if (*destRgnp != NULL) { + REGION_DESTROY (pScreen, *destRgnp); + *destRgnp = 0; + /* go on to remove shape and generate ShapeNotify */ + } + else { + /* May/30/2001: + * The target currently has no shape in effect, so nothing to + * do here. The specs say that ShapeNotify is generated whenever + * the client region is "modified"; since no modification is done + * here, we do not generate that event. The specs does not say + * "it is an error to request removal when there is no shape in + * effect", so we return good status. + */ + return Success; + } + } + else switch (op) { + case ShapeSet: + if (*destRgnp) + REGION_DESTROY(pScreen, *destRgnp); + *destRgnp = srcRgn; + srcRgn = 0; + break; + case ShapeUnion: + if (*destRgnp) + REGION_UNION(pScreen, *destRgnp, *destRgnp, srcRgn); + break; + case ShapeIntersect: + if (*destRgnp) + REGION_INTERSECT(pScreen, *destRgnp, *destRgnp, srcRgn); + else { + *destRgnp = srcRgn; + srcRgn = 0; + } + break; + case ShapeSubtract: + if (!*destRgnp) + *destRgnp = (*create)(pWin); + REGION_SUBTRACT(pScreen, *destRgnp, *destRgnp, srcRgn); + break; + case ShapeInvert: + if (!*destRgnp) + *destRgnp = REGION_CREATE(pScreen, (BoxPtr) 0, 0); + else + REGION_SUBTRACT(pScreen, *destRgnp, srcRgn, *destRgnp); + break; + default: + client->errorValue = op; + return BadValue; + } + if (srcRgn) + REGION_DESTROY(pScreen, srcRgn); + (*pScreen->SetShape) (pWin); + SendShapeNotify (pWin, kind); + return Success; +} + +RegionPtr +CreateBoundingShape (WindowPtr pWin) +{ + BoxRec extents; + + extents.x1 = -wBorderWidth (pWin); + extents.y1 = -wBorderWidth (pWin); + extents.x2 = pWin->drawable.width + wBorderWidth (pWin); + extents.y2 = pWin->drawable.height + wBorderWidth (pWin); + return REGION_CREATE(pWin->drawable.pScreen, &extents, 1); +} + +RegionPtr +CreateClipShape (WindowPtr pWin) +{ + BoxRec extents; + + extents.x1 = 0; + extents.y1 = 0; + extents.x2 = pWin->drawable.width; + extents.y2 = pWin->drawable.height; + return REGION_CREATE(pWin->drawable.pScreen, &extents, 1); +} + +static int +ProcShapeQueryVersion (ClientPtr client) +{ + xShapeQueryVersionReply rep; + int n; + + REQUEST_SIZE_MATCH (xShapeQueryVersionReq); + memset(&rep, 0, sizeof(xShapeQueryVersionReply)); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = SERVER_SHAPE_MAJOR_VERSION; + rep.minorVersion = SERVER_SHAPE_MINOR_VERSION; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.majorVersion, n); + swaps(&rep.minorVersion, n); + } + WriteToClient(client, sizeof (xShapeQueryVersionReply), (char *)&rep); + return Success; +} + +/***************** + * ProcShapeRectangles + * + *****************/ + +static int +ProcShapeRectangles (ClientPtr client) +{ + WindowPtr pWin; + ScreenPtr pScreen; + REQUEST(xShapeRectanglesReq); + xRectangle *prects; + int nrects, ctype, rc; + RegionPtr srcRgn; + RegionPtr *destRgn; + CreateDftPtr createDefault; + + REQUEST_AT_LEAST_SIZE (xShapeRectanglesReq); + UpdateCurrentTime(); + rc = dixLookupWindow(&pWin, stuff->dest, client, DixSetAttrAccess); + if (rc != Success) + return rc; + switch (stuff->destKind) { + case ShapeBounding: + createDefault = CreateBoundingShape; + break; + case ShapeClip: + createDefault = CreateClipShape; + break; + case ShapeInput: + createDefault = CreateBoundingShape; + break; + default: + client->errorValue = stuff->destKind; + return BadValue; + } + if ((stuff->ordering != Unsorted) && (stuff->ordering != YSorted) && + (stuff->ordering != YXSorted) && (stuff->ordering != YXBanded)) + { + client->errorValue = stuff->ordering; + return BadValue; + } + pScreen = pWin->drawable.pScreen; + nrects = ((stuff->length << 2) - sizeof(xShapeRectanglesReq)); + if (nrects & 4) + return BadLength; + nrects >>= 3; + prects = (xRectangle *) &stuff[1]; + ctype = VerifyRectOrder(nrects, prects, (int)stuff->ordering); + if (ctype < 0) + return BadMatch; + srcRgn = RECTS_TO_REGION(pScreen, nrects, prects, ctype); + + if (!pWin->optional) + MakeWindowOptional (pWin); + switch (stuff->destKind) { + case ShapeBounding: + destRgn = &pWin->optional->boundingShape; + break; + case ShapeClip: + destRgn = &pWin->optional->clipShape; + break; + case ShapeInput: + destRgn = &pWin->optional->inputShape; + break; + default: + return BadValue; + } + + return RegionOperate (client, pWin, (int)stuff->destKind, + destRgn, srcRgn, (int)stuff->op, + stuff->xOff, stuff->yOff, createDefault); +} + +#ifdef PANORAMIX +static int +ProcPanoramiXShapeRectangles( + ClientPtr client) +{ + REQUEST(xShapeRectanglesReq); + PanoramiXRes *win; + int j, result; + + REQUEST_AT_LEAST_SIZE (xShapeRectanglesReq); + + result = dixLookupResourceByType((pointer *)&win, stuff->dest, XRT_WINDOW, + client, DixWriteAccess); + if (result != Success) + return (result == BadValue) ? BadWindow : result; + + FOR_NSCREENS(j) { + stuff->dest = win->info[j].id; + result = ProcShapeRectangles (client); + if (result != Success) break; + } + return (result); +} +#endif + + +/************** + * ProcShapeMask + **************/ + + +static int +ProcShapeMask (ClientPtr client) +{ + WindowPtr pWin; + ScreenPtr pScreen; + REQUEST(xShapeMaskReq); + RegionPtr srcRgn; + RegionPtr *destRgn; + PixmapPtr pPixmap; + CreateDftPtr createDefault; + int rc; + + REQUEST_SIZE_MATCH (xShapeMaskReq); + UpdateCurrentTime(); + rc = dixLookupWindow(&pWin, stuff->dest, client, DixSetAttrAccess); + if (rc != Success) + return rc; + switch (stuff->destKind) { + case ShapeBounding: + createDefault = CreateBoundingShape; + break; + case ShapeClip: + createDefault = CreateClipShape; + break; + case ShapeInput: + createDefault = CreateBoundingShape; + break; + default: + client->errorValue = stuff->destKind; + return BadValue; + } + pScreen = pWin->drawable.pScreen; + if (stuff->src == None) + srcRgn = 0; + else { + rc = dixLookupResourceByType((pointer *)&pPixmap, stuff->src, RT_PIXMAP, + client, DixReadAccess); + if (rc != Success) + return (rc == BadValue) ? BadPixmap : rc; + if (pPixmap->drawable.pScreen != pScreen || + pPixmap->drawable.depth != 1) + return BadMatch; + srcRgn = BITMAP_TO_REGION(pScreen, pPixmap); + if (!srcRgn) + return BadAlloc; + } + + if (!pWin->optional) + MakeWindowOptional (pWin); + switch (stuff->destKind) { + case ShapeBounding: + destRgn = &pWin->optional->boundingShape; + break; + case ShapeClip: + destRgn = &pWin->optional->clipShape; + break; + case ShapeInput: + destRgn = &pWin->optional->inputShape; + break; + default: + return BadValue; + } + + return RegionOperate (client, pWin, (int)stuff->destKind, + destRgn, srcRgn, (int)stuff->op, + stuff->xOff, stuff->yOff, createDefault); +} + +#ifdef PANORAMIX +static int +ProcPanoramiXShapeMask( + ClientPtr client) +{ + REQUEST(xShapeMaskReq); + PanoramiXRes *win, *pmap; + int j, result; + + REQUEST_SIZE_MATCH (xShapeMaskReq); + + result = dixLookupResourceByType((pointer *)&win, stuff->dest, XRT_WINDOW, + client, DixWriteAccess); + if (result != Success) + return (result == BadValue) ? BadWindow : result; + + if(stuff->src != None) { + result = dixLookupResourceByType((pointer *)&pmap, stuff->src, + XRT_PIXMAP, client, DixReadAccess); + if (result != Success) + return (result == BadValue) ? BadPixmap : result; + } else + pmap = NULL; + + FOR_NSCREENS(j) { + stuff->dest = win->info[j].id; + if(pmap) + stuff->src = pmap->info[j].id; + result = ProcShapeMask (client); + if (result != Success) break; + } + return (result); +} +#endif + + +/************ + * ProcShapeCombine + ************/ + +static int +ProcShapeCombine (ClientPtr client) +{ + WindowPtr pSrcWin, pDestWin; + ScreenPtr pScreen; + REQUEST(xShapeCombineReq); + RegionPtr srcRgn; + RegionPtr *destRgn; + CreateDftPtr createDefault; + CreateDftPtr createSrc; + RegionPtr tmp; + int rc; + + REQUEST_SIZE_MATCH (xShapeCombineReq); + UpdateCurrentTime(); + rc = dixLookupWindow(&pDestWin, stuff->dest, client, DixSetAttrAccess); + if (rc != Success) + return rc; + if (!pDestWin->optional) + MakeWindowOptional (pDestWin); + switch (stuff->destKind) { + case ShapeBounding: + createDefault = CreateBoundingShape; + break; + case ShapeClip: + createDefault = CreateClipShape; + break; + case ShapeInput: + createDefault = CreateBoundingShape; + break; + default: + client->errorValue = stuff->destKind; + return BadValue; + } + pScreen = pDestWin->drawable.pScreen; + + rc = dixLookupWindow(&pSrcWin, stuff->src, client, DixGetAttrAccess); + if (rc != Success) + return rc; + switch (stuff->srcKind) { + case ShapeBounding: + srcRgn = wBoundingShape (pSrcWin); + createSrc = CreateBoundingShape; + break; + case ShapeClip: + srcRgn = wClipShape (pSrcWin); + createSrc = CreateClipShape; + break; + case ShapeInput: + srcRgn = wInputShape (pSrcWin); + createSrc = CreateBoundingShape; + break; + default: + client->errorValue = stuff->srcKind; + return BadValue; + } + if (pSrcWin->drawable.pScreen != pScreen) + { + return BadMatch; + } + + if (srcRgn) { + tmp = REGION_CREATE(pScreen, (BoxPtr) 0, 0); + REGION_COPY(pScreen, tmp, srcRgn); + srcRgn = tmp; + } else + srcRgn = (*createSrc) (pSrcWin); + + if (!pDestWin->optional) + MakeWindowOptional (pDestWin); + switch (stuff->destKind) { + case ShapeBounding: + destRgn = &pDestWin->optional->boundingShape; + break; + case ShapeClip: + destRgn = &pDestWin->optional->clipShape; + break; + case ShapeInput: + destRgn = &pDestWin->optional->inputShape; + break; + default: + return BadValue; + } + + return RegionOperate (client, pDestWin, (int)stuff->destKind, + destRgn, srcRgn, (int)stuff->op, + stuff->xOff, stuff->yOff, createDefault); +} + + +#ifdef PANORAMIX +static int +ProcPanoramiXShapeCombine( + ClientPtr client) +{ + REQUEST(xShapeCombineReq); + PanoramiXRes *win, *win2; + int j, result; + + REQUEST_AT_LEAST_SIZE (xShapeCombineReq); + + result = dixLookupResourceByType((pointer *)&win, stuff->dest, XRT_WINDOW, + client, DixWriteAccess); + if (result != Success) + return (result == BadValue) ? BadWindow : result; + + result = dixLookupResourceByType((pointer *)&win2, stuff->src, XRT_WINDOW, + client, DixReadAccess); + if (result != Success) + return (result == BadValue) ? BadWindow : result; + + FOR_NSCREENS(j) { + stuff->dest = win->info[j].id; + stuff->src = win2->info[j].id; + result = ProcShapeCombine (client); + if (result != Success) break; + } + return (result); +} +#endif + +/************* + * ProcShapeOffset + *************/ + +static int +ProcShapeOffset (ClientPtr client) +{ + WindowPtr pWin; + ScreenPtr pScreen; + REQUEST(xShapeOffsetReq); + RegionPtr srcRgn; + int rc; + + REQUEST_SIZE_MATCH (xShapeOffsetReq); + UpdateCurrentTime(); + rc = dixLookupWindow(&pWin, stuff->dest, client, DixSetAttrAccess); + if (rc != Success) + return rc; + switch (stuff->destKind) { + case ShapeBounding: + srcRgn = wBoundingShape (pWin); + break; + case ShapeClip: + srcRgn = wClipShape(pWin); + break; + case ShapeInput: + srcRgn = wInputShape (pWin); + break; + default: + client->errorValue = stuff->destKind; + return BadValue; + } + pScreen = pWin->drawable.pScreen; + if (srcRgn) + { + REGION_TRANSLATE(pScreen, srcRgn, stuff->xOff, stuff->yOff); + (*pScreen->SetShape) (pWin); + } + SendShapeNotify (pWin, (int)stuff->destKind); + return Success; +} + + +#ifdef PANORAMIX +static int +ProcPanoramiXShapeOffset( + ClientPtr client) +{ + REQUEST(xShapeOffsetReq); + PanoramiXRes *win; + int j, result; + + REQUEST_AT_LEAST_SIZE (xShapeOffsetReq); + + result = dixLookupResourceByType((pointer *)&win, stuff->dest, XRT_WINDOW, + client, DixWriteAccess); + if (result != Success) + return (result == BadValue) ? BadWindow : result; + + FOR_NSCREENS(j) { + stuff->dest = win->info[j].id; + result = ProcShapeOffset (client); + if(result != Success) break; + } + return (result); +} +#endif + + +static int +ProcShapeQueryExtents (ClientPtr client) +{ + REQUEST(xShapeQueryExtentsReq); + WindowPtr pWin; + xShapeQueryExtentsReply rep; + BoxRec extents, *pExtents; + int n, rc; + RegionPtr region; + + REQUEST_SIZE_MATCH (xShapeQueryExtentsReq); + rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); + if (rc != Success) + return rc; + memset(&rep, 0, sizeof(xShapeQueryExtentsReply)); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.boundingShaped = (wBoundingShape(pWin) != 0); + rep.clipShaped = (wClipShape(pWin) != 0); + if ((region = wBoundingShape(pWin))) { + /* this is done in two steps because of a compiler bug on SunOS 4.1.3 */ + pExtents = REGION_EXTENTS(pWin->drawable.pScreen, region); + extents = *pExtents; + } else { + extents.x1 = -wBorderWidth (pWin); + extents.y1 = -wBorderWidth (pWin); + extents.x2 = pWin->drawable.width + wBorderWidth (pWin); + extents.y2 = pWin->drawable.height + wBorderWidth (pWin); + } + rep.xBoundingShape = extents.x1; + rep.yBoundingShape = extents.y1; + rep.widthBoundingShape = extents.x2 - extents.x1; + rep.heightBoundingShape = extents.y2 - extents.y1; + if ((region = wClipShape(pWin))) { + /* this is done in two steps because of a compiler bug on SunOS 4.1.3 */ + pExtents = REGION_EXTENTS(pWin->drawable.pScreen, region); + extents = *pExtents; + } else { + extents.x1 = 0; + extents.y1 = 0; + extents.x2 = pWin->drawable.width; + extents.y2 = pWin->drawable.height; + } + rep.xClipShape = extents.x1; + rep.yClipShape = extents.y1; + rep.widthClipShape = extents.x2 - extents.x1; + rep.heightClipShape = extents.y2 - extents.y1; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.xBoundingShape, n); + swaps(&rep.yBoundingShape, n); + swaps(&rep.widthBoundingShape, n); + swaps(&rep.heightBoundingShape, n); + swaps(&rep.xClipShape, n); + swaps(&rep.yClipShape, n); + swaps(&rep.widthClipShape, n); + swaps(&rep.heightClipShape, n); + } + WriteToClient(client, sizeof (xShapeQueryExtentsReply), (char *)&rep); + return Success; +} + +/*ARGSUSED*/ +static int +ShapeFreeClient (pointer data, XID id) +{ + ShapeEventPtr pShapeEvent; + WindowPtr pWin; + ShapeEventPtr *pHead, pCur, pPrev; + int rc; + + pShapeEvent = (ShapeEventPtr) data; + pWin = pShapeEvent->window; + rc = dixLookupResourceByType((pointer *)&pHead, pWin->drawable.id, + ShapeEventType, serverClient, DixReadAccess); + if (rc == Success) { + pPrev = 0; + for (pCur = *pHead; pCur && pCur != pShapeEvent; pCur=pCur->next) + pPrev = pCur; + if (pCur) + { + if (pPrev) + pPrev->next = pShapeEvent->next; + else + *pHead = pShapeEvent->next; + } + } + free((pointer) pShapeEvent); + return 1; +} + +/*ARGSUSED*/ +static int +ShapeFreeEvents (pointer data, XID id) +{ + ShapeEventPtr *pHead, pCur, pNext; + + pHead = (ShapeEventPtr *) data; + for (pCur = *pHead; pCur; pCur = pNext) { + pNext = pCur->next; + FreeResource (pCur->clientResource, ClientType); + free((pointer) pCur); + } + free((pointer) pHead); + return 1; +} + +static int +ProcShapeSelectInput (ClientPtr client) +{ + REQUEST(xShapeSelectInputReq); + WindowPtr pWin; + ShapeEventPtr pShapeEvent, pNewShapeEvent, *pHead; + XID clientResource; + int rc; + + REQUEST_SIZE_MATCH (xShapeSelectInputReq); + rc = dixLookupWindow(&pWin, stuff->window, client, DixReceiveAccess); + if (rc != Success) + return rc; + rc = dixLookupResourceByType((pointer *)&pHead, pWin->drawable.id, + ShapeEventType, client, DixWriteAccess); + if (rc != Success && rc != BadValue) + return rc; + + switch (stuff->enable) { + case xTrue: + if (pHead) { + + /* check for existing entry. */ + for (pShapeEvent = *pHead; + pShapeEvent; + pShapeEvent = pShapeEvent->next) + { + if (pShapeEvent->client == client) + return Success; + } + } + + /* build the entry */ + pNewShapeEvent = malloc(sizeof (ShapeEventRec)); + if (!pNewShapeEvent) + return BadAlloc; + pNewShapeEvent->next = 0; + pNewShapeEvent->client = client; + pNewShapeEvent->window = pWin; + /* + * add a resource that will be deleted when + * the client goes away + */ + clientResource = FakeClientID (client->index); + pNewShapeEvent->clientResource = clientResource; + if (!AddResource (clientResource, ClientType, (pointer)pNewShapeEvent)) + return BadAlloc; + /* + * create a resource to contain a pointer to the list + * of clients selecting input. This must be indirect as + * the list may be arbitrarily rearranged which cannot be + * done through the resource database. + */ + if (!pHead) + { + pHead = malloc(sizeof (ShapeEventPtr)); + if (!pHead || + !AddResource (pWin->drawable.id, ShapeEventType, (pointer)pHead)) + { + FreeResource (clientResource, RT_NONE); + return BadAlloc; + } + *pHead = 0; + } + pNewShapeEvent->next = *pHead; + *pHead = pNewShapeEvent; + break; + case xFalse: + /* delete the interest */ + if (pHead) { + pNewShapeEvent = 0; + for (pShapeEvent = *pHead; pShapeEvent; pShapeEvent = pShapeEvent->next) { + if (pShapeEvent->client == client) + break; + pNewShapeEvent = pShapeEvent; + } + if (pShapeEvent) { + FreeResource (pShapeEvent->clientResource, ClientType); + if (pNewShapeEvent) + pNewShapeEvent->next = pShapeEvent->next; + else + *pHead = pShapeEvent->next; + free(pShapeEvent); + } + } + break; + default: + client->errorValue = stuff->enable; + return BadValue; + } + return Success; +} + +/* + * deliver the event + */ + +void +SendShapeNotify (WindowPtr pWin, int which) +{ + ShapeEventPtr *pHead, pShapeEvent; + ClientPtr client; + xShapeNotifyEvent se; + BoxRec extents; + RegionPtr region; + BYTE shaped; + int rc; + + rc = dixLookupResourceByType((pointer *)&pHead, pWin->drawable.id, + ShapeEventType, serverClient, DixReadAccess); + if (rc != Success) + return; + switch (which) { + case ShapeBounding: + region = wBoundingShape(pWin); + if (region) { + extents = *REGION_EXTENTS(pWin->drawable.pScreen, region); + shaped = xTrue; + } else { + extents.x1 = -wBorderWidth (pWin); + extents.y1 = -wBorderWidth (pWin); + extents.x2 = pWin->drawable.width + wBorderWidth (pWin); + extents.y2 = pWin->drawable.height + wBorderWidth (pWin); + shaped = xFalse; + } + break; + case ShapeClip: + region = wClipShape(pWin); + if (region) { + extents = *REGION_EXTENTS(pWin->drawable.pScreen, region); + shaped = xTrue; + } else { + extents.x1 = 0; + extents.y1 = 0; + extents.x2 = pWin->drawable.width; + extents.y2 = pWin->drawable.height; + shaped = xFalse; + } + break; + case ShapeInput: + region = wInputShape(pWin); + if (region) { + extents = *REGION_EXTENTS(pWin->drawable.pScreen, region); + shaped = xTrue; + } else { + extents.x1 = -wBorderWidth (pWin); + extents.y1 = -wBorderWidth (pWin); + extents.x2 = pWin->drawable.width + wBorderWidth (pWin); + extents.y2 = pWin->drawable.height + wBorderWidth (pWin); + shaped = xFalse; + } + break; + default: + return; + } + for (pShapeEvent = *pHead; pShapeEvent; pShapeEvent = pShapeEvent->next) { + client = pShapeEvent->client; + if (client == serverClient || client->clientGone) + continue; + se.type = ShapeNotify + ShapeEventBase; + se.kind = which; + se.window = pWin->drawable.id; + se.sequenceNumber = client->sequence; + se.x = extents.x1; + se.y = extents.y1; + se.width = extents.x2 - extents.x1; + se.height = extents.y2 - extents.y1; + se.time = currentTime.milliseconds; + se.shaped = shaped; + WriteEventsToClient (client, 1, (xEvent *) &se); + } +} + +static int +ProcShapeInputSelected (ClientPtr client) +{ + REQUEST(xShapeInputSelectedReq); + WindowPtr pWin; + ShapeEventPtr pShapeEvent, *pHead; + int enabled, rc; + xShapeInputSelectedReply rep; + int n; + + REQUEST_SIZE_MATCH (xShapeInputSelectedReq); + rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); + if (rc != Success) + return rc; + rc = dixLookupResourceByType((pointer *)&pHead, pWin->drawable.id, + ShapeEventType, client, DixReadAccess); + if (rc != Success && rc != BadValue) + return rc; + enabled = xFalse; + if (pHead) { + for (pShapeEvent = *pHead; + pShapeEvent; + pShapeEvent = pShapeEvent->next) + { + if (pShapeEvent->client == client) { + enabled = xTrue; + break; + } + } + } + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.enabled = enabled; + if (client->swapped) { + swaps (&rep.sequenceNumber, n); + swapl (&rep.length, n); + } + WriteToClient (client, sizeof (xShapeInputSelectedReply), (char *) &rep); + return Success; +} + +static int +ProcShapeGetRectangles (ClientPtr client) +{ + REQUEST(xShapeGetRectanglesReq); + WindowPtr pWin; + xShapeGetRectanglesReply rep; + xRectangle *rects; + int nrects, i, rc; + RegionPtr region; + int n; + + REQUEST_SIZE_MATCH(xShapeGetRectanglesReq); + rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); + if (rc != Success) + return rc; + switch (stuff->kind) { + case ShapeBounding: + region = wBoundingShape(pWin); + break; + case ShapeClip: + region = wClipShape(pWin); + break; + case ShapeInput: + region = wInputShape (pWin); + break; + default: + client->errorValue = stuff->kind; + return BadValue; + } + if (!region) { + nrects = 1; + rects = malloc(sizeof (xRectangle)); + if (!rects) + return BadAlloc; + switch (stuff->kind) { + case ShapeBounding: + rects->x = - (int) wBorderWidth (pWin); + rects->y = - (int) wBorderWidth (pWin); + rects->width = pWin->drawable.width + wBorderWidth (pWin); + rects->height = pWin->drawable.height + wBorderWidth (pWin); + break; + case ShapeClip: + rects->x = 0; + rects->y = 0; + rects->width = pWin->drawable.width; + rects->height = pWin->drawable.height; + break; + case ShapeInput: + rects->x = - (int) wBorderWidth (pWin); + rects->y = - (int) wBorderWidth (pWin); + rects->width = pWin->drawable.width + wBorderWidth (pWin); + rects->height = pWin->drawable.height + wBorderWidth (pWin); + break; + } + } else { + BoxPtr box; + nrects = REGION_NUM_RECTS(region); + box = REGION_RECTS(region); + rects = malloc(nrects * sizeof (xRectangle)); + if (!rects && nrects) + return BadAlloc; + for (i = 0; i < nrects; i++, box++) { + rects[i].x = box->x1; + rects[i].y = box->y1; + rects[i].width = box->x2 - box->x1; + rects[i].height = box->y2 - box->y1; + } + } + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = bytes_to_int32(nrects * sizeof (xRectangle)); + rep.ordering = YXBanded; + rep.nrects = nrects; + if (client->swapped) { + swaps (&rep.sequenceNumber, n); + swapl (&rep.length, n); + swapl (&rep.nrects, n); + SwapShorts ((short *)rects, (unsigned long)nrects * 4); + } + WriteToClient (client, sizeof (rep), (char *) &rep); + WriteToClient (client, nrects * sizeof (xRectangle), (char *) rects); + free(rects); + return Success; +} + +static int +ProcShapeDispatch (ClientPtr client) +{ + REQUEST(xReq); + switch (stuff->data) { + case X_ShapeQueryVersion: + return ProcShapeQueryVersion (client); + case X_ShapeRectangles: +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + return ProcPanoramiXShapeRectangles (client); + else +#endif + return ProcShapeRectangles (client); + case X_ShapeMask: +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + return ProcPanoramiXShapeMask (client); + else +#endif + return ProcShapeMask (client); + case X_ShapeCombine: +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + return ProcPanoramiXShapeCombine (client); + else +#endif + return ProcShapeCombine (client); + case X_ShapeOffset: +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + return ProcPanoramiXShapeOffset (client); + else +#endif + return ProcShapeOffset (client); + case X_ShapeQueryExtents: + return ProcShapeQueryExtents (client); + case X_ShapeSelectInput: + return ProcShapeSelectInput (client); + case X_ShapeInputSelected: + return ProcShapeInputSelected (client); + case X_ShapeGetRectangles: + return ProcShapeGetRectangles (client); + default: + return BadRequest; + } +} + +static void +SShapeNotifyEvent(xShapeNotifyEvent *from, xShapeNotifyEvent *to) +{ + to->type = from->type; + to->kind = from->kind; + cpswapl (from->window, to->window); + cpswaps (from->sequenceNumber, to->sequenceNumber); + cpswaps (from->x, to->x); + cpswaps (from->y, to->y); + cpswaps (from->width, to->width); + cpswaps (from->height, to->height); + cpswapl (from->time, to->time); + to->shaped = from->shaped; +} + +static int +SProcShapeQueryVersion (ClientPtr client) +{ + int n; + REQUEST (xShapeQueryVersionReq); + + swaps (&stuff->length, n); + return ProcShapeQueryVersion (client); +} + +static int +SProcShapeRectangles (ClientPtr client) +{ + char n; + REQUEST (xShapeRectanglesReq); + + swaps (&stuff->length, n); + REQUEST_AT_LEAST_SIZE (xShapeRectanglesReq); + swapl (&stuff->dest, n); + swaps (&stuff->xOff, n); + swaps (&stuff->yOff, n); + SwapRestS(stuff); + return ProcShapeRectangles (client); +} + +static int +SProcShapeMask (ClientPtr client) +{ + char n; + REQUEST (xShapeMaskReq); + + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH (xShapeMaskReq); + swapl (&stuff->dest, n); + swaps (&stuff->xOff, n); + swaps (&stuff->yOff, n); + swapl (&stuff->src, n); + return ProcShapeMask (client); +} + +static int +SProcShapeCombine (ClientPtr client) +{ + char n; + REQUEST (xShapeCombineReq); + + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH (xShapeCombineReq); + swapl (&stuff->dest, n); + swaps (&stuff->xOff, n); + swaps (&stuff->yOff, n); + swapl (&stuff->src, n); + return ProcShapeCombine (client); +} + +static int +SProcShapeOffset (ClientPtr client) +{ + char n; + REQUEST (xShapeOffsetReq); + + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH (xShapeOffsetReq); + swapl (&stuff->dest, n); + swaps (&stuff->xOff, n); + swaps (&stuff->yOff, n); + return ProcShapeOffset (client); +} + +static int +SProcShapeQueryExtents (ClientPtr client) +{ + char n; + REQUEST (xShapeQueryExtentsReq); + + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH (xShapeQueryExtentsReq); + swapl (&stuff->window, n); + return ProcShapeQueryExtents (client); +} + +static int +SProcShapeSelectInput (ClientPtr client) +{ + char n; + REQUEST (xShapeSelectInputReq); + + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH (xShapeSelectInputReq); + swapl (&stuff->window, n); + return ProcShapeSelectInput (client); +} + +static int +SProcShapeInputSelected (ClientPtr client) +{ + int n; + REQUEST (xShapeInputSelectedReq); + + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH (xShapeInputSelectedReq); + swapl (&stuff->window, n); + return ProcShapeInputSelected (client); +} + +static int +SProcShapeGetRectangles (ClientPtr client) +{ + REQUEST(xShapeGetRectanglesReq); + char n; + + swaps (&stuff->length, n); + REQUEST_SIZE_MATCH(xShapeGetRectanglesReq); + swapl (&stuff->window, n); + return ProcShapeGetRectangles (client); +} + +static int +SProcShapeDispatch (ClientPtr client) +{ + REQUEST(xReq); + switch (stuff->data) { + case X_ShapeQueryVersion: + return SProcShapeQueryVersion (client); + case X_ShapeRectangles: + return SProcShapeRectangles (client); + case X_ShapeMask: + return SProcShapeMask (client); + case X_ShapeCombine: + return SProcShapeCombine (client); + case X_ShapeOffset: + return SProcShapeOffset (client); + case X_ShapeQueryExtents: + return SProcShapeQueryExtents (client); + case X_ShapeSelectInput: + return SProcShapeSelectInput (client); + case X_ShapeInputSelected: + return SProcShapeInputSelected (client); + case X_ShapeGetRectangles: + return SProcShapeGetRectangles (client); + default: + return BadRequest; + } +} diff --git a/xorg-server/Xext/shm.c b/xorg-server/Xext/shm.c index ab58c2750..0d78fbc06 100644 --- a/xorg-server/Xext/shm.c +++ b/xorg-server/Xext/shm.c @@ -1,1329 +1,1329 @@ -/************************************************************ - -Copyright 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. - -********************************************************/ - -/* THIS IS NOT AN X CONSORTIUM STANDARD OR AN X PROJECT TEAM SPECIFICATION */ - - -#define SHM - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include -#include -#include -#include "misc.h" -#include "os.h" -#include "dixstruct.h" -#include "resource.h" -#include "scrnintstr.h" -#include "windowstr.h" -#include "pixmapstr.h" -#include "gcstruct.h" -#include "extnsionst.h" -#include "servermd.h" -#include "shmint.h" -#include "xace.h" -#include -#include -#include "protocol-versions.h" - -/* Needed for Solaris cross-zone shared memory extension */ -#ifdef HAVE_SHMCTL64 -#include -#define SHMSTAT(id, buf) shmctl64(id, IPC_STAT64, buf) -#define SHMSTAT_TYPE struct shmid_ds64 -#define SHMPERM_TYPE struct ipc_perm64 -#define SHM_PERM(buf) buf.shmx_perm -#define SHM_SEGSZ(buf) buf.shmx_segsz -#define SHMPERM_UID(p) p->ipcx_uid -#define SHMPERM_CUID(p) p->ipcx_cuid -#define SHMPERM_GID(p) p->ipcx_gid -#define SHMPERM_CGID(p) p->ipcx_cgid -#define SHMPERM_MODE(p) p->ipcx_mode -#define SHMPERM_ZONEID(p) p->ipcx_zoneid -#else -#define SHMSTAT(id, buf) shmctl(id, IPC_STAT, buf) -#define SHMSTAT_TYPE struct shmid_ds -#define SHMPERM_TYPE struct ipc_perm -#define SHM_PERM(buf) buf.shm_perm -#define SHM_SEGSZ(buf) buf.shm_segsz -#define SHMPERM_UID(p) p->uid -#define SHMPERM_CUID(p) p->cuid -#define SHMPERM_GID(p) p->gid -#define SHMPERM_CGID(p) p->cgid -#define SHMPERM_MODE(p) p->mode -#endif - -#ifdef PANORAMIX -#include "panoramiX.h" -#include "panoramiXsrv.h" -#endif - -#include "modinit.h" - -typedef struct _ShmDesc { - struct _ShmDesc *next; - int shmid; - int refcnt; - char *addr; - Bool writable; - unsigned long size; -} ShmDescRec, *ShmDescPtr; - -typedef struct _ShmScrPrivateRec { - CloseScreenProcPtr CloseScreen; - ShmFuncsPtr shmFuncs; - DestroyPixmapProcPtr destroyPixmap; -} ShmScrPrivateRec; - -static PixmapPtr fbShmCreatePixmap(XSHM_CREATE_PIXMAP_ARGS); -static int ShmDetachSegment( - pointer /* value */, - XID /* shmseg */ - ); -static void ShmResetProc( - ExtensionEntry * /* extEntry */ - ); -static void SShmCompletionEvent( - xShmCompletionEvent * /* from */, - xShmCompletionEvent * /* to */ - ); - -static Bool ShmDestroyPixmap (PixmapPtr pPixmap); - -static DISPATCH_PROC(ProcShmAttach); -static DISPATCH_PROC(ProcShmCreatePixmap); -static DISPATCH_PROC(ProcShmDetach); -static DISPATCH_PROC(ProcShmDispatch); -static DISPATCH_PROC(ProcShmGetImage); -static DISPATCH_PROC(ProcShmPutImage); -static DISPATCH_PROC(ProcShmQueryVersion); -static DISPATCH_PROC(SProcShmAttach); -static DISPATCH_PROC(SProcShmCreatePixmap); -static DISPATCH_PROC(SProcShmDetach); -static DISPATCH_PROC(SProcShmDispatch); -static DISPATCH_PROC(SProcShmGetImage); -static DISPATCH_PROC(SProcShmPutImage); -static DISPATCH_PROC(SProcShmQueryVersion); - -static unsigned char ShmReqCode; -int ShmCompletionCode; -int BadShmSegCode; -RESTYPE ShmSegType; -static ShmDescPtr Shmsegs; -static Bool sharedPixmaps; -static int shmScrPrivateKeyIndex; -static DevPrivateKey shmScrPrivateKey = &shmScrPrivateKeyIndex; -static int shmPixmapPrivateIndex; -static DevPrivateKey shmPixmapPrivate = &shmPixmapPrivateIndex; -static ShmFuncs miFuncs = {NULL, NULL}; -static ShmFuncs fbFuncs = {fbShmCreatePixmap, NULL}; - -#define ShmGetScreenPriv(s) ((ShmScrPrivateRec *)dixLookupPrivate(&(s)->devPrivates, shmScrPrivateKey)) - -#define VERIFY_SHMSEG(shmseg,shmdesc,client) \ -{ \ - int rc; \ - rc = dixLookupResourceByType((pointer *)&(shmdesc), shmseg, ShmSegType, \ - client, DixReadAccess); \ - if (rc != Success) \ - return (rc == BadValue) ? BadShmSegCode : rc; \ -} - -#define VERIFY_SHMPTR(shmseg,offset,needwrite,shmdesc,client) \ -{ \ - VERIFY_SHMSEG(shmseg, shmdesc, client); \ - if ((offset & 3) || (offset > shmdesc->size)) \ - { \ - client->errorValue = offset; \ - return BadValue; \ - } \ - if (needwrite && !shmdesc->writable) \ - return BadAccess; \ -} - -#define VERIFY_SHMSIZE(shmdesc,offset,len,client) \ -{ \ - if ((offset + len) > shmdesc->size) \ - { \ - return BadAccess; \ - } \ -} - - -#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__CYGWIN__) || defined(__DragonFly__) -#include - -static Bool badSysCall = FALSE; - -static void -SigSysHandler(int signo) -{ - badSysCall = TRUE; -} - -static Bool CheckForShmSyscall(void) -{ - void (*oldHandler)(); - int shmid = -1; - - /* If no SHM support in the kernel, the bad syscall will generate SIGSYS */ - oldHandler = signal(SIGSYS, SigSysHandler); - - badSysCall = FALSE; - shmid = shmget(IPC_PRIVATE, 4096, IPC_CREAT); - - if (shmid != -1) - { - /* Successful allocation - clean up */ - shmctl(shmid, IPC_RMID, NULL); - } - else - { - /* Allocation failed */ - badSysCall = TRUE; - } - signal(SIGSYS, oldHandler); - return(!badSysCall); -} - -#define MUST_CHECK_FOR_SHM_SYSCALL - -#endif - -static Bool -ShmCloseScreen(int i, ScreenPtr pScreen) -{ - ShmScrPrivateRec *screen_priv = ShmGetScreenPriv(pScreen); - pScreen->CloseScreen = screen_priv->CloseScreen; - dixSetPrivate(&pScreen->devPrivates, shmScrPrivateKey, NULL); - xfree (screen_priv); - return (*pScreen->CloseScreen) (i, pScreen); -} - -static ShmScrPrivateRec * -ShmInitScreenPriv(ScreenPtr pScreen) -{ - ShmScrPrivateRec *screen_priv = ShmGetScreenPriv(pScreen); - if (!screen_priv) - { - screen_priv = xcalloc (1, sizeof (ShmScrPrivateRec)); - screen_priv->CloseScreen = pScreen->CloseScreen; - dixSetPrivate(&pScreen->devPrivates, shmScrPrivateKey, screen_priv); - pScreen->CloseScreen = ShmCloseScreen; - } - return screen_priv; -} - -void -ShmExtensionInit(INITARGS) -{ - ExtensionEntry *extEntry; - int i; - -#ifdef MUST_CHECK_FOR_SHM_SYSCALL - if (!CheckForShmSyscall()) - { - ErrorF("MIT-SHM extension disabled due to lack of kernel support\n"); - return; - } -#endif - - sharedPixmaps = xFalse; - { - sharedPixmaps = xTrue; - for (i = 0; i < screenInfo.numScreens; i++) - { - ShmScrPrivateRec *screen_priv = ShmInitScreenPriv(screenInfo.screens[i]); - if (!screen_priv->shmFuncs) - screen_priv->shmFuncs = &miFuncs; - if (!screen_priv->shmFuncs->CreatePixmap) - sharedPixmaps = xFalse; - } - if (sharedPixmaps) - for (i = 0; i < screenInfo.numScreens; i++) - { - ShmScrPrivateRec *screen_priv = ShmGetScreenPriv(screenInfo.screens[i]); - screen_priv->destroyPixmap = screenInfo.screens[i]->DestroyPixmap; - screenInfo.screens[i]->DestroyPixmap = ShmDestroyPixmap; - } - } - ShmSegType = CreateNewResourceType(ShmDetachSegment, "ShmSeg"); - if (ShmSegType && - (extEntry = AddExtension(SHMNAME, ShmNumberEvents, ShmNumberErrors, - ProcShmDispatch, SProcShmDispatch, - ShmResetProc, StandardMinorOpcode))) - { - ShmReqCode = (unsigned char)extEntry->base; - ShmCompletionCode = extEntry->eventBase; - BadShmSegCode = extEntry->errorBase; - EventSwapVector[ShmCompletionCode] = (EventSwapPtr) SShmCompletionEvent; - } -} - -/*ARGSUSED*/ -static void -ShmResetProc(ExtensionEntry *extEntry) -{ - int i; - for (i = 0; i < screenInfo.numScreens; i++) - ShmRegisterFuncs(screenInfo.screens[i], NULL); -} - -void -ShmRegisterFuncs(ScreenPtr pScreen, ShmFuncsPtr funcs) -{ - ShmInitScreenPriv(pScreen)->shmFuncs = funcs; -} - -static Bool -ShmDestroyPixmap (PixmapPtr pPixmap) -{ - ScreenPtr pScreen = pPixmap->drawable.pScreen; - ShmScrPrivateRec *screen_priv = ShmGetScreenPriv(pScreen); - Bool ret; - if (pPixmap->refcnt == 1) - { - ShmDescPtr shmdesc; - shmdesc = (ShmDescPtr)dixLookupPrivate(&pPixmap->devPrivates, - shmPixmapPrivate); - if (shmdesc) - ShmDetachSegment ((pointer) shmdesc, pPixmap->drawable.id); - } - - pScreen->DestroyPixmap = screen_priv->destroyPixmap; - ret = (*pScreen->DestroyPixmap) (pPixmap); - screen_priv->destroyPixmap = pScreen->DestroyPixmap; - pScreen->DestroyPixmap = ShmDestroyPixmap; - return ret; -} - -void -ShmRegisterFbFuncs(ScreenPtr pScreen) -{ - ShmRegisterFuncs(pScreen, &fbFuncs); -} - -static int -ProcShmQueryVersion(ClientPtr client) -{ - xShmQueryVersionReply rep; - int n; - - REQUEST_SIZE_MATCH(xShmQueryVersionReq); - memset(&rep, 0, sizeof(xShmQueryVersionReply)); - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.sharedPixmaps = sharedPixmaps; - rep.pixmapFormat = sharedPixmaps ? ZPixmap : 0; - rep.majorVersion = SERVER_SHM_MAJOR_VERSION; - rep.minorVersion = SERVER_SHM_MINOR_VERSION; - rep.uid = geteuid(); - rep.gid = getegid(); - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swaps(&rep.majorVersion, n); - swaps(&rep.minorVersion, n); - swaps(&rep.uid, n); - swaps(&rep.gid, n); - } - WriteToClient(client, sizeof(xShmQueryVersionReply), (char *)&rep); - return (client->noClientException); -} - -/* - * Simulate the access() system call for a shared memory segement, - * using the credentials from the client if available - */ -static int -shm_access(ClientPtr client, SHMPERM_TYPE *perm, int readonly) -{ - int uid, gid; - mode_t mask; - int uidset = 0, gidset = 0; - LocalClientCredRec *lcc; - - if (GetLocalClientCreds(client, &lcc) != -1) { - - if (lcc->fieldsSet & LCC_UID_SET) { - uid = lcc->euid; - uidset = 1; - } - if (lcc->fieldsSet & LCC_GID_SET) { - gid = lcc->egid; - gidset = 1; - } - -#if defined(HAVE_GETZONEID) && defined(SHMPERM_ZONEID) - if ( ((lcc->fieldsSet & LCC_ZID_SET) == 0) || (lcc->zoneid == -1) - || (lcc->zoneid != SHMPERM_ZONEID(perm))) { - uidset = 0; - gidset = 0; - } -#endif - FreeLocalClientCreds(lcc); - - if (uidset) { - /* User id 0 always gets access */ - if (uid == 0) { - return 0; - } - /* Check the owner */ - if (SHMPERM_UID(perm) == uid || SHMPERM_CUID(perm) == uid) { - mask = S_IRUSR; - if (!readonly) { - mask |= S_IWUSR; - } - return (SHMPERM_MODE(perm) & mask) == mask ? 0 : -1; - } - } - - if (gidset) { - /* Check the group */ - if (SHMPERM_GID(perm) == gid || SHMPERM_CGID(perm) == gid) { - mask = S_IRGRP; - if (!readonly) { - mask |= S_IWGRP; - } - return (SHMPERM_MODE(perm) & mask) == mask ? 0 : -1; - } - } - } - /* Otherwise, check everyone else */ - mask = S_IROTH; - if (!readonly) { - mask |= S_IWOTH; - } - return (SHMPERM_MODE(perm) & mask) == mask ? 0 : -1; -} - -static int -ProcShmAttach(ClientPtr client) -{ - SHMSTAT_TYPE buf; - ShmDescPtr shmdesc; - REQUEST(xShmAttachReq); - - REQUEST_SIZE_MATCH(xShmAttachReq); - LEGAL_NEW_RESOURCE(stuff->shmseg, client); - if ((stuff->readOnly != xTrue) && (stuff->readOnly != xFalse)) - { - client->errorValue = stuff->readOnly; - return(BadValue); - } - for (shmdesc = Shmsegs; - shmdesc && (shmdesc->shmid != stuff->shmid); - shmdesc = shmdesc->next) - ; - if (shmdesc) - { - if (!stuff->readOnly && !shmdesc->writable) - return BadAccess; - shmdesc->refcnt++; - } - else - { - shmdesc = xalloc(sizeof(ShmDescRec)); - if (!shmdesc) - return BadAlloc; - shmdesc->addr = shmat(stuff->shmid, 0, - stuff->readOnly ? SHM_RDONLY : 0); - if ((shmdesc->addr == ((char *)-1)) || - SHMSTAT(stuff->shmid, &buf)) - { - xfree(shmdesc); - return BadAccess; - } - - /* The attach was performed with root privs. We must - * do manual checking of access rights for the credentials - * of the client */ - - if (shm_access(client, &(SHM_PERM(buf)), stuff->readOnly) == -1) { - shmdt(shmdesc->addr); - xfree(shmdesc); - return BadAccess; - } - - shmdesc->shmid = stuff->shmid; - shmdesc->refcnt = 1; - shmdesc->writable = !stuff->readOnly; - shmdesc->size = SHM_SEGSZ(buf); - shmdesc->next = Shmsegs; - Shmsegs = shmdesc; - } - if (!AddResource(stuff->shmseg, ShmSegType, (pointer)shmdesc)) - return BadAlloc; - return(client->noClientException); -} - -/*ARGSUSED*/ -static int -ShmDetachSegment(pointer value, /* must conform to DeleteType */ - XID shmseg) -{ - ShmDescPtr shmdesc = (ShmDescPtr)value; - ShmDescPtr *prev; - - if (--shmdesc->refcnt) - return TRUE; - shmdt(shmdesc->addr); - for (prev = &Shmsegs; *prev != shmdesc; prev = &(*prev)->next) - ; - *prev = shmdesc->next; - xfree(shmdesc); - return Success; -} - -static int -ProcShmDetach(ClientPtr client) -{ - ShmDescPtr shmdesc; - REQUEST(xShmDetachReq); - - REQUEST_SIZE_MATCH(xShmDetachReq); - VERIFY_SHMSEG(stuff->shmseg, shmdesc, client); - FreeResource(stuff->shmseg, RT_NONE); - return(client->noClientException); -} - -/* - * If the given request doesn't exactly match PutImage's constraints, - * wrap the image in a scratch pixmap header and let CopyArea sort it out. - */ -static void -doShmPutImage(DrawablePtr dst, GCPtr pGC, - int depth, unsigned int format, - int w, int h, int sx, int sy, int sw, int sh, int dx, int dy, - char *data) -{ - PixmapPtr pPixmap; - - if (format == ZPixmap || depth == 1) { - pPixmap = GetScratchPixmapHeader(dst->pScreen, w, h, depth, - BitsPerPixel(depth), - PixmapBytePad(w, depth), - data); - if (!pPixmap) - return; - pGC->ops->CopyArea((DrawablePtr)pPixmap, dst, pGC, sx, sy, sw, sh, dx, dy); - FreeScratchPixmapHeader(pPixmap); - } else { - GCPtr putGC = GetScratchGC(depth, dst->pScreen); - - if (!putGC) - return; - - pPixmap = (*dst->pScreen->CreatePixmap)(dst->pScreen, sw, sh, depth, - CREATE_PIXMAP_USAGE_SCRATCH); - if (!pPixmap) { - FreeScratchGC(putGC); - return; - } - ValidateGC(&pPixmap->drawable, putGC); - (*putGC->ops->PutImage)(&pPixmap->drawable, putGC, depth, -sx, -sy, w, h, 0, - (format == XYPixmap) ? XYPixmap : ZPixmap, data); - FreeScratchGC(putGC); - if (format == XYBitmap) - (void)(*pGC->ops->CopyPlane)(&pPixmap->drawable, dst, pGC, 0, 0, sw, sh, - dx, dy, 1L); - else - (void)(*pGC->ops->CopyArea)(&pPixmap->drawable, dst, pGC, 0, 0, sw, sh, - dx, dy); - (*pPixmap->drawable.pScreen->DestroyPixmap)(pPixmap); - } -} - -#ifdef PANORAMIX -static int -ProcPanoramiXShmPutImage(ClientPtr client) -{ - int j, result, orig_x, orig_y; - PanoramiXRes *draw, *gc; - Bool sendEvent, isRoot; - - REQUEST(xShmPutImageReq); - REQUEST_SIZE_MATCH(xShmPutImageReq); - - result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable, - XRC_DRAWABLE, client, DixWriteAccess); - if (result != Success) - return (result == BadValue) ? BadDrawable : result; - - result = dixLookupResourceByType((pointer *)&gc, stuff->gc, - XRT_GC, client, DixReadAccess); - if (result != Success) - return (result == BadValue) ? BadGC : result; - - isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; - - orig_x = stuff->dstX; - orig_y = stuff->dstY; - sendEvent = stuff->sendEvent; - stuff->sendEvent = 0; - FOR_NSCREENS(j) { - if(!j) stuff->sendEvent = sendEvent; - stuff->drawable = draw->info[j].id; - stuff->gc = gc->info[j].id; - if (isRoot) { - stuff->dstX = orig_x - panoramiXdataPtr[j].x; - stuff->dstY = orig_y - panoramiXdataPtr[j].y; - } - result = ProcShmPutImage(client); - if(result != client->noClientException) break; - } - return(result); -} - -static int -ProcPanoramiXShmGetImage(ClientPtr client) -{ - PanoramiXRes *draw; - DrawablePtr *drawables; - DrawablePtr pDraw; - xShmGetImageReply xgi; - ShmDescPtr shmdesc; - int i, x, y, w, h, format, rc; - Mask plane = 0, planemask; - long lenPer = 0, length, widthBytesLine; - Bool isRoot; - - REQUEST(xShmGetImageReq); - - REQUEST_SIZE_MATCH(xShmGetImageReq); - - if ((stuff->format != XYPixmap) && (stuff->format != ZPixmap)) { - client->errorValue = stuff->format; - return(BadValue); - } - - rc = dixLookupResourceByClass((pointer *)&draw, stuff->drawable, - XRC_DRAWABLE, client, DixWriteAccess); - if (rc != Success) - return (rc == BadValue) ? BadDrawable : rc; - - if (draw->type == XRT_PIXMAP) - return ProcShmGetImage(client); - - rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0, - DixReadAccess); - if (rc != Success) - return rc; - - VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); - - x = stuff->x; - y = stuff->y; - w = stuff->width; - h = stuff->height; - format = stuff->format; - planemask = stuff->planeMask; - - isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; - - if(isRoot) { - if( /* check for being onscreen */ - x < 0 || x + w > PanoramiXPixWidth || - y < 0 || y + h > PanoramiXPixHeight ) - return(BadMatch); - } else { - if( /* check for being onscreen */ - panoramiXdataPtr[0].x + pDraw->x + x < 0 || - panoramiXdataPtr[0].x + pDraw->x + x + w > PanoramiXPixWidth || - panoramiXdataPtr[0].y + pDraw->y + y < 0 || - panoramiXdataPtr[0].y + pDraw->y + y + h > PanoramiXPixHeight || - /* check for being inside of border */ - x < - wBorderWidth((WindowPtr)pDraw) || - x + w > wBorderWidth((WindowPtr)pDraw) + (int)pDraw->width || - y < -wBorderWidth((WindowPtr)pDraw) || - y + h > wBorderWidth ((WindowPtr)pDraw) + (int)pDraw->height) - return(BadMatch); - } - - drawables = xcalloc(PanoramiXNumScreens, sizeof(DrawablePtr)); - if(!drawables) - return(BadAlloc); - - drawables[0] = pDraw; - for(i = 1; i < PanoramiXNumScreens; i++) { - rc = dixLookupDrawable(drawables+i, draw->info[i].id, client, 0, - DixReadAccess); - if (rc != Success) - { - xfree(drawables); - return rc; - } - } - - xgi.visual = wVisual(((WindowPtr)pDraw)); - xgi.type = X_Reply; - xgi.length = 0; - xgi.sequenceNumber = client->sequence; - xgi.depth = pDraw->depth; - - if(format == ZPixmap) { - widthBytesLine = PixmapBytePad(w, pDraw->depth); - length = widthBytesLine * h; - } else { - widthBytesLine = PixmapBytePad(w, 1); - lenPer = widthBytesLine * h; - plane = ((Mask)1) << (pDraw->depth - 1); - length = lenPer * Ones(planemask & (plane | (plane - 1))); - } - - VERIFY_SHMSIZE(shmdesc, stuff->offset, length, client); - xgi.size = length; - - if (length == 0) {/* nothing to do */ } - else if (format == ZPixmap) { - XineramaGetImageData(drawables, x, y, w, h, format, planemask, - shmdesc->addr + stuff->offset, - widthBytesLine, isRoot); - } else { - - length = stuff->offset; - for (; plane; plane >>= 1) { - if (planemask & plane) { - XineramaGetImageData(drawables, x, y, w, h, - format, plane, shmdesc->addr + length, - widthBytesLine, isRoot); - length += lenPer; - } - } - } - xfree(drawables); - - if (client->swapped) { - int n; - swaps(&xgi.sequenceNumber, n); - swapl(&xgi.length, n); - swapl(&xgi.visual, n); - swapl(&xgi.size, n); - } - WriteToClient(client, sizeof(xShmGetImageReply), (char *)&xgi); - - return(client->noClientException); -} - -static int -ProcPanoramiXShmCreatePixmap(ClientPtr client) -{ - ScreenPtr pScreen = NULL; - PixmapPtr pMap = NULL; - DrawablePtr pDraw; - DepthPtr pDepth; - int i, j, result, rc; - ShmDescPtr shmdesc; - REQUEST(xShmCreatePixmapReq); - unsigned int width, height, depth; - unsigned long size; - PanoramiXRes *newPix; - - REQUEST_SIZE_MATCH(xShmCreatePixmapReq); - client->errorValue = stuff->pid; - if (!sharedPixmaps) - return BadImplementation; - LEGAL_NEW_RESOURCE(stuff->pid, client); - rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY, - DixGetAttrAccess); - if (rc != Success) - return rc; - - VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); - - width = stuff->width; - height = stuff->height; - depth = stuff->depth; - if (!width || !height || !depth) - { - client->errorValue = 0; - return BadValue; - } - if (width > 32767 || height > 32767) - return BadAlloc; - - if (stuff->depth != 1) - { - pDepth = pDraw->pScreen->allowedDepths; - for (i=0; ipScreen->numDepths; i++, pDepth++) - if (pDepth->depth == stuff->depth) - goto CreatePmap; - client->errorValue = stuff->depth; - return BadValue; - } - -CreatePmap: - size = PixmapBytePad(width, depth) * height; - if (sizeof(size) == 4 && BitsPerPixel(depth) > 8) { - if (size < width * height) - return BadAlloc; - } - /* thankfully, offset is unsigned */ - if (stuff->offset + size < size) - return BadAlloc; - - VERIFY_SHMSIZE(shmdesc, stuff->offset, size, client); - - if(!(newPix = xalloc(sizeof(PanoramiXRes)))) - return BadAlloc; - - newPix->type = XRT_PIXMAP; - newPix->u.pix.shared = TRUE; - newPix->info[0].id = stuff->pid; - for(j = 1; j < PanoramiXNumScreens; j++) - newPix->info[j].id = FakeClientID(client->index); - - result = (client->noClientException); - - FOR_NSCREENS(j) { - ShmScrPrivateRec *screen_priv; - pScreen = screenInfo.screens[j]; - - screen_priv = ShmGetScreenPriv(pScreen); - pMap = (*screen_priv->shmFuncs->CreatePixmap)(pScreen, - stuff->width, stuff->height, stuff->depth, - shmdesc->addr + stuff->offset); - - if (pMap) { - dixSetPrivate(&pMap->devPrivates, shmPixmapPrivate, shmdesc); - shmdesc->refcnt++; - pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER; - pMap->drawable.id = newPix->info[j].id; - if (!AddResource(newPix->info[j].id, RT_PIXMAP, (pointer)pMap)) { - (*pScreen->DestroyPixmap)(pMap); - result = BadAlloc; - break; - } - } else { - result = BadAlloc; - break; - } - } - - if(result == BadAlloc) { - while(j--) { - (*pScreen->DestroyPixmap)(pMap); - FreeResource(newPix->info[j].id, RT_NONE); - } - xfree(newPix); - } else - AddResource(stuff->pid, XRT_PIXMAP, newPix); - - return result; -} - -#endif - -static int -ProcShmPutImage(ClientPtr client) -{ - GCPtr pGC; - DrawablePtr pDraw; - long length; - ShmDescPtr shmdesc; - REQUEST(xShmPutImageReq); - - REQUEST_SIZE_MATCH(xShmPutImageReq); - VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); - VERIFY_SHMPTR(stuff->shmseg, stuff->offset, FALSE, shmdesc, client); - if ((stuff->sendEvent != xTrue) && (stuff->sendEvent != xFalse)) - return BadValue; - if (stuff->format == XYBitmap) - { - if (stuff->depth != 1) - return BadMatch; - length = PixmapBytePad(stuff->totalWidth, 1); - } - else if (stuff->format == XYPixmap) - { - if (pDraw->depth != stuff->depth) - return BadMatch; - length = PixmapBytePad(stuff->totalWidth, 1); - length *= stuff->depth; - } - else if (stuff->format == ZPixmap) - { - if (pDraw->depth != stuff->depth) - return BadMatch; - length = PixmapBytePad(stuff->totalWidth, stuff->depth); - } - else - { - client->errorValue = stuff->format; - return BadValue; - } - - /* - * There's a potential integer overflow in this check: - * VERIFY_SHMSIZE(shmdesc, stuff->offset, length * stuff->totalHeight, - * client); - * the version below ought to avoid it - */ - if (stuff->totalHeight != 0 && - length > (shmdesc->size - stuff->offset)/stuff->totalHeight) { - client->errorValue = stuff->totalWidth; - return BadValue; - } - if (stuff->srcX > stuff->totalWidth) - { - client->errorValue = stuff->srcX; - return BadValue; - } - if (stuff->srcY > stuff->totalHeight) - { - client->errorValue = stuff->srcY; - return BadValue; - } - if ((stuff->srcX + stuff->srcWidth) > stuff->totalWidth) - { - client->errorValue = stuff->srcWidth; - return BadValue; - } - if ((stuff->srcY + stuff->srcHeight) > stuff->totalHeight) - { - client->errorValue = stuff->srcHeight; - return BadValue; - } - - if ((((stuff->format == ZPixmap) && (stuff->srcX == 0)) || - ((stuff->format != ZPixmap) && - (stuff->srcX < screenInfo.bitmapScanlinePad) && - ((stuff->format == XYBitmap) || - ((stuff->srcY == 0) && - (stuff->srcHeight == stuff->totalHeight))))) && - ((stuff->srcX + stuff->srcWidth) == stuff->totalWidth)) - (*pGC->ops->PutImage) (pDraw, pGC, stuff->depth, - stuff->dstX, stuff->dstY, - stuff->totalWidth, stuff->srcHeight, - stuff->srcX, stuff->format, - shmdesc->addr + stuff->offset + - (stuff->srcY * length)); - else - doShmPutImage(pDraw, pGC, stuff->depth, stuff->format, - stuff->totalWidth, stuff->totalHeight, - stuff->srcX, stuff->srcY, - stuff->srcWidth, stuff->srcHeight, - stuff->dstX, stuff->dstY, - shmdesc->addr + stuff->offset); - - if (stuff->sendEvent) - { - xShmCompletionEvent ev; - - ev.type = ShmCompletionCode; - ev.drawable = stuff->drawable; - ev.sequenceNumber = client->sequence; - ev.minorEvent = X_ShmPutImage; - ev.majorEvent = ShmReqCode; - ev.shmseg = stuff->shmseg; - ev.offset = stuff->offset; - WriteEventsToClient(client, 1, (xEvent *) &ev); - } - - return (client->noClientException); -} - - - -static int -ProcShmGetImage(ClientPtr client) -{ - DrawablePtr pDraw; - long lenPer = 0, length; - Mask plane = 0; - xShmGetImageReply xgi; - ShmDescPtr shmdesc; - int n, rc; - - REQUEST(xShmGetImageReq); - - REQUEST_SIZE_MATCH(xShmGetImageReq); - if ((stuff->format != XYPixmap) && (stuff->format != ZPixmap)) - { - client->errorValue = stuff->format; - return(BadValue); - } - rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0, - DixReadAccess); - if (rc != Success) - return rc; - VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); - if (pDraw->type == DRAWABLE_WINDOW) - { - if( /* check for being viewable */ - !((WindowPtr) pDraw)->realized || - /* check for being on screen */ - pDraw->x + stuff->x < 0 || - pDraw->x + stuff->x + (int)stuff->width > pDraw->pScreen->width || - pDraw->y + stuff->y < 0 || - pDraw->y + stuff->y + (int)stuff->height > pDraw->pScreen->height || - /* check for being inside of border */ - stuff->x < - wBorderWidth((WindowPtr)pDraw) || - stuff->x + (int)stuff->width > - wBorderWidth((WindowPtr)pDraw) + (int)pDraw->width || - stuff->y < -wBorderWidth((WindowPtr)pDraw) || - stuff->y + (int)stuff->height > - wBorderWidth((WindowPtr)pDraw) + (int)pDraw->height - ) - return(BadMatch); - xgi.visual = wVisual(((WindowPtr)pDraw)); - } - else - { - if (stuff->x < 0 || - stuff->x+(int)stuff->width > pDraw->width || - stuff->y < 0 || - stuff->y+(int)stuff->height > pDraw->height - ) - return(BadMatch); - xgi.visual = None; - } - xgi.type = X_Reply; - xgi.length = 0; - xgi.sequenceNumber = client->sequence; - xgi.depth = pDraw->depth; - if(stuff->format == ZPixmap) - { - length = PixmapBytePad(stuff->width, pDraw->depth) * stuff->height; - } - else - { - lenPer = PixmapBytePad(stuff->width, 1) * stuff->height; - plane = ((Mask)1) << (pDraw->depth - 1); - /* only planes asked for */ - length = lenPer * Ones(stuff->planeMask & (plane | (plane - 1))); - } - - VERIFY_SHMSIZE(shmdesc, stuff->offset, length, client); - xgi.size = length; - - if (length == 0) - { - /* nothing to do */ - } - else if (stuff->format == ZPixmap) - { - (*pDraw->pScreen->GetImage)(pDraw, stuff->x, stuff->y, - stuff->width, stuff->height, - stuff->format, stuff->planeMask, - shmdesc->addr + stuff->offset); - } - else - { - - length = stuff->offset; - for (; plane; plane >>= 1) - { - if (stuff->planeMask & plane) - { - (*pDraw->pScreen->GetImage)(pDraw, - stuff->x, stuff->y, - stuff->width, stuff->height, - stuff->format, plane, - shmdesc->addr + length); - length += lenPer; - } - } - } - - if (client->swapped) { - swaps(&xgi.sequenceNumber, n); - swapl(&xgi.length, n); - swapl(&xgi.visual, n); - swapl(&xgi.size, n); - } - WriteToClient(client, sizeof(xShmGetImageReply), (char *)&xgi); - - return(client->noClientException); -} - -static PixmapPtr -fbShmCreatePixmap (ScreenPtr pScreen, - int width, int height, int depth, char *addr) -{ - PixmapPtr pPixmap; - - pPixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, pScreen->rootDepth, 0); - if (!pPixmap) - return NullPixmap; - - if (!(*pScreen->ModifyPixmapHeader)(pPixmap, width, height, depth, - BitsPerPixel(depth), PixmapBytePad(width, depth), (pointer)addr)) { - (*pScreen->DestroyPixmap)(pPixmap); - return NullPixmap; - } - return pPixmap; -} - -static int -ProcShmCreatePixmap(ClientPtr client) -{ - PixmapPtr pMap; - DrawablePtr pDraw; - DepthPtr pDepth; - int i, rc; - ShmDescPtr shmdesc; - ShmScrPrivateRec *screen_priv; - REQUEST(xShmCreatePixmapReq); - unsigned int width, height, depth; - unsigned long size; - - REQUEST_SIZE_MATCH(xShmCreatePixmapReq); - client->errorValue = stuff->pid; - if (!sharedPixmaps) - return BadImplementation; - LEGAL_NEW_RESOURCE(stuff->pid, client); - rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY, - DixGetAttrAccess); - if (rc != Success) - return rc; - - VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); - - width = stuff->width; - height = stuff->height; - depth = stuff->depth; - if (!width || !height || !depth) - { - client->errorValue = 0; - return BadValue; - } - if (width > 32767 || height > 32767) - return BadAlloc; - - if (stuff->depth != 1) - { - pDepth = pDraw->pScreen->allowedDepths; - for (i=0; ipScreen->numDepths; i++, pDepth++) - if (pDepth->depth == stuff->depth) - goto CreatePmap; - client->errorValue = stuff->depth; - return BadValue; - } - -CreatePmap: - size = PixmapBytePad(width, depth) * height; - if (sizeof(size) == 4 && BitsPerPixel(depth) > 8) { - if (size < width * height) - return BadAlloc; - } - /* thankfully, offset is unsigned */ - if (stuff->offset + size < size) - return BadAlloc; - - VERIFY_SHMSIZE(shmdesc, stuff->offset, size, client); - screen_priv = ShmGetScreenPriv(pDraw->pScreen); - pMap = (*screen_priv->shmFuncs->CreatePixmap)( - pDraw->pScreen, stuff->width, - stuff->height, stuff->depth, - shmdesc->addr + stuff->offset); - if (pMap) - { - rc = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pid, RT_PIXMAP, - pMap, RT_NONE, NULL, DixCreateAccess); - if (rc != Success) { - pDraw->pScreen->DestroyPixmap(pMap); - return rc; - } - dixSetPrivate(&pMap->devPrivates, shmPixmapPrivate, shmdesc); - shmdesc->refcnt++; - pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER; - pMap->drawable.id = stuff->pid; - if (AddResource(stuff->pid, RT_PIXMAP, (pointer)pMap)) - { - return(client->noClientException); - } - pDraw->pScreen->DestroyPixmap(pMap); - } - return (BadAlloc); -} - -static int -ProcShmDispatch (ClientPtr client) -{ - REQUEST(xReq); - switch (stuff->data) - { - case X_ShmQueryVersion: - return ProcShmQueryVersion(client); - case X_ShmAttach: - return ProcShmAttach(client); - case X_ShmDetach: - return ProcShmDetach(client); - case X_ShmPutImage: -#ifdef PANORAMIX - if ( !noPanoramiXExtension ) - return ProcPanoramiXShmPutImage(client); -#endif - return ProcShmPutImage(client); - case X_ShmGetImage: -#ifdef PANORAMIX - if ( !noPanoramiXExtension ) - return ProcPanoramiXShmGetImage(client); -#endif - return ProcShmGetImage(client); - case X_ShmCreatePixmap: -#ifdef PANORAMIX - if ( !noPanoramiXExtension ) - return ProcPanoramiXShmCreatePixmap(client); -#endif - return ProcShmCreatePixmap(client); - default: - return BadRequest; - } -} - -static void -SShmCompletionEvent(xShmCompletionEvent *from, xShmCompletionEvent *to) -{ - to->type = from->type; - cpswaps(from->sequenceNumber, to->sequenceNumber); - cpswapl(from->drawable, to->drawable); - cpswaps(from->minorEvent, to->minorEvent); - to->majorEvent = from->majorEvent; - cpswapl(from->shmseg, to->shmseg); - cpswapl(from->offset, to->offset); -} - -static int -SProcShmQueryVersion(ClientPtr client) -{ - int n; - REQUEST(xShmQueryVersionReq); - - swaps(&stuff->length, n); - return ProcShmQueryVersion(client); -} - -static int -SProcShmAttach(ClientPtr client) -{ - int n; - REQUEST(xShmAttachReq); - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH(xShmAttachReq); - swapl(&stuff->shmseg, n); - swapl(&stuff->shmid, n); - return ProcShmAttach(client); -} - -static int -SProcShmDetach(ClientPtr client) -{ - int n; - REQUEST(xShmDetachReq); - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH(xShmDetachReq); - swapl(&stuff->shmseg, n); - return ProcShmDetach(client); -} - -static int -SProcShmPutImage(ClientPtr client) -{ - int n; - REQUEST(xShmPutImageReq); - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH(xShmPutImageReq); - swapl(&stuff->drawable, n); - swapl(&stuff->gc, n); - swaps(&stuff->totalWidth, n); - swaps(&stuff->totalHeight, n); - swaps(&stuff->srcX, n); - swaps(&stuff->srcY, n); - swaps(&stuff->srcWidth, n); - swaps(&stuff->srcHeight, n); - swaps(&stuff->dstX, n); - swaps(&stuff->dstY, n); - swapl(&stuff->shmseg, n); - swapl(&stuff->offset, n); - return ProcShmPutImage(client); -} - -static int -SProcShmGetImage(ClientPtr client) -{ - int n; - REQUEST(xShmGetImageReq); - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH(xShmGetImageReq); - swapl(&stuff->drawable, n); - swaps(&stuff->x, n); - swaps(&stuff->y, n); - swaps(&stuff->width, n); - swaps(&stuff->height, n); - swapl(&stuff->planeMask, n); - swapl(&stuff->shmseg, n); - swapl(&stuff->offset, n); - return ProcShmGetImage(client); -} - -static int -SProcShmCreatePixmap(ClientPtr client) -{ - int n; - REQUEST(xShmCreatePixmapReq); - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH(xShmCreatePixmapReq); - swapl(&stuff->pid, n); - swapl(&stuff->drawable, n); - swaps(&stuff->width, n); - swaps(&stuff->height, n); - swapl(&stuff->shmseg, n); - swapl(&stuff->offset, n); - return ProcShmCreatePixmap(client); -} - -static int -SProcShmDispatch (ClientPtr client) -{ - REQUEST(xReq); - switch (stuff->data) - { - case X_ShmQueryVersion: - return SProcShmQueryVersion(client); - case X_ShmAttach: - return SProcShmAttach(client); - case X_ShmDetach: - return SProcShmDetach(client); - case X_ShmPutImage: - return SProcShmPutImage(client); - case X_ShmGetImage: - return SProcShmGetImage(client); - case X_ShmCreatePixmap: - return SProcShmCreatePixmap(client); - default: - return BadRequest; - } -} +/************************************************************ + +Copyright 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. + +********************************************************/ + +/* THIS IS NOT AN X CONSORTIUM STANDARD OR AN X PROJECT TEAM SPECIFICATION */ + + +#define SHM + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include +#include +#include +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "resource.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "gcstruct.h" +#include "extnsionst.h" +#include "servermd.h" +#include "shmint.h" +#include "xace.h" +#include +#include +#include "protocol-versions.h" + +/* Needed for Solaris cross-zone shared memory extension */ +#ifdef HAVE_SHMCTL64 +#include +#define SHMSTAT(id, buf) shmctl64(id, IPC_STAT64, buf) +#define SHMSTAT_TYPE struct shmid_ds64 +#define SHMPERM_TYPE struct ipc_perm64 +#define SHM_PERM(buf) buf.shmx_perm +#define SHM_SEGSZ(buf) buf.shmx_segsz +#define SHMPERM_UID(p) p->ipcx_uid +#define SHMPERM_CUID(p) p->ipcx_cuid +#define SHMPERM_GID(p) p->ipcx_gid +#define SHMPERM_CGID(p) p->ipcx_cgid +#define SHMPERM_MODE(p) p->ipcx_mode +#define SHMPERM_ZONEID(p) p->ipcx_zoneid +#else +#define SHMSTAT(id, buf) shmctl(id, IPC_STAT, buf) +#define SHMSTAT_TYPE struct shmid_ds +#define SHMPERM_TYPE struct ipc_perm +#define SHM_PERM(buf) buf.shm_perm +#define SHM_SEGSZ(buf) buf.shm_segsz +#define SHMPERM_UID(p) p->uid +#define SHMPERM_CUID(p) p->cuid +#define SHMPERM_GID(p) p->gid +#define SHMPERM_CGID(p) p->cgid +#define SHMPERM_MODE(p) p->mode +#endif + +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" +#endif + +#include "modinit.h" + +typedef struct _ShmDesc { + struct _ShmDesc *next; + int shmid; + int refcnt; + char *addr; + Bool writable; + unsigned long size; +} ShmDescRec, *ShmDescPtr; + +typedef struct _ShmScrPrivateRec { + CloseScreenProcPtr CloseScreen; + ShmFuncsPtr shmFuncs; + DestroyPixmapProcPtr destroyPixmap; +} ShmScrPrivateRec; + +static PixmapPtr fbShmCreatePixmap(XSHM_CREATE_PIXMAP_ARGS); +static int ShmDetachSegment( + pointer /* value */, + XID /* shmseg */ + ); +static void ShmResetProc( + ExtensionEntry * /* extEntry */ + ); +static void SShmCompletionEvent( + xShmCompletionEvent * /* from */, + xShmCompletionEvent * /* to */ + ); + +static Bool ShmDestroyPixmap (PixmapPtr pPixmap); + +static DISPATCH_PROC(ProcShmAttach); +static DISPATCH_PROC(ProcShmCreatePixmap); +static DISPATCH_PROC(ProcShmDetach); +static DISPATCH_PROC(ProcShmDispatch); +static DISPATCH_PROC(ProcShmGetImage); +static DISPATCH_PROC(ProcShmPutImage); +static DISPATCH_PROC(ProcShmQueryVersion); +static DISPATCH_PROC(SProcShmAttach); +static DISPATCH_PROC(SProcShmCreatePixmap); +static DISPATCH_PROC(SProcShmDetach); +static DISPATCH_PROC(SProcShmDispatch); +static DISPATCH_PROC(SProcShmGetImage); +static DISPATCH_PROC(SProcShmPutImage); +static DISPATCH_PROC(SProcShmQueryVersion); + +static unsigned char ShmReqCode; +int ShmCompletionCode; +int BadShmSegCode; +RESTYPE ShmSegType; +static ShmDescPtr Shmsegs; +static Bool sharedPixmaps; +static int shmScrPrivateKeyIndex; +static DevPrivateKey shmScrPrivateKey = &shmScrPrivateKeyIndex; +static int shmPixmapPrivateIndex; +static DevPrivateKey shmPixmapPrivate = &shmPixmapPrivateIndex; +static ShmFuncs miFuncs = {NULL, NULL}; +static ShmFuncs fbFuncs = {fbShmCreatePixmap, NULL}; + +#define ShmGetScreenPriv(s) ((ShmScrPrivateRec *)dixLookupPrivate(&(s)->devPrivates, shmScrPrivateKey)) + +#define VERIFY_SHMSEG(shmseg,shmdesc,client) \ +{ \ + int rc; \ + rc = dixLookupResourceByType((pointer *)&(shmdesc), shmseg, ShmSegType, \ + client, DixReadAccess); \ + if (rc != Success) \ + return (rc == BadValue) ? BadShmSegCode : rc; \ +} + +#define VERIFY_SHMPTR(shmseg,offset,needwrite,shmdesc,client) \ +{ \ + VERIFY_SHMSEG(shmseg, shmdesc, client); \ + if ((offset & 3) || (offset > shmdesc->size)) \ + { \ + client->errorValue = offset; \ + return BadValue; \ + } \ + if (needwrite && !shmdesc->writable) \ + return BadAccess; \ +} + +#define VERIFY_SHMSIZE(shmdesc,offset,len,client) \ +{ \ + if ((offset + len) > shmdesc->size) \ + { \ + return BadAccess; \ + } \ +} + + +#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__CYGWIN__) || defined(__DragonFly__) +#include + +static Bool badSysCall = FALSE; + +static void +SigSysHandler(int signo) +{ + badSysCall = TRUE; +} + +static Bool CheckForShmSyscall(void) +{ + void (*oldHandler)(); + int shmid = -1; + + /* If no SHM support in the kernel, the bad syscall will generate SIGSYS */ + oldHandler = signal(SIGSYS, SigSysHandler); + + badSysCall = FALSE; + shmid = shmget(IPC_PRIVATE, 4096, IPC_CREAT); + + if (shmid != -1) + { + /* Successful allocation - clean up */ + shmctl(shmid, IPC_RMID, NULL); + } + else + { + /* Allocation failed */ + badSysCall = TRUE; + } + signal(SIGSYS, oldHandler); + return(!badSysCall); +} + +#define MUST_CHECK_FOR_SHM_SYSCALL + +#endif + +static Bool +ShmCloseScreen(int i, ScreenPtr pScreen) +{ + ShmScrPrivateRec *screen_priv = ShmGetScreenPriv(pScreen); + pScreen->CloseScreen = screen_priv->CloseScreen; + dixSetPrivate(&pScreen->devPrivates, shmScrPrivateKey, NULL); + free(screen_priv); + return (*pScreen->CloseScreen) (i, pScreen); +} + +static ShmScrPrivateRec * +ShmInitScreenPriv(ScreenPtr pScreen) +{ + ShmScrPrivateRec *screen_priv = ShmGetScreenPriv(pScreen); + if (!screen_priv) + { + screen_priv = calloc(1, sizeof (ShmScrPrivateRec)); + screen_priv->CloseScreen = pScreen->CloseScreen; + dixSetPrivate(&pScreen->devPrivates, shmScrPrivateKey, screen_priv); + pScreen->CloseScreen = ShmCloseScreen; + } + return screen_priv; +} + +void +ShmExtensionInit(INITARGS) +{ + ExtensionEntry *extEntry; + int i; + +#ifdef MUST_CHECK_FOR_SHM_SYSCALL + if (!CheckForShmSyscall()) + { + ErrorF("MIT-SHM extension disabled due to lack of kernel support\n"); + return; + } +#endif + + sharedPixmaps = xFalse; + { + sharedPixmaps = xTrue; + for (i = 0; i < screenInfo.numScreens; i++) + { + ShmScrPrivateRec *screen_priv = ShmInitScreenPriv(screenInfo.screens[i]); + if (!screen_priv->shmFuncs) + screen_priv->shmFuncs = &miFuncs; + if (!screen_priv->shmFuncs->CreatePixmap) + sharedPixmaps = xFalse; + } + if (sharedPixmaps) + for (i = 0; i < screenInfo.numScreens; i++) + { + ShmScrPrivateRec *screen_priv = ShmGetScreenPriv(screenInfo.screens[i]); + screen_priv->destroyPixmap = screenInfo.screens[i]->DestroyPixmap; + screenInfo.screens[i]->DestroyPixmap = ShmDestroyPixmap; + } + } + ShmSegType = CreateNewResourceType(ShmDetachSegment, "ShmSeg"); + if (ShmSegType && + (extEntry = AddExtension(SHMNAME, ShmNumberEvents, ShmNumberErrors, + ProcShmDispatch, SProcShmDispatch, + ShmResetProc, StandardMinorOpcode))) + { + ShmReqCode = (unsigned char)extEntry->base; + ShmCompletionCode = extEntry->eventBase; + BadShmSegCode = extEntry->errorBase; + EventSwapVector[ShmCompletionCode] = (EventSwapPtr) SShmCompletionEvent; + } +} + +/*ARGSUSED*/ +static void +ShmResetProc(ExtensionEntry *extEntry) +{ + int i; + for (i = 0; i < screenInfo.numScreens; i++) + ShmRegisterFuncs(screenInfo.screens[i], NULL); +} + +void +ShmRegisterFuncs(ScreenPtr pScreen, ShmFuncsPtr funcs) +{ + ShmInitScreenPriv(pScreen)->shmFuncs = funcs; +} + +static Bool +ShmDestroyPixmap (PixmapPtr pPixmap) +{ + ScreenPtr pScreen = pPixmap->drawable.pScreen; + ShmScrPrivateRec *screen_priv = ShmGetScreenPriv(pScreen); + Bool ret; + if (pPixmap->refcnt == 1) + { + ShmDescPtr shmdesc; + shmdesc = (ShmDescPtr)dixLookupPrivate(&pPixmap->devPrivates, + shmPixmapPrivate); + if (shmdesc) + ShmDetachSegment ((pointer) shmdesc, pPixmap->drawable.id); + } + + pScreen->DestroyPixmap = screen_priv->destroyPixmap; + ret = (*pScreen->DestroyPixmap) (pPixmap); + screen_priv->destroyPixmap = pScreen->DestroyPixmap; + pScreen->DestroyPixmap = ShmDestroyPixmap; + return ret; +} + +void +ShmRegisterFbFuncs(ScreenPtr pScreen) +{ + ShmRegisterFuncs(pScreen, &fbFuncs); +} + +static int +ProcShmQueryVersion(ClientPtr client) +{ + xShmQueryVersionReply rep; + int n; + + REQUEST_SIZE_MATCH(xShmQueryVersionReq); + memset(&rep, 0, sizeof(xShmQueryVersionReply)); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.sharedPixmaps = sharedPixmaps; + rep.pixmapFormat = sharedPixmaps ? ZPixmap : 0; + rep.majorVersion = SERVER_SHM_MAJOR_VERSION; + rep.minorVersion = SERVER_SHM_MINOR_VERSION; + rep.uid = geteuid(); + rep.gid = getegid(); + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.majorVersion, n); + swaps(&rep.minorVersion, n); + swaps(&rep.uid, n); + swaps(&rep.gid, n); + } + WriteToClient(client, sizeof(xShmQueryVersionReply), (char *)&rep); + return Success; +} + +/* + * Simulate the access() system call for a shared memory segement, + * using the credentials from the client if available + */ +static int +shm_access(ClientPtr client, SHMPERM_TYPE *perm, int readonly) +{ + int uid, gid; + mode_t mask; + int uidset = 0, gidset = 0; + LocalClientCredRec *lcc; + + if (GetLocalClientCreds(client, &lcc) != -1) { + + if (lcc->fieldsSet & LCC_UID_SET) { + uid = lcc->euid; + uidset = 1; + } + if (lcc->fieldsSet & LCC_GID_SET) { + gid = lcc->egid; + gidset = 1; + } + +#if defined(HAVE_GETZONEID) && defined(SHMPERM_ZONEID) + if ( ((lcc->fieldsSet & LCC_ZID_SET) == 0) || (lcc->zoneid == -1) + || (lcc->zoneid != SHMPERM_ZONEID(perm))) { + uidset = 0; + gidset = 0; + } +#endif + FreeLocalClientCreds(lcc); + + if (uidset) { + /* User id 0 always gets access */ + if (uid == 0) { + return 0; + } + /* Check the owner */ + if (SHMPERM_UID(perm) == uid || SHMPERM_CUID(perm) == uid) { + mask = S_IRUSR; + if (!readonly) { + mask |= S_IWUSR; + } + return (SHMPERM_MODE(perm) & mask) == mask ? 0 : -1; + } + } + + if (gidset) { + /* Check the group */ + if (SHMPERM_GID(perm) == gid || SHMPERM_CGID(perm) == gid) { + mask = S_IRGRP; + if (!readonly) { + mask |= S_IWGRP; + } + return (SHMPERM_MODE(perm) & mask) == mask ? 0 : -1; + } + } + } + /* Otherwise, check everyone else */ + mask = S_IROTH; + if (!readonly) { + mask |= S_IWOTH; + } + return (SHMPERM_MODE(perm) & mask) == mask ? 0 : -1; +} + +static int +ProcShmAttach(ClientPtr client) +{ + SHMSTAT_TYPE buf; + ShmDescPtr shmdesc; + REQUEST(xShmAttachReq); + + REQUEST_SIZE_MATCH(xShmAttachReq); + LEGAL_NEW_RESOURCE(stuff->shmseg, client); + if ((stuff->readOnly != xTrue) && (stuff->readOnly != xFalse)) + { + client->errorValue = stuff->readOnly; + return(BadValue); + } + for (shmdesc = Shmsegs; + shmdesc && (shmdesc->shmid != stuff->shmid); + shmdesc = shmdesc->next) + ; + if (shmdesc) + { + if (!stuff->readOnly && !shmdesc->writable) + return BadAccess; + shmdesc->refcnt++; + } + else + { + shmdesc = malloc(sizeof(ShmDescRec)); + if (!shmdesc) + return BadAlloc; + shmdesc->addr = shmat(stuff->shmid, 0, + stuff->readOnly ? SHM_RDONLY : 0); + if ((shmdesc->addr == ((char *)-1)) || + SHMSTAT(stuff->shmid, &buf)) + { + free(shmdesc); + return BadAccess; + } + + /* The attach was performed with root privs. We must + * do manual checking of access rights for the credentials + * of the client */ + + if (shm_access(client, &(SHM_PERM(buf)), stuff->readOnly) == -1) { + shmdt(shmdesc->addr); + free(shmdesc); + return BadAccess; + } + + shmdesc->shmid = stuff->shmid; + shmdesc->refcnt = 1; + shmdesc->writable = !stuff->readOnly; + shmdesc->size = SHM_SEGSZ(buf); + shmdesc->next = Shmsegs; + Shmsegs = shmdesc; + } + if (!AddResource(stuff->shmseg, ShmSegType, (pointer)shmdesc)) + return BadAlloc; + return Success; +} + +/*ARGSUSED*/ +static int +ShmDetachSegment(pointer value, /* must conform to DeleteType */ + XID shmseg) +{ + ShmDescPtr shmdesc = (ShmDescPtr)value; + ShmDescPtr *prev; + + if (--shmdesc->refcnt) + return TRUE; + shmdt(shmdesc->addr); + for (prev = &Shmsegs; *prev != shmdesc; prev = &(*prev)->next) + ; + *prev = shmdesc->next; + free(shmdesc); + return Success; +} + +static int +ProcShmDetach(ClientPtr client) +{ + ShmDescPtr shmdesc; + REQUEST(xShmDetachReq); + + REQUEST_SIZE_MATCH(xShmDetachReq); + VERIFY_SHMSEG(stuff->shmseg, shmdesc, client); + FreeResource(stuff->shmseg, RT_NONE); + return Success; +} + +/* + * If the given request doesn't exactly match PutImage's constraints, + * wrap the image in a scratch pixmap header and let CopyArea sort it out. + */ +static void +doShmPutImage(DrawablePtr dst, GCPtr pGC, + int depth, unsigned int format, + int w, int h, int sx, int sy, int sw, int sh, int dx, int dy, + char *data) +{ + PixmapPtr pPixmap; + + if (format == ZPixmap || depth == 1) { + pPixmap = GetScratchPixmapHeader(dst->pScreen, w, h, depth, + BitsPerPixel(depth), + PixmapBytePad(w, depth), + data); + if (!pPixmap) + return; + pGC->ops->CopyArea((DrawablePtr)pPixmap, dst, pGC, sx, sy, sw, sh, dx, dy); + FreeScratchPixmapHeader(pPixmap); + } else { + GCPtr putGC = GetScratchGC(depth, dst->pScreen); + + if (!putGC) + return; + + pPixmap = (*dst->pScreen->CreatePixmap)(dst->pScreen, sw, sh, depth, + CREATE_PIXMAP_USAGE_SCRATCH); + if (!pPixmap) { + FreeScratchGC(putGC); + return; + } + ValidateGC(&pPixmap->drawable, putGC); + (*putGC->ops->PutImage)(&pPixmap->drawable, putGC, depth, -sx, -sy, w, h, 0, + (format == XYPixmap) ? XYPixmap : ZPixmap, data); + FreeScratchGC(putGC); + if (format == XYBitmap) + (void)(*pGC->ops->CopyPlane)(&pPixmap->drawable, dst, pGC, 0, 0, sw, sh, + dx, dy, 1L); + else + (void)(*pGC->ops->CopyArea)(&pPixmap->drawable, dst, pGC, 0, 0, sw, sh, + dx, dy); + (*pPixmap->drawable.pScreen->DestroyPixmap)(pPixmap); + } +} + +#ifdef PANORAMIX +static int +ProcPanoramiXShmPutImage(ClientPtr client) +{ + int j, result, orig_x, orig_y; + PanoramiXRes *draw, *gc; + Bool sendEvent, isRoot; + + REQUEST(xShmPutImageReq); + REQUEST_SIZE_MATCH(xShmPutImageReq); + + result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable, + XRC_DRAWABLE, client, DixWriteAccess); + if (result != Success) + return (result == BadValue) ? BadDrawable : result; + + result = dixLookupResourceByType((pointer *)&gc, stuff->gc, + XRT_GC, client, DixReadAccess); + if (result != Success) + return (result == BadValue) ? BadGC : result; + + isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; + + orig_x = stuff->dstX; + orig_y = stuff->dstY; + sendEvent = stuff->sendEvent; + stuff->sendEvent = 0; + FOR_NSCREENS(j) { + if(!j) stuff->sendEvent = sendEvent; + stuff->drawable = draw->info[j].id; + stuff->gc = gc->info[j].id; + if (isRoot) { + stuff->dstX = orig_x - panoramiXdataPtr[j].x; + stuff->dstY = orig_y - panoramiXdataPtr[j].y; + } + result = ProcShmPutImage(client); + if(result != Success) break; + } + return(result); +} + +static int +ProcPanoramiXShmGetImage(ClientPtr client) +{ + PanoramiXRes *draw; + DrawablePtr *drawables; + DrawablePtr pDraw; + xShmGetImageReply xgi; + ShmDescPtr shmdesc; + int i, x, y, w, h, format, rc; + Mask plane = 0, planemask; + long lenPer = 0, length, widthBytesLine; + Bool isRoot; + + REQUEST(xShmGetImageReq); + + REQUEST_SIZE_MATCH(xShmGetImageReq); + + if ((stuff->format != XYPixmap) && (stuff->format != ZPixmap)) { + client->errorValue = stuff->format; + return(BadValue); + } + + rc = dixLookupResourceByClass((pointer *)&draw, stuff->drawable, + XRC_DRAWABLE, client, DixWriteAccess); + if (rc != Success) + return (rc == BadValue) ? BadDrawable : rc; + + if (draw->type == XRT_PIXMAP) + return ProcShmGetImage(client); + + rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0, + DixReadAccess); + if (rc != Success) + return rc; + + VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); + + x = stuff->x; + y = stuff->y; + w = stuff->width; + h = stuff->height; + format = stuff->format; + planemask = stuff->planeMask; + + isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; + + if(isRoot) { + if( /* check for being onscreen */ + x < 0 || x + w > PanoramiXPixWidth || + y < 0 || y + h > PanoramiXPixHeight ) + return(BadMatch); + } else { + if( /* check for being onscreen */ + panoramiXdataPtr[0].x + pDraw->x + x < 0 || + panoramiXdataPtr[0].x + pDraw->x + x + w > PanoramiXPixWidth || + panoramiXdataPtr[0].y + pDraw->y + y < 0 || + panoramiXdataPtr[0].y + pDraw->y + y + h > PanoramiXPixHeight || + /* check for being inside of border */ + x < - wBorderWidth((WindowPtr)pDraw) || + x + w > wBorderWidth((WindowPtr)pDraw) + (int)pDraw->width || + y < -wBorderWidth((WindowPtr)pDraw) || + y + h > wBorderWidth ((WindowPtr)pDraw) + (int)pDraw->height) + return(BadMatch); + } + + drawables = calloc(PanoramiXNumScreens, sizeof(DrawablePtr)); + if(!drawables) + return(BadAlloc); + + drawables[0] = pDraw; + for(i = 1; i < PanoramiXNumScreens; i++) { + rc = dixLookupDrawable(drawables+i, draw->info[i].id, client, 0, + DixReadAccess); + if (rc != Success) + { + free(drawables); + return rc; + } + } + + xgi.visual = wVisual(((WindowPtr)pDraw)); + xgi.type = X_Reply; + xgi.length = 0; + xgi.sequenceNumber = client->sequence; + xgi.depth = pDraw->depth; + + if(format == ZPixmap) { + widthBytesLine = PixmapBytePad(w, pDraw->depth); + length = widthBytesLine * h; + } else { + widthBytesLine = PixmapBytePad(w, 1); + lenPer = widthBytesLine * h; + plane = ((Mask)1) << (pDraw->depth - 1); + length = lenPer * Ones(planemask & (plane | (plane - 1))); + } + + VERIFY_SHMSIZE(shmdesc, stuff->offset, length, client); + xgi.size = length; + + if (length == 0) {/* nothing to do */ } + else if (format == ZPixmap) { + XineramaGetImageData(drawables, x, y, w, h, format, planemask, + shmdesc->addr + stuff->offset, + widthBytesLine, isRoot); + } else { + + length = stuff->offset; + for (; plane; plane >>= 1) { + if (planemask & plane) { + XineramaGetImageData(drawables, x, y, w, h, + format, plane, shmdesc->addr + length, + widthBytesLine, isRoot); + length += lenPer; + } + } + } + free(drawables); + + if (client->swapped) { + int n; + swaps(&xgi.sequenceNumber, n); + swapl(&xgi.length, n); + swapl(&xgi.visual, n); + swapl(&xgi.size, n); + } + WriteToClient(client, sizeof(xShmGetImageReply), (char *)&xgi); + + return Success; +} + +static int +ProcPanoramiXShmCreatePixmap(ClientPtr client) +{ + ScreenPtr pScreen = NULL; + PixmapPtr pMap = NULL; + DrawablePtr pDraw; + DepthPtr pDepth; + int i, j, result, rc; + ShmDescPtr shmdesc; + REQUEST(xShmCreatePixmapReq); + unsigned int width, height, depth; + unsigned long size; + PanoramiXRes *newPix; + + REQUEST_SIZE_MATCH(xShmCreatePixmapReq); + client->errorValue = stuff->pid; + if (!sharedPixmaps) + return BadImplementation; + LEGAL_NEW_RESOURCE(stuff->pid, client); + rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY, + DixGetAttrAccess); + if (rc != Success) + return rc; + + VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); + + width = stuff->width; + height = stuff->height; + depth = stuff->depth; + if (!width || !height || !depth) + { + client->errorValue = 0; + return BadValue; + } + if (width > 32767 || height > 32767) + return BadAlloc; + + if (stuff->depth != 1) + { + pDepth = pDraw->pScreen->allowedDepths; + for (i=0; ipScreen->numDepths; i++, pDepth++) + if (pDepth->depth == stuff->depth) + goto CreatePmap; + client->errorValue = stuff->depth; + return BadValue; + } + +CreatePmap: + size = PixmapBytePad(width, depth) * height; + if (sizeof(size) == 4 && BitsPerPixel(depth) > 8) { + if (size < width * height) + return BadAlloc; + } + /* thankfully, offset is unsigned */ + if (stuff->offset + size < size) + return BadAlloc; + + VERIFY_SHMSIZE(shmdesc, stuff->offset, size, client); + + if(!(newPix = malloc(sizeof(PanoramiXRes)))) + return BadAlloc; + + newPix->type = XRT_PIXMAP; + newPix->u.pix.shared = TRUE; + newPix->info[0].id = stuff->pid; + for(j = 1; j < PanoramiXNumScreens; j++) + newPix->info[j].id = FakeClientID(client->index); + + result = Success; + + FOR_NSCREENS(j) { + ShmScrPrivateRec *screen_priv; + pScreen = screenInfo.screens[j]; + + screen_priv = ShmGetScreenPriv(pScreen); + pMap = (*screen_priv->shmFuncs->CreatePixmap)(pScreen, + stuff->width, stuff->height, stuff->depth, + shmdesc->addr + stuff->offset); + + if (pMap) { + dixSetPrivate(&pMap->devPrivates, shmPixmapPrivate, shmdesc); + shmdesc->refcnt++; + pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER; + pMap->drawable.id = newPix->info[j].id; + if (!AddResource(newPix->info[j].id, RT_PIXMAP, (pointer)pMap)) { + (*pScreen->DestroyPixmap)(pMap); + result = BadAlloc; + break; + } + } else { + result = BadAlloc; + break; + } + } + + if(result == BadAlloc) { + while(j--) { + (*pScreen->DestroyPixmap)(pMap); + FreeResource(newPix->info[j].id, RT_NONE); + } + free(newPix); + } else + AddResource(stuff->pid, XRT_PIXMAP, newPix); + + return result; +} + +#endif + +static int +ProcShmPutImage(ClientPtr client) +{ + GCPtr pGC; + DrawablePtr pDraw; + long length; + ShmDescPtr shmdesc; + REQUEST(xShmPutImageReq); + + REQUEST_SIZE_MATCH(xShmPutImageReq); + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); + VERIFY_SHMPTR(stuff->shmseg, stuff->offset, FALSE, shmdesc, client); + if ((stuff->sendEvent != xTrue) && (stuff->sendEvent != xFalse)) + return BadValue; + if (stuff->format == XYBitmap) + { + if (stuff->depth != 1) + return BadMatch; + length = PixmapBytePad(stuff->totalWidth, 1); + } + else if (stuff->format == XYPixmap) + { + if (pDraw->depth != stuff->depth) + return BadMatch; + length = PixmapBytePad(stuff->totalWidth, 1); + length *= stuff->depth; + } + else if (stuff->format == ZPixmap) + { + if (pDraw->depth != stuff->depth) + return BadMatch; + length = PixmapBytePad(stuff->totalWidth, stuff->depth); + } + else + { + client->errorValue = stuff->format; + return BadValue; + } + + /* + * There's a potential integer overflow in this check: + * VERIFY_SHMSIZE(shmdesc, stuff->offset, length * stuff->totalHeight, + * client); + * the version below ought to avoid it + */ + if (stuff->totalHeight != 0 && + length > (shmdesc->size - stuff->offset)/stuff->totalHeight) { + client->errorValue = stuff->totalWidth; + return BadValue; + } + if (stuff->srcX > stuff->totalWidth) + { + client->errorValue = stuff->srcX; + return BadValue; + } + if (stuff->srcY > stuff->totalHeight) + { + client->errorValue = stuff->srcY; + return BadValue; + } + if ((stuff->srcX + stuff->srcWidth) > stuff->totalWidth) + { + client->errorValue = stuff->srcWidth; + return BadValue; + } + if ((stuff->srcY + stuff->srcHeight) > stuff->totalHeight) + { + client->errorValue = stuff->srcHeight; + return BadValue; + } + + if ((((stuff->format == ZPixmap) && (stuff->srcX == 0)) || + ((stuff->format != ZPixmap) && + (stuff->srcX < screenInfo.bitmapScanlinePad) && + ((stuff->format == XYBitmap) || + ((stuff->srcY == 0) && + (stuff->srcHeight == stuff->totalHeight))))) && + ((stuff->srcX + stuff->srcWidth) == stuff->totalWidth)) + (*pGC->ops->PutImage) (pDraw, pGC, stuff->depth, + stuff->dstX, stuff->dstY, + stuff->totalWidth, stuff->srcHeight, + stuff->srcX, stuff->format, + shmdesc->addr + stuff->offset + + (stuff->srcY * length)); + else + doShmPutImage(pDraw, pGC, stuff->depth, stuff->format, + stuff->totalWidth, stuff->totalHeight, + stuff->srcX, stuff->srcY, + stuff->srcWidth, stuff->srcHeight, + stuff->dstX, stuff->dstY, + shmdesc->addr + stuff->offset); + + if (stuff->sendEvent) + { + xShmCompletionEvent ev; + + ev.type = ShmCompletionCode; + ev.drawable = stuff->drawable; + ev.sequenceNumber = client->sequence; + ev.minorEvent = X_ShmPutImage; + ev.majorEvent = ShmReqCode; + ev.shmseg = stuff->shmseg; + ev.offset = stuff->offset; + WriteEventsToClient(client, 1, (xEvent *) &ev); + } + + return Success; +} + + + +static int +ProcShmGetImage(ClientPtr client) +{ + DrawablePtr pDraw; + long lenPer = 0, length; + Mask plane = 0; + xShmGetImageReply xgi; + ShmDescPtr shmdesc; + int n, rc; + + REQUEST(xShmGetImageReq); + + REQUEST_SIZE_MATCH(xShmGetImageReq); + if ((stuff->format != XYPixmap) && (stuff->format != ZPixmap)) + { + client->errorValue = stuff->format; + return(BadValue); + } + rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0, + DixReadAccess); + if (rc != Success) + return rc; + VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); + if (pDraw->type == DRAWABLE_WINDOW) + { + if( /* check for being viewable */ + !((WindowPtr) pDraw)->realized || + /* check for being on screen */ + pDraw->x + stuff->x < 0 || + pDraw->x + stuff->x + (int)stuff->width > pDraw->pScreen->width || + pDraw->y + stuff->y < 0 || + pDraw->y + stuff->y + (int)stuff->height > pDraw->pScreen->height || + /* check for being inside of border */ + stuff->x < - wBorderWidth((WindowPtr)pDraw) || + stuff->x + (int)stuff->width > + wBorderWidth((WindowPtr)pDraw) + (int)pDraw->width || + stuff->y < -wBorderWidth((WindowPtr)pDraw) || + stuff->y + (int)stuff->height > + wBorderWidth((WindowPtr)pDraw) + (int)pDraw->height + ) + return(BadMatch); + xgi.visual = wVisual(((WindowPtr)pDraw)); + } + else + { + if (stuff->x < 0 || + stuff->x+(int)stuff->width > pDraw->width || + stuff->y < 0 || + stuff->y+(int)stuff->height > pDraw->height + ) + return(BadMatch); + xgi.visual = None; + } + xgi.type = X_Reply; + xgi.length = 0; + xgi.sequenceNumber = client->sequence; + xgi.depth = pDraw->depth; + if(stuff->format == ZPixmap) + { + length = PixmapBytePad(stuff->width, pDraw->depth) * stuff->height; + } + else + { + lenPer = PixmapBytePad(stuff->width, 1) * stuff->height; + plane = ((Mask)1) << (pDraw->depth - 1); + /* only planes asked for */ + length = lenPer * Ones(stuff->planeMask & (plane | (plane - 1))); + } + + VERIFY_SHMSIZE(shmdesc, stuff->offset, length, client); + xgi.size = length; + + if (length == 0) + { + /* nothing to do */ + } + else if (stuff->format == ZPixmap) + { + (*pDraw->pScreen->GetImage)(pDraw, stuff->x, stuff->y, + stuff->width, stuff->height, + stuff->format, stuff->planeMask, + shmdesc->addr + stuff->offset); + } + else + { + + length = stuff->offset; + for (; plane; plane >>= 1) + { + if (stuff->planeMask & plane) + { + (*pDraw->pScreen->GetImage)(pDraw, + stuff->x, stuff->y, + stuff->width, stuff->height, + stuff->format, plane, + shmdesc->addr + length); + length += lenPer; + } + } + } + + if (client->swapped) { + swaps(&xgi.sequenceNumber, n); + swapl(&xgi.length, n); + swapl(&xgi.visual, n); + swapl(&xgi.size, n); + } + WriteToClient(client, sizeof(xShmGetImageReply), (char *)&xgi); + + return Success; +} + +static PixmapPtr +fbShmCreatePixmap (ScreenPtr pScreen, + int width, int height, int depth, char *addr) +{ + PixmapPtr pPixmap; + + pPixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, pScreen->rootDepth, 0); + if (!pPixmap) + return NullPixmap; + + if (!(*pScreen->ModifyPixmapHeader)(pPixmap, width, height, depth, + BitsPerPixel(depth), PixmapBytePad(width, depth), (pointer)addr)) { + (*pScreen->DestroyPixmap)(pPixmap); + return NullPixmap; + } + return pPixmap; +} + +static int +ProcShmCreatePixmap(ClientPtr client) +{ + PixmapPtr pMap; + DrawablePtr pDraw; + DepthPtr pDepth; + int i, rc; + ShmDescPtr shmdesc; + ShmScrPrivateRec *screen_priv; + REQUEST(xShmCreatePixmapReq); + unsigned int width, height, depth; + unsigned long size; + + REQUEST_SIZE_MATCH(xShmCreatePixmapReq); + client->errorValue = stuff->pid; + if (!sharedPixmaps) + return BadImplementation; + LEGAL_NEW_RESOURCE(stuff->pid, client); + rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY, + DixGetAttrAccess); + if (rc != Success) + return rc; + + VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); + + width = stuff->width; + height = stuff->height; + depth = stuff->depth; + if (!width || !height || !depth) + { + client->errorValue = 0; + return BadValue; + } + if (width > 32767 || height > 32767) + return BadAlloc; + + if (stuff->depth != 1) + { + pDepth = pDraw->pScreen->allowedDepths; + for (i=0; ipScreen->numDepths; i++, pDepth++) + if (pDepth->depth == stuff->depth) + goto CreatePmap; + client->errorValue = stuff->depth; + return BadValue; + } + +CreatePmap: + size = PixmapBytePad(width, depth) * height; + if (sizeof(size) == 4 && BitsPerPixel(depth) > 8) { + if (size < width * height) + return BadAlloc; + } + /* thankfully, offset is unsigned */ + if (stuff->offset + size < size) + return BadAlloc; + + VERIFY_SHMSIZE(shmdesc, stuff->offset, size, client); + screen_priv = ShmGetScreenPriv(pDraw->pScreen); + pMap = (*screen_priv->shmFuncs->CreatePixmap)( + pDraw->pScreen, stuff->width, + stuff->height, stuff->depth, + shmdesc->addr + stuff->offset); + if (pMap) + { + rc = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pid, RT_PIXMAP, + pMap, RT_NONE, NULL, DixCreateAccess); + if (rc != Success) { + pDraw->pScreen->DestroyPixmap(pMap); + return rc; + } + dixSetPrivate(&pMap->devPrivates, shmPixmapPrivate, shmdesc); + shmdesc->refcnt++; + pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER; + pMap->drawable.id = stuff->pid; + if (AddResource(stuff->pid, RT_PIXMAP, (pointer)pMap)) + { + return Success; + } + pDraw->pScreen->DestroyPixmap(pMap); + } + return (BadAlloc); +} + +static int +ProcShmDispatch (ClientPtr client) +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_ShmQueryVersion: + return ProcShmQueryVersion(client); + case X_ShmAttach: + return ProcShmAttach(client); + case X_ShmDetach: + return ProcShmDetach(client); + case X_ShmPutImage: +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + return ProcPanoramiXShmPutImage(client); +#endif + return ProcShmPutImage(client); + case X_ShmGetImage: +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + return ProcPanoramiXShmGetImage(client); +#endif + return ProcShmGetImage(client); + case X_ShmCreatePixmap: +#ifdef PANORAMIX + if ( !noPanoramiXExtension ) + return ProcPanoramiXShmCreatePixmap(client); +#endif + return ProcShmCreatePixmap(client); + default: + return BadRequest; + } +} + +static void +SShmCompletionEvent(xShmCompletionEvent *from, xShmCompletionEvent *to) +{ + to->type = from->type; + cpswaps(from->sequenceNumber, to->sequenceNumber); + cpswapl(from->drawable, to->drawable); + cpswaps(from->minorEvent, to->minorEvent); + to->majorEvent = from->majorEvent; + cpswapl(from->shmseg, to->shmseg); + cpswapl(from->offset, to->offset); +} + +static int +SProcShmQueryVersion(ClientPtr client) +{ + int n; + REQUEST(xShmQueryVersionReq); + + swaps(&stuff->length, n); + return ProcShmQueryVersion(client); +} + +static int +SProcShmAttach(ClientPtr client) +{ + int n; + REQUEST(xShmAttachReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xShmAttachReq); + swapl(&stuff->shmseg, n); + swapl(&stuff->shmid, n); + return ProcShmAttach(client); +} + +static int +SProcShmDetach(ClientPtr client) +{ + int n; + REQUEST(xShmDetachReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xShmDetachReq); + swapl(&stuff->shmseg, n); + return ProcShmDetach(client); +} + +static int +SProcShmPutImage(ClientPtr client) +{ + int n; + REQUEST(xShmPutImageReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xShmPutImageReq); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swaps(&stuff->totalWidth, n); + swaps(&stuff->totalHeight, n); + swaps(&stuff->srcX, n); + swaps(&stuff->srcY, n); + swaps(&stuff->srcWidth, n); + swaps(&stuff->srcHeight, n); + swaps(&stuff->dstX, n); + swaps(&stuff->dstY, n); + swapl(&stuff->shmseg, n); + swapl(&stuff->offset, n); + return ProcShmPutImage(client); +} + +static int +SProcShmGetImage(ClientPtr client) +{ + int n; + REQUEST(xShmGetImageReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xShmGetImageReq); + swapl(&stuff->drawable, n); + swaps(&stuff->x, n); + swaps(&stuff->y, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + swapl(&stuff->planeMask, n); + swapl(&stuff->shmseg, n); + swapl(&stuff->offset, n); + return ProcShmGetImage(client); +} + +static int +SProcShmCreatePixmap(ClientPtr client) +{ + int n; + REQUEST(xShmCreatePixmapReq); + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xShmCreatePixmapReq); + swapl(&stuff->pid, n); + swapl(&stuff->drawable, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + swapl(&stuff->shmseg, n); + swapl(&stuff->offset, n); + return ProcShmCreatePixmap(client); +} + +static int +SProcShmDispatch (ClientPtr client) +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_ShmQueryVersion: + return SProcShmQueryVersion(client); + case X_ShmAttach: + return SProcShmAttach(client); + case X_ShmDetach: + return SProcShmDetach(client); + case X_ShmPutImage: + return SProcShmPutImage(client); + case X_ShmGetImage: + return SProcShmGetImage(client); + case X_ShmCreatePixmap: + return SProcShmCreatePixmap(client); + default: + return BadRequest; + } +} diff --git a/xorg-server/Xext/sleepuntil.c b/xorg-server/Xext/sleepuntil.c index 075f428d4..69945585d 100644 --- a/xorg-server/Xext/sleepuntil.c +++ b/xorg-server/Xext/sleepuntil.c @@ -1,225 +1,225 @@ -/* - * -Copyright 1992, 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. - * - * Author: Keith Packard, MIT X Consortium - */ - -/* dixsleep.c - implement millisecond timeouts for X clients */ - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include "sleepuntil.h" -#include -#include -#include "misc.h" -#include "windowstr.h" -#include "dixstruct.h" -#include "pixmapstr.h" -#include "scrnintstr.h" - -typedef struct _Sertafied { - struct _Sertafied *next; - TimeStamp revive; - ClientPtr pClient; - XID id; - void (*notifyFunc)( - ClientPtr /* client */, - pointer /* closure */ - ); - - pointer closure; -} SertafiedRec, *SertafiedPtr; - -static SertafiedPtr pPending; -static RESTYPE SertafiedResType; -static Bool BlockHandlerRegistered; -static int SertafiedGeneration; - -static void ClientAwaken( - ClientPtr /* client */, - pointer /* closure */ -); -static int SertafiedDelete( - pointer /* value */, - XID /* id */ -); -static void SertafiedBlockHandler( - pointer /* data */, - OSTimePtr /* wt */, - pointer /* LastSelectMask */ -); -static void SertafiedWakeupHandler( - pointer /* data */, - int /* i */, - pointer /* LastSelectMask */ -); - -int -ClientSleepUntil (ClientPtr client, - TimeStamp *revive, - void (*notifyFunc)(ClientPtr, pointer), - pointer closure) -{ - SertafiedPtr pRequest, pReq, pPrev; - - if (SertafiedGeneration != serverGeneration) - { - SertafiedResType = CreateNewResourceType (SertafiedDelete, - "ClientSleep"); - if (!SertafiedResType) - return FALSE; - SertafiedGeneration = serverGeneration; - BlockHandlerRegistered = FALSE; - } - pRequest = xalloc (sizeof (SertafiedRec)); - if (!pRequest) - return FALSE; - pRequest->pClient = client; - pRequest->revive = *revive; - pRequest->id = FakeClientID (client->index); - pRequest->closure = closure; - if (!BlockHandlerRegistered) - { - if (!RegisterBlockAndWakeupHandlers (SertafiedBlockHandler, - SertafiedWakeupHandler, - (pointer) 0)) - { - xfree (pRequest); - return FALSE; - } - BlockHandlerRegistered = TRUE; - } - pRequest->notifyFunc = 0; - if (!AddResource (pRequest->id, SertafiedResType, (pointer) pRequest)) - return FALSE; - if (!notifyFunc) - notifyFunc = ClientAwaken; - pRequest->notifyFunc = notifyFunc; - /* Insert into time-ordered queue, with earliest activation time coming first. */ - pPrev = 0; - for (pReq = pPending; pReq; pReq = pReq->next) - { - if (CompareTimeStamps (pReq->revive, *revive) == LATER) - break; - pPrev = pReq; - } - if (pPrev) - pPrev->next = pRequest; - else - pPending = pRequest; - pRequest->next = pReq; - IgnoreClient (client); - return TRUE; -} - -static void -ClientAwaken (ClientPtr client, pointer closure) -{ - if (!client->clientGone) - AttendClient (client); -} - - -static int -SertafiedDelete (pointer value, XID id) -{ - SertafiedPtr pRequest = (SertafiedPtr)value; - SertafiedPtr pReq, pPrev; - - pPrev = 0; - for (pReq = pPending; pReq; pPrev = pReq, pReq = pReq->next) - if (pReq == pRequest) - { - if (pPrev) - pPrev->next = pReq->next; - else - pPending = pReq->next; - break; - } - if (pRequest->notifyFunc) - (*pRequest->notifyFunc) (pRequest->pClient, pRequest->closure); - xfree (pRequest); - return TRUE; -} - -static void -SertafiedBlockHandler (pointer data, OSTimePtr wt, pointer LastSelectMask) -{ - SertafiedPtr pReq, pNext; - unsigned long delay; - TimeStamp now; - - if (!pPending) - return; - now.milliseconds = GetTimeInMillis (); - now.months = currentTime.months; - if ((int) (now.milliseconds - currentTime.milliseconds) < 0) - now.months++; - for (pReq = pPending; pReq; pReq = pNext) - { - pNext = pReq->next; - if (CompareTimeStamps (pReq->revive, now) == LATER) - break; - FreeResource (pReq->id, RT_NONE); - - /* AttendClient() may have been called via the resource delete - * function so a client may have input to be processed and so - * set delay to 0 to prevent blocking in WaitForSomething(). - */ - AdjustWaitForDelay (wt, 0); - } - pReq = pPending; - if (!pReq) - return; - delay = pReq->revive.milliseconds - now.milliseconds; - AdjustWaitForDelay (wt, delay); -} - -static void -SertafiedWakeupHandler (pointer data, int i, pointer LastSelectMask) -{ - SertafiedPtr pReq, pNext; - TimeStamp now; - - now.milliseconds = GetTimeInMillis (); - now.months = currentTime.months; - if ((int) (now.milliseconds - currentTime.milliseconds) < 0) - now.months++; - for (pReq = pPending; pReq; pReq = pNext) - { - pNext = pReq->next; - if (CompareTimeStamps (pReq->revive, now) == LATER) - break; - FreeResource (pReq->id, RT_NONE); - } - if (!pPending) - { - RemoveBlockAndWakeupHandlers (SertafiedBlockHandler, - SertafiedWakeupHandler, - (pointer) 0); - BlockHandlerRegistered = FALSE; - } -} +/* + * +Copyright 1992, 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. + * + * Author: Keith Packard, MIT X Consortium + */ + +/* dixsleep.c - implement millisecond timeouts for X clients */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include "sleepuntil.h" +#include +#include +#include "misc.h" +#include "windowstr.h" +#include "dixstruct.h" +#include "pixmapstr.h" +#include "scrnintstr.h" + +typedef struct _Sertafied { + struct _Sertafied *next; + TimeStamp revive; + ClientPtr pClient; + XID id; + void (*notifyFunc)( + ClientPtr /* client */, + pointer /* closure */ + ); + + pointer closure; +} SertafiedRec, *SertafiedPtr; + +static SertafiedPtr pPending; +static RESTYPE SertafiedResType; +static Bool BlockHandlerRegistered; +static int SertafiedGeneration; + +static void ClientAwaken( + ClientPtr /* client */, + pointer /* closure */ +); +static int SertafiedDelete( + pointer /* value */, + XID /* id */ +); +static void SertafiedBlockHandler( + pointer /* data */, + OSTimePtr /* wt */, + pointer /* LastSelectMask */ +); +static void SertafiedWakeupHandler( + pointer /* data */, + int /* i */, + pointer /* LastSelectMask */ +); + +int +ClientSleepUntil (ClientPtr client, + TimeStamp *revive, + void (*notifyFunc)(ClientPtr, pointer), + pointer closure) +{ + SertafiedPtr pRequest, pReq, pPrev; + + if (SertafiedGeneration != serverGeneration) + { + SertafiedResType = CreateNewResourceType (SertafiedDelete, + "ClientSleep"); + if (!SertafiedResType) + return FALSE; + SertafiedGeneration = serverGeneration; + BlockHandlerRegistered = FALSE; + } + pRequest = malloc(sizeof (SertafiedRec)); + if (!pRequest) + return FALSE; + pRequest->pClient = client; + pRequest->revive = *revive; + pRequest->id = FakeClientID (client->index); + pRequest->closure = closure; + if (!BlockHandlerRegistered) + { + if (!RegisterBlockAndWakeupHandlers (SertafiedBlockHandler, + SertafiedWakeupHandler, + (pointer) 0)) + { + free(pRequest); + return FALSE; + } + BlockHandlerRegistered = TRUE; + } + pRequest->notifyFunc = 0; + if (!AddResource (pRequest->id, SertafiedResType, (pointer) pRequest)) + return FALSE; + if (!notifyFunc) + notifyFunc = ClientAwaken; + pRequest->notifyFunc = notifyFunc; + /* Insert into time-ordered queue, with earliest activation time coming first. */ + pPrev = 0; + for (pReq = pPending; pReq; pReq = pReq->next) + { + if (CompareTimeStamps (pReq->revive, *revive) == LATER) + break; + pPrev = pReq; + } + if (pPrev) + pPrev->next = pRequest; + else + pPending = pRequest; + pRequest->next = pReq; + IgnoreClient (client); + return TRUE; +} + +static void +ClientAwaken (ClientPtr client, pointer closure) +{ + if (!client->clientGone) + AttendClient (client); +} + + +static int +SertafiedDelete (pointer value, XID id) +{ + SertafiedPtr pRequest = (SertafiedPtr)value; + SertafiedPtr pReq, pPrev; + + pPrev = 0; + for (pReq = pPending; pReq; pPrev = pReq, pReq = pReq->next) + if (pReq == pRequest) + { + if (pPrev) + pPrev->next = pReq->next; + else + pPending = pReq->next; + break; + } + if (pRequest->notifyFunc) + (*pRequest->notifyFunc) (pRequest->pClient, pRequest->closure); + free(pRequest); + return TRUE; +} + +static void +SertafiedBlockHandler (pointer data, OSTimePtr wt, pointer LastSelectMask) +{ + SertafiedPtr pReq, pNext; + unsigned long delay; + TimeStamp now; + + if (!pPending) + return; + now.milliseconds = GetTimeInMillis (); + now.months = currentTime.months; + if ((int) (now.milliseconds - currentTime.milliseconds) < 0) + now.months++; + for (pReq = pPending; pReq; pReq = pNext) + { + pNext = pReq->next; + if (CompareTimeStamps (pReq->revive, now) == LATER) + break; + FreeResource (pReq->id, RT_NONE); + + /* AttendClient() may have been called via the resource delete + * function so a client may have input to be processed and so + * set delay to 0 to prevent blocking in WaitForSomething(). + */ + AdjustWaitForDelay (wt, 0); + } + pReq = pPending; + if (!pReq) + return; + delay = pReq->revive.milliseconds - now.milliseconds; + AdjustWaitForDelay (wt, delay); +} + +static void +SertafiedWakeupHandler (pointer data, int i, pointer LastSelectMask) +{ + SertafiedPtr pReq, pNext; + TimeStamp now; + + now.milliseconds = GetTimeInMillis (); + now.months = currentTime.months; + if ((int) (now.milliseconds - currentTime.milliseconds) < 0) + now.months++; + for (pReq = pPending; pReq; pReq = pNext) + { + pNext = pReq->next; + if (CompareTimeStamps (pReq->revive, now) == LATER) + break; + FreeResource (pReq->id, RT_NONE); + } + if (!pPending) + { + RemoveBlockAndWakeupHandlers (SertafiedBlockHandler, + SertafiedWakeupHandler, + (pointer) 0); + BlockHandlerRegistered = FALSE; + } +} diff --git a/xorg-server/Xext/sync.c b/xorg-server/Xext/sync.c index e865e527a..8faab0d1d 100644 --- a/xorg-server/Xext/sync.c +++ b/xorg-server/Xext/sync.c @@ -1,2399 +1,2399 @@ -/* - -Copyright 1991, 1993, 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 1991, 1993 by Digital Equipment Corporation, Maynard, Massachusetts, -and Olivetti Research Limited, Cambridge, England. - - 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 names of Digital or Olivetti -not be used in advertising or publicity pertaining to distribution of the -software without specific, written prior permission. Digital and Olivetti -make no representations about the suitability of this software -for any purpose. It is provided "as is" without express or implied warranty. - -DIGITAL AND OLIVETTI DISCLAIM ALL WARRANTIES WITH REGARD TO THIS -SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND -FITNESS, IN NO EVENT SHALL THEY 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. - -*/ - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include - -#include -#include -#include -#include "misc.h" -#include "os.h" -#include "extnsionst.h" -#include "dixstruct.h" -#include "resource.h" -#include "opaque.h" -#include -#include "syncsrv.h" - -#include -#if !defined(WIN32) -#include -#endif - -#include "modinit.h" - -/* - * Local Global Variables - */ -static int SyncEventBase; -static int SyncErrorBase; -static RESTYPE RTCounter = 0; -static RESTYPE RTAwait; -static RESTYPE RTAlarm; -static RESTYPE RTAlarmClient; -static int SyncNumSystemCounters = 0; -static SyncCounter **SysCounterList = NULL; - -#define IsSystemCounter(pCounter) \ - (pCounter && (pCounter->client == NULL)) - -/* these are all the alarm attributes that pertain to the alarm's trigger */ -#define XSyncCAAllTrigger \ - (XSyncCACounter | XSyncCAValueType | XSyncCAValue | XSyncCATestType) - -static void SyncComputeBracketValues(SyncCounter *); - -static void SyncInitServerTime(void); - -static void SyncInitIdleTime(void); - -static DISPATCH_PROC(ProcSyncAwait); -static DISPATCH_PROC(ProcSyncChangeAlarm); -static DISPATCH_PROC(ProcSyncChangeCounter); -static DISPATCH_PROC(ProcSyncCreateAlarm); -static DISPATCH_PROC(ProcSyncCreateCounter); -static DISPATCH_PROC(ProcSyncDestroyAlarm); -static DISPATCH_PROC(ProcSyncDestroyCounter); -static DISPATCH_PROC(ProcSyncDispatch); -static DISPATCH_PROC(ProcSyncGetPriority); -static DISPATCH_PROC(ProcSyncInitialize); -static DISPATCH_PROC(ProcSyncListSystemCounters); -static DISPATCH_PROC(ProcSyncQueryAlarm); -static DISPATCH_PROC(ProcSyncQueryCounter); -static DISPATCH_PROC(ProcSyncSetCounter); -static DISPATCH_PROC(ProcSyncSetPriority); -static DISPATCH_PROC(SProcSyncAwait); -static DISPATCH_PROC(SProcSyncChangeAlarm); -static DISPATCH_PROC(SProcSyncChangeCounter); -static DISPATCH_PROC(SProcSyncCreateAlarm); -static DISPATCH_PROC(SProcSyncCreateCounter); -static DISPATCH_PROC(SProcSyncDestroyAlarm); -static DISPATCH_PROC(SProcSyncDestroyCounter); -static DISPATCH_PROC(SProcSyncDispatch); -static DISPATCH_PROC(SProcSyncGetPriority); -static DISPATCH_PROC(SProcSyncInitialize); -static DISPATCH_PROC(SProcSyncListSystemCounters); -static DISPATCH_PROC(SProcSyncQueryAlarm); -static DISPATCH_PROC(SProcSyncQueryCounter); -static DISPATCH_PROC(SProcSyncSetCounter); -static DISPATCH_PROC(SProcSyncSetPriority); - -/* Each counter maintains a simple linked list of triggers that are - * interested in the counter. The two functions below are used to - * delete and add triggers on this list. - */ -static void -SyncDeleteTriggerFromCounter(SyncTrigger *pTrigger) -{ - SyncTriggerList *pCur; - SyncTriggerList *pPrev; - - /* pCounter needs to be stored in pTrigger before calling here. */ - - if (!pTrigger->pCounter) - return; - - pPrev = NULL; - pCur = pTrigger->pCounter->pTriglist; - - while (pCur) - { - if (pCur->pTrigger == pTrigger) - { - if (pPrev) - pPrev->next = pCur->next; - else - pTrigger->pCounter->pTriglist = pCur->next; - - xfree(pCur); - break; - } - - pPrev = pCur; - pCur = pCur->next; - } - - if (IsSystemCounter(pTrigger->pCounter)) - SyncComputeBracketValues(pTrigger->pCounter); -} - - -static int -SyncAddTriggerToCounter(SyncTrigger *pTrigger) -{ - SyncTriggerList *pCur; - - if (!pTrigger->pCounter) - return Success; - - /* don't do anything if it's already there */ - for (pCur = pTrigger->pCounter->pTriglist; pCur; pCur = pCur->next) - { - if (pCur->pTrigger == pTrigger) - return Success; - } - - if (!(pCur = xalloc(sizeof(SyncTriggerList)))) - return BadAlloc; - - pCur->pTrigger = pTrigger; - pCur->next = pTrigger->pCounter->pTriglist; - pTrigger->pCounter->pTriglist = pCur; - - if (IsSystemCounter(pTrigger->pCounter)) - SyncComputeBracketValues(pTrigger->pCounter); - - return Success; -} - - -/* Below are four possible functions that can be plugged into - * pTrigger->CheckTrigger, corresponding to the four possible - * test-types. These functions are called after the counter's - * value changes but are also passed the old counter value - * so they can inspect both the old and new values. - * (PositiveTransition and NegativeTransition need to see both - * pieces of information.) These functions return the truth value - * of the trigger. - * - * All of them include the condition pTrigger->pCounter == NULL. - * This is because the spec says that a trigger with a counter value - * of None is always TRUE. - */ - -static Bool -SyncCheckTriggerPositiveComparison(SyncTrigger *pTrigger, CARD64 oldval) -{ - return (pTrigger->pCounter == NULL || - XSyncValueGreaterOrEqual(pTrigger->pCounter->value, - pTrigger->test_value)); -} - -static Bool -SyncCheckTriggerNegativeComparison(SyncTrigger *pTrigger, CARD64 oldval) -{ - return (pTrigger->pCounter == NULL || - XSyncValueLessOrEqual(pTrigger->pCounter->value, - pTrigger->test_value)); -} - -static Bool -SyncCheckTriggerPositiveTransition(SyncTrigger *pTrigger, CARD64 oldval) -{ - return (pTrigger->pCounter == NULL || - (XSyncValueLessThan(oldval, pTrigger->test_value) && - XSyncValueGreaterOrEqual(pTrigger->pCounter->value, - pTrigger->test_value))); -} - -static Bool -SyncCheckTriggerNegativeTransition(SyncTrigger *pTrigger, CARD64 oldval) -{ - return (pTrigger->pCounter == NULL || - (XSyncValueGreaterThan(oldval, pTrigger->test_value) && - XSyncValueLessOrEqual(pTrigger->pCounter->value, - pTrigger->test_value))); -} - -static int -SyncInitTrigger(ClientPtr client, SyncTrigger *pTrigger, XSyncCounter counter, - Mask changes) -{ - SyncCounter *pCounter = pTrigger->pCounter; - int rc; - Bool newcounter = FALSE; - - if (changes & XSyncCACounter) - { - if (counter == None) - pCounter = NULL; - else if (Success != (rc = dixLookupResourceByType ((pointer *)&pCounter, - counter, RTCounter, client, DixReadAccess))) - { - client->errorValue = counter; - return (rc == BadValue) ? SyncErrorBase + XSyncBadCounter : rc; - } - if (pCounter != pTrigger->pCounter) - { /* new counter for trigger */ - SyncDeleteTriggerFromCounter(pTrigger); - pTrigger->pCounter = pCounter; - newcounter = TRUE; - } - } - - /* if system counter, ask it what the current value is */ - - if (IsSystemCounter(pCounter)) - { - (*pCounter->pSysCounterInfo->QueryValue) ((pointer) pCounter, - &pCounter->value); - } - - if (changes & XSyncCAValueType) - { - if (pTrigger->value_type != XSyncRelative && - pTrigger->value_type != XSyncAbsolute) - { - client->errorValue = pTrigger->value_type; - return BadValue; - } - } - - if (changes & XSyncCATestType) - { - if (pTrigger->test_type != XSyncPositiveTransition && - pTrigger->test_type != XSyncNegativeTransition && - pTrigger->test_type != XSyncPositiveComparison && - pTrigger->test_type != XSyncNegativeComparison) - { - client->errorValue = pTrigger->test_type; - return BadValue; - } - /* select appropriate CheckTrigger function */ - - switch (pTrigger->test_type) - { - case XSyncPositiveTransition: - pTrigger->CheckTrigger = SyncCheckTriggerPositiveTransition; - break; - case XSyncNegativeTransition: - pTrigger->CheckTrigger = SyncCheckTriggerNegativeTransition; - break; - case XSyncPositiveComparison: - pTrigger->CheckTrigger = SyncCheckTriggerPositiveComparison; - break; - case XSyncNegativeComparison: - pTrigger->CheckTrigger = SyncCheckTriggerNegativeComparison; - break; - } - } - - if (changes & (XSyncCAValueType | XSyncCAValue)) - { - if (pTrigger->value_type == XSyncAbsolute) - pTrigger->test_value = pTrigger->wait_value; - else /* relative */ - { - Bool overflow; - if (pCounter == NULL) - return BadMatch; - - XSyncValueAdd(&pTrigger->test_value, pCounter->value, - pTrigger->wait_value, &overflow); - if (overflow) - { - client->errorValue = XSyncValueHigh32(pTrigger->wait_value); - return BadValue; - } - } - } - - /* we wait until we're sure there are no errors before registering - * a new counter on a trigger - */ - if (newcounter) - { - if ((rc = SyncAddTriggerToCounter(pTrigger)) != Success) - return rc; - } - else if (IsSystemCounter(pCounter)) - { - SyncComputeBracketValues(pCounter); - } - - return Success; -} - -/* AlarmNotify events happen in response to actions taken on an Alarm or - * the counter used by the alarm. AlarmNotify may be sent to multiple - * clients. The alarm maintains a list of clients interested in events. - */ -static void -SyncSendAlarmNotifyEvents(SyncAlarm *pAlarm) -{ - SyncAlarmClientList *pcl; - xSyncAlarmNotifyEvent ane; - SyncTrigger *pTrigger = &pAlarm->trigger; - - UpdateCurrentTime(); - - ane.type = SyncEventBase + XSyncAlarmNotify; - ane.kind = XSyncAlarmNotify; - ane.sequenceNumber = pAlarm->client->sequence; - ane.alarm = pAlarm->alarm_id; - if (pTrigger->pCounter) - { - ane.counter_value_hi = XSyncValueHigh32(pTrigger->pCounter->value); - ane.counter_value_lo = XSyncValueLow32(pTrigger->pCounter->value); - } - else - { /* XXX what else can we do if there's no counter? */ - ane.counter_value_hi = ane.counter_value_lo = 0; - } - - ane.alarm_value_hi = XSyncValueHigh32(pTrigger->test_value); - ane.alarm_value_lo = XSyncValueLow32(pTrigger->test_value); - ane.time = currentTime.milliseconds; - ane.state = pAlarm->state; - - /* send to owner */ - if (pAlarm->events && !pAlarm->client->clientGone) - WriteEventsToClient(pAlarm->client, 1, (xEvent *) &ane); - - /* send to other interested clients */ - for (pcl = pAlarm->pEventClients; pcl; pcl = pcl->next) - { - if (!pAlarm->client->clientGone) - { - ane.sequenceNumber = pcl->client->sequence; - WriteEventsToClient(pcl->client, 1, (xEvent *) &ane); - } - } -} - - -/* CounterNotify events only occur in response to an Await. The events - * go only to the Awaiting client. - */ -static void -SyncSendCounterNotifyEvents(ClientPtr client, SyncAwait **ppAwait, - int num_events) -{ - xSyncCounterNotifyEvent *pEvents, *pev; - int i; - - if (client->clientGone) - return; - pev = pEvents = xalloc(num_events * sizeof(xSyncCounterNotifyEvent)); - if (!pEvents) - return; - UpdateCurrentTime(); - for (i = 0; i < num_events; i++, ppAwait++, pev++) - { - SyncTrigger *pTrigger = &(*ppAwait)->trigger; - pev->type = SyncEventBase + XSyncCounterNotify; - pev->kind = XSyncCounterNotify; - pev->sequenceNumber = client->sequence; - pev->counter = pTrigger->pCounter->id; - pev->wait_value_lo = XSyncValueLow32(pTrigger->test_value); - pev->wait_value_hi = XSyncValueHigh32(pTrigger->test_value); - pev->counter_value_lo = XSyncValueLow32(pTrigger->pCounter->value); - pev->counter_value_hi = XSyncValueHigh32(pTrigger->pCounter->value); - pev->time = currentTime.milliseconds; - pev->count = num_events - i - 1; /* events remaining */ - pev->destroyed = pTrigger->pCounter->beingDestroyed; - } - /* swapping will be taken care of by this */ - WriteEventsToClient(client, num_events, (xEvent *)pEvents); - xfree(pEvents); -} - - -/* This function is called when an alarm's counter is destroyed. - * It is plugged into pTrigger->CounterDestroyed (for alarm triggers). - */ -static void -SyncAlarmCounterDestroyed(SyncTrigger *pTrigger) -{ - SyncAlarm *pAlarm = (SyncAlarm *)pTrigger; - - pAlarm->state = XSyncAlarmInactive; - SyncSendAlarmNotifyEvents(pAlarm); - pTrigger->pCounter = NULL; -} - - -/* This function is called when an alarm "goes off." - * It is plugged into pTrigger->TriggerFired (for alarm triggers). - */ -static void -SyncAlarmTriggerFired(SyncTrigger *pTrigger) -{ - SyncAlarm *pAlarm = (SyncAlarm *)pTrigger; - CARD64 new_test_value; - - /* no need to check alarm unless it's active */ - if (pAlarm->state != XSyncAlarmActive) - return; - - /* " if the counter value is None, or if the delta is 0 and - * the test-type is PositiveComparison or NegativeComparison, - * no change is made to value (test-value) and the alarm - * state is changed to Inactive before the event is generated." - */ - if (pAlarm->trigger.pCounter == NULL - || (XSyncValueIsZero(pAlarm->delta) - && (pAlarm->trigger.test_type == XSyncPositiveComparison - || pAlarm->trigger.test_type == XSyncNegativeComparison))) - pAlarm->state = XSyncAlarmInactive; - - new_test_value = pAlarm->trigger.test_value; - - if (pAlarm->state == XSyncAlarmActive) - { - Bool overflow; - CARD64 oldvalue; - SyncTrigger *paTrigger = &pAlarm->trigger; - - /* "The alarm is updated by repeatedly adding delta to the - * value of the trigger and re-initializing it until it - * becomes FALSE." - */ - oldvalue = paTrigger->test_value; - - /* XXX really should do something smarter here */ - - do - { - XSyncValueAdd(&paTrigger->test_value, paTrigger->test_value, - pAlarm->delta, &overflow); - } while (!overflow && - (*paTrigger->CheckTrigger)(paTrigger, - paTrigger->pCounter->value)); - - new_test_value = paTrigger->test_value; - paTrigger->test_value = oldvalue; - - /* "If this update would cause value to fall outside the range - * for an INT64...no change is made to value (test-value) and - * the alarm state is changed to Inactive before the event is - * generated." - */ - if (overflow) - { - new_test_value = oldvalue; - pAlarm->state = XSyncAlarmInactive; - } - } - /* The AlarmNotify event has to have the "new state of the alarm" - * which we can't be sure of until this point. However, it has - * to have the "old" trigger test value. That's the reason for - * all the newvalue/oldvalue shuffling above. After we send the - * events, give the trigger its new test value. - */ - SyncSendAlarmNotifyEvents(pAlarm); - pTrigger->test_value = new_test_value; -} - - -/* This function is called when an Await unblocks, either as a result - * of the trigger firing OR the counter being destroyed. - * It goes into pTrigger->TriggerFired AND pTrigger->CounterDestroyed - * (for Await triggers). - */ -static void -SyncAwaitTriggerFired(SyncTrigger *pTrigger) -{ - SyncAwait *pAwait = (SyncAwait *)pTrigger; - int numwaits; - SyncAwaitUnion *pAwaitUnion; - SyncAwait **ppAwait; - int num_events = 0; - - pAwaitUnion = (SyncAwaitUnion *)pAwait->pHeader; - numwaits = pAwaitUnion->header.num_waitconditions; - ppAwait = xalloc(numwaits * sizeof(SyncAwait *)); - if (!ppAwait) - goto bail; - - pAwait = &(pAwaitUnion+1)->await; - - /* "When a client is unblocked, all the CounterNotify events for - * the Await request are generated contiguously. If count is 0 - * there are no more events to follow for this request. If - * count is n, there are at least n more events to follow." - * - * Thus, it is best to find all the counters for which events - * need to be sent first, so that an accurate count field can - * be stored in the events. - */ - for ( ; numwaits; numwaits--, pAwait++) - { - CARD64 diff; - Bool overflow, diffgreater, diffequal; - - /* "A CounterNotify event with the destroyed flag set to TRUE is - * always generated if the counter for one of the triggers is - * destroyed." - */ - if (pAwait->trigger.pCounter->beingDestroyed) - { - ppAwait[num_events++] = pAwait; - continue; - } - - /* "The difference between the counter and the test value is - * calculated by subtracting the test value from the value of - * the counter." - */ - XSyncValueSubtract(&diff, pAwait->trigger.pCounter->value, - pAwait->trigger.test_value, &overflow); - - /* "If the difference lies outside the range for an INT64, an - * event is not generated." - */ - if (overflow) - continue; - diffgreater = XSyncValueGreaterThan(diff, pAwait->event_threshold); - diffequal = XSyncValueEqual(diff, pAwait->event_threshold); - - /* "If the test-type is PositiveTransition or - * PositiveComparison, a CounterNotify event is generated if - * the difference is at least event-threshold. If the test-type - * is NegativeTransition or NegativeComparison, a CounterNotify - * event is generated if the difference is at most - * event-threshold." - */ - - if ( ((pAwait->trigger.test_type == XSyncPositiveComparison || - pAwait->trigger.test_type == XSyncPositiveTransition) - && (diffgreater || diffequal)) - || - ((pAwait->trigger.test_type == XSyncNegativeComparison || - pAwait->trigger.test_type == XSyncNegativeTransition) - && (!diffgreater) /* less or equal */ - ) - ) - { - ppAwait[num_events++] = pAwait; - } - } - if (num_events) - SyncSendCounterNotifyEvents(pAwaitUnion->header.client, ppAwait, - num_events); - xfree(ppAwait); - -bail: - /* unblock the client */ - AttendClient(pAwaitUnion->header.client); - /* delete the await */ - FreeResource(pAwaitUnion->header.delete_id, RT_NONE); -} - - -/* This function should always be used to change a counter's value so that - * any triggers depending on the counter will be checked. - */ -void -SyncChangeCounter(SyncCounter *pCounter, CARD64 newval) -{ - SyncTriggerList *ptl, *pnext; - CARD64 oldval; - - oldval = pCounter->value; - pCounter->value = newval; - - /* run through triggers to see if any become true */ - for (ptl = pCounter->pTriglist; ptl; ptl = pnext) - { - pnext = ptl->next; - if ((*ptl->pTrigger->CheckTrigger)(ptl->pTrigger, oldval)) - (*ptl->pTrigger->TriggerFired)(ptl->pTrigger); - } - - if (IsSystemCounter(pCounter)) - { - SyncComputeBracketValues(pCounter); - } -} - - -/* loosely based on dix/events.c/EventSelectForWindow */ -static Bool -SyncEventSelectForAlarm(SyncAlarm *pAlarm, ClientPtr client, Bool wantevents) -{ - SyncAlarmClientList *pClients; - - if (client == pAlarm->client) /* alarm owner */ - { - pAlarm->events = wantevents; - return Success; - } - - /* see if the client is already on the list (has events selected) */ - - for (pClients = pAlarm->pEventClients; pClients; - pClients = pClients->next) - { - if (pClients->client == client) - { - /* client's presence on the list indicates desire for - * events. If the client doesn't want events, remove it - * from the list. If the client does want events, do - * nothing, since it's already got them. - */ - if (!wantevents) - { - FreeResource(pClients->delete_id, RT_NONE); - } - return Success; - } - } - - /* if we get here, this client does not currently have - * events selected on the alarm - */ - - if (!wantevents) - /* client doesn't want events, and we just discovered that it - * doesn't have them, so there's nothing to do. - */ - return Success; - - /* add new client to pAlarm->pEventClients */ - - pClients = xalloc(sizeof(SyncAlarmClientList)); - if (!pClients) - return BadAlloc; - - /* register it as a resource so it will be cleaned up - * if the client dies - */ - - pClients->delete_id = FakeClientID(client->index); - if (!AddResource(pClients->delete_id, RTAlarmClient, pAlarm)) - { - xfree(pClients); - return BadAlloc; - } - - /* link it into list after we know all the allocations succeed */ - - pClients->next = pAlarm->pEventClients; - pAlarm->pEventClients = pClients; - pClients->client = client; - return Success; -} - -/* - * ** SyncChangeAlarmAttributes ** This is used by CreateAlarm and ChangeAlarm - */ -static int -SyncChangeAlarmAttributes(ClientPtr client, SyncAlarm *pAlarm, Mask mask, - CARD32 *values) -{ - int status; - XSyncCounter counter; - Mask origmask = mask; - - counter = pAlarm->trigger.pCounter ? pAlarm->trigger.pCounter->id : None; - - while (mask) - { - int index2 = lowbit(mask); - mask &= ~index2; - switch (index2) - { - case XSyncCACounter: - mask &= ~XSyncCACounter; - /* sanity check in SyncInitTrigger */ - counter = *values++; - break; - - case XSyncCAValueType: - mask &= ~XSyncCAValueType; - /* sanity check in SyncInitTrigger */ - pAlarm->trigger.value_type = *values++; - break; - - case XSyncCAValue: - mask &= ~XSyncCAValue; - XSyncIntsToValue(&pAlarm->trigger.wait_value, values[1], values[0]); - values += 2; - break; - - case XSyncCATestType: - mask &= ~XSyncCATestType; - /* sanity check in SyncInitTrigger */ - pAlarm->trigger.test_type = *values++; - break; - - case XSyncCADelta: - mask &= ~XSyncCADelta; - XSyncIntsToValue(&pAlarm->delta, values[1], values[0]); - values += 2; - break; - - case XSyncCAEvents: - mask &= ~XSyncCAEvents; - if ((*values != xTrue) && (*values != xFalse)) - { - client->errorValue = *values; - return BadValue; - } - status = SyncEventSelectForAlarm(pAlarm, client, - (Bool)(*values++)); - if (status != Success) - return status; - break; - - default: - client->errorValue = mask; - return BadValue; - } - } - - /* "If the test-type is PositiveComparison or PositiveTransition - * and delta is less than zero, or if the test-type is - * NegativeComparison or NegativeTransition and delta is - * greater than zero, a Match error is generated." - */ - if (origmask & (XSyncCADelta|XSyncCATestType)) - { - CARD64 zero; - XSyncIntToValue(&zero, 0); - if ((((pAlarm->trigger.test_type == XSyncPositiveComparison) || - (pAlarm->trigger.test_type == XSyncPositiveTransition)) - && XSyncValueLessThan(pAlarm->delta, zero)) - || - (((pAlarm->trigger.test_type == XSyncNegativeComparison) || - (pAlarm->trigger.test_type == XSyncNegativeTransition)) - && XSyncValueGreaterThan(pAlarm->delta, zero)) - ) - { - return BadMatch; - } - } - - /* postpone this until now, when we're sure nothing else can go wrong */ - if ((status = SyncInitTrigger(client, &pAlarm->trigger, counter, - origmask & XSyncCAAllTrigger)) != Success) - return status; - - /* XXX spec does not really say to do this - needs clarification */ - pAlarm->state = XSyncAlarmActive; - return Success; -} - - -static SyncCounter * -SyncCreateCounter(ClientPtr client, XSyncCounter id, CARD64 initialvalue) -{ - SyncCounter *pCounter; - - if (!(pCounter = xalloc(sizeof(SyncCounter)))) - return NULL; - - if (!AddResource(id, RTCounter, (pointer) pCounter)) - { - xfree(pCounter); - return NULL; - } - - pCounter->client = client; - pCounter->id = id; - pCounter->value = initialvalue; - pCounter->pTriglist = NULL; - pCounter->beingDestroyed = FALSE; - pCounter->pSysCounterInfo = NULL; - return pCounter; -} - -static int FreeCounter(void *, XID); - -/* - * ***** System Counter utilities - */ - -pointer -SyncCreateSystemCounter( - char *name, - CARD64 initial, - CARD64 resolution, - SyncCounterType counterType, - void (*QueryValue)(pointer /* pCounter */, - CARD64 * /* pValue_return */), - void (*BracketValues)(pointer /* pCounter */, - CARD64 * /* pbracket_less */, - CARD64 * /* pbracket_greater */) - ) -{ - SyncCounter *pCounter; - - SysCounterList = xrealloc(SysCounterList, - (SyncNumSystemCounters+1)*sizeof(SyncCounter *)); - if (!SysCounterList) - return NULL; - - /* this function may be called before SYNC has been initialized, so we - * have to make sure RTCounter is created. - */ - if (RTCounter == 0) - { - RTCounter = CreateNewResourceType(FreeCounter, "SyncCounter"); - if (RTCounter == 0) - { - return NULL; - } - } - - pCounter = SyncCreateCounter(NULL, FakeClientID(0), initial); - - if (pCounter) - { - SysCounterInfo *psci; - - psci = xalloc(sizeof(SysCounterInfo)); - if (!psci) - { - FreeResource(pCounter->id, RT_NONE); - return pCounter; - } - pCounter->pSysCounterInfo = psci; - psci->name = name; - psci->resolution = resolution; - psci->counterType = counterType; - psci->QueryValue = QueryValue; - psci->BracketValues = BracketValues; - XSyncMaxValue(&psci->bracket_greater); - XSyncMinValue(&psci->bracket_less); - SysCounterList[SyncNumSystemCounters++] = pCounter; - } - return pCounter; -} - -void -SyncDestroySystemCounter(pointer pSysCounter) -{ - SyncCounter *pCounter = (SyncCounter *)pSysCounter; - FreeResource(pCounter->id, RT_NONE); -} - -static void -SyncComputeBracketValues(SyncCounter *pCounter) -{ - SyncTriggerList *pCur; - SyncTrigger *pTrigger; - SysCounterInfo *psci; - CARD64 *pnewgtval = NULL; - CARD64 *pnewltval = NULL; - SyncCounterType ct; - - if (!pCounter) - return; - - psci = pCounter->pSysCounterInfo; - ct = pCounter->pSysCounterInfo->counterType; - if (ct == XSyncCounterNeverChanges) - return; - - XSyncMaxValue(&psci->bracket_greater); - XSyncMinValue(&psci->bracket_less); - - for (pCur = pCounter->pTriglist; pCur; pCur = pCur->next) - { - pTrigger = pCur->pTrigger; - - if (pTrigger->test_type == XSyncPositiveComparison && - ct != XSyncCounterNeverIncreases) - { - if (XSyncValueLessThan(pCounter->value, pTrigger->test_value) && - XSyncValueLessThan(pTrigger->test_value, - psci->bracket_greater)) - { - psci->bracket_greater = pTrigger->test_value; - pnewgtval = &psci->bracket_greater; - } - } - else if (pTrigger->test_type == XSyncNegativeComparison && - ct != XSyncCounterNeverDecreases) - { - if (XSyncValueGreaterThan(pCounter->value, pTrigger->test_value) && - XSyncValueGreaterThan(pTrigger->test_value, - psci->bracket_less)) - { - psci->bracket_less = pTrigger->test_value; - pnewltval = &psci->bracket_less; - } - } - else if (pTrigger->test_type == XSyncNegativeTransition && - ct != XSyncCounterNeverIncreases) - { - if (XSyncValueGreaterThan(pCounter->value, pTrigger->test_value) && - XSyncValueGreaterThan(pTrigger->test_value, psci->bracket_less)) - { - psci->bracket_less = pTrigger->test_value; - pnewltval = &psci->bracket_less; - } - } - else if (pTrigger->test_type == XSyncPositiveTransition && - ct != XSyncCounterNeverDecreases) - { - if (XSyncValueLessThan(pCounter->value, pTrigger->test_value) && - XSyncValueLessThan(pTrigger->test_value, psci->bracket_greater)) - { - psci->bracket_greater = pTrigger->test_value; - pnewgtval = &psci->bracket_greater; - } - } - } /* end for each trigger */ - - if (pnewgtval || pnewltval) - { - (*psci->BracketValues)((pointer)pCounter, pnewltval, pnewgtval); - } -} - -/* - * ***** Resource delete functions - */ - -/* ARGSUSED */ -static int -FreeAlarm(void *addr, XID id) -{ - SyncAlarm *pAlarm = (SyncAlarm *) addr; - - pAlarm->state = XSyncAlarmDestroyed; - - SyncSendAlarmNotifyEvents(pAlarm); - - /* delete event selections */ - - while (pAlarm->pEventClients) - FreeResource(pAlarm->pEventClients->delete_id, RT_NONE); - - SyncDeleteTriggerFromCounter(&pAlarm->trigger); - - xfree(pAlarm); - return Success; -} - - -/* - * ** Cleanup after the destruction of a Counter - */ -/* ARGSUSED */ -static int -FreeCounter(void *env, XID id) -{ - SyncCounter *pCounter = (SyncCounter *) env; - SyncTriggerList *ptl, *pnext; - - pCounter->beingDestroyed = TRUE; - /* tell all the counter's triggers that the counter has been destroyed */ - for (ptl = pCounter->pTriglist; ptl; ptl = pnext) - { - (*ptl->pTrigger->CounterDestroyed)(ptl->pTrigger); - pnext = ptl->next; - xfree(ptl); /* destroy the trigger list as we go */ - } - if (IsSystemCounter(pCounter)) - { - int i, found = 0; - - xfree(pCounter->pSysCounterInfo); - - /* find the counter in the list of system counters and remove it */ - - if (SysCounterList) - { - for (i = 0; i < SyncNumSystemCounters; i++) - { - if (SysCounterList[i] == pCounter) - { - found = i; - break; - } - } - if (found < (SyncNumSystemCounters-1)) - { - for (i = found; i < SyncNumSystemCounters-1; i++) - { - SysCounterList[i] = SysCounterList[i+1]; - } - } - } - SyncNumSystemCounters--; - } - xfree(pCounter); - return Success; -} - -/* - * ** Cleanup after Await - */ -/* ARGSUSED */ -static int -FreeAwait(void *addr, XID id) -{ - SyncAwaitUnion *pAwaitUnion = (SyncAwaitUnion *) addr; - SyncAwait *pAwait; - int numwaits; - - pAwait = &(pAwaitUnion+1)->await; /* first await on list */ - - /* remove triggers from counters */ - - for (numwaits = pAwaitUnion->header.num_waitconditions; numwaits; - numwaits--, pAwait++) - { - /* If the counter is being destroyed, FreeCounter will delete - * the trigger list itself, so don't do it here. - */ - SyncCounter *pCounter = pAwait->trigger.pCounter; - if (pCounter && !pCounter->beingDestroyed) - SyncDeleteTriggerFromCounter(&pAwait->trigger); - } - xfree(pAwaitUnion); - return Success; -} - -/* loosely based on dix/events.c/OtherClientGone */ -static int -FreeAlarmClient(void *value, XID id) -{ - SyncAlarm *pAlarm = (SyncAlarm *)value; - SyncAlarmClientList *pCur, *pPrev; - - for (pPrev = NULL, pCur = pAlarm->pEventClients; - pCur; - pPrev = pCur, pCur = pCur->next) - { - if (pCur->delete_id == id) - { - if (pPrev) - pPrev->next = pCur->next; - else - pAlarm->pEventClients = pCur->next; - xfree(pCur); - return Success; - } - } - FatalError("alarm client not on event list"); - /*NOTREACHED*/ -} - - -/* - * ***** Proc functions - */ - - -/* - * ** Initialize the extension - */ -static int -ProcSyncInitialize(ClientPtr client) -{ - xSyncInitializeReply rep; - int n; - - REQUEST_SIZE_MATCH(xSyncInitializeReq); - - memset(&rep, 0, sizeof(xSyncInitializeReply)); - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.majorVersion = SYNC_MAJOR_VERSION; - rep.minorVersion = SYNC_MINOR_VERSION; - rep.length = 0; - - if (client->swapped) - { - swaps(&rep.sequenceNumber, n); - } - WriteToClient(client, sizeof(rep), (char *) &rep); - return client->noClientException; -} - -/* - * ** Get list of system counters available through the extension - */ -static int -ProcSyncListSystemCounters(ClientPtr client) -{ - xSyncListSystemCountersReply rep; - int i, len; - xSyncSystemCounter *list = NULL, *walklist = NULL; - - REQUEST_SIZE_MATCH(xSyncListSystemCountersReq); - - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.nCounters = SyncNumSystemCounters; - - for (i = len = 0; i < SyncNumSystemCounters; i++) - { - char *name = SysCounterList[i]->pSysCounterInfo->name; - /* pad to 4 byte boundary */ - len += pad_to_int32(sz_xSyncSystemCounter + strlen(name)); - } - - if (len) - { - walklist = list = xalloc(len); - if (!list) - return BadAlloc; - } - - rep.length = bytes_to_int32(len); - - if (client->swapped) - { - char n; - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swapl(&rep.nCounters, n); - } - - for (i = 0; i < SyncNumSystemCounters; i++) - { - int namelen; - char *pname_in_reply; - SysCounterInfo *psci = SysCounterList[i]->pSysCounterInfo; - - walklist->counter = SysCounterList[i]->id; - walklist->resolution_hi = XSyncValueHigh32(psci->resolution); - walklist->resolution_lo = XSyncValueLow32(psci->resolution); - namelen = strlen(psci->name); - walklist->name_length = namelen; - - if (client->swapped) - { - char n; - swapl(&walklist->counter, n); - swapl(&walklist->resolution_hi, n); - swapl(&walklist->resolution_lo, n); - swaps(&walklist->name_length, n); - } - - pname_in_reply = ((char *)walklist) + sz_xSyncSystemCounter; - strncpy(pname_in_reply, psci->name, namelen); - walklist = (xSyncSystemCounter *) (((char *)walklist) + - pad_to_int32(sz_xSyncSystemCounter + namelen)); - } - - WriteToClient(client, sizeof(rep), (char *) &rep); - if (len) - { - WriteToClient(client, len, (char *) list); - xfree(list); - } - - return client->noClientException; -} - -/* - * ** Set client Priority - */ -static int -ProcSyncSetPriority(ClientPtr client) -{ - REQUEST(xSyncSetPriorityReq); - ClientPtr priorityclient; - int rc; - - REQUEST_SIZE_MATCH(xSyncSetPriorityReq); - - if (stuff->id == None) - priorityclient = client; - else { - rc = dixLookupClient(&priorityclient, stuff->id, client, - DixSetAttrAccess); - if (rc != Success) - return rc; - } - - if (priorityclient->priority != stuff->priority) - { - priorityclient->priority = stuff->priority; - - /* The following will force the server back into WaitForSomething - * so that the change in this client's priority is immediately - * reflected. - */ - isItTimeToYield = TRUE; - dispatchException |= DE_PRIORITYCHANGE; - } - return Success; -} - -/* - * ** Get client Priority - */ -static int -ProcSyncGetPriority(ClientPtr client) -{ - REQUEST(xSyncGetPriorityReq); - xSyncGetPriorityReply rep; - ClientPtr priorityclient; - int rc; - - REQUEST_SIZE_MATCH(xSyncGetPriorityReq); - - if (stuff->id == None) - priorityclient = client; - else { - rc = dixLookupClient(&priorityclient, stuff->id, client, - DixGetAttrAccess); - if (rc != Success) - return rc; - } - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.priority = priorityclient->priority; - - if (client->swapped) - { - char n; - swaps(&rep.sequenceNumber, n); - swapl(&rep.priority, n); - } - - WriteToClient(client, sizeof(xSyncGetPriorityReply), (char *) &rep); - - return client->noClientException; -} - -/* - * ** Create a new counter - */ -static int -ProcSyncCreateCounter(ClientPtr client) -{ - REQUEST(xSyncCreateCounterReq); - CARD64 initial; - - REQUEST_SIZE_MATCH(xSyncCreateCounterReq); - - LEGAL_NEW_RESOURCE(stuff->cid, client); - - XSyncIntsToValue(&initial, stuff->initial_value_lo, stuff->initial_value_hi); - if (!SyncCreateCounter(client, stuff->cid, initial)) - return BadAlloc; - - return client->noClientException; -} - -/* - * ** Set Counter value - */ -static int -ProcSyncSetCounter(ClientPtr client) -{ - REQUEST(xSyncSetCounterReq); - SyncCounter *pCounter; - CARD64 newvalue; - int rc; - - REQUEST_SIZE_MATCH(xSyncSetCounterReq); - - rc = dixLookupResourceByType((pointer *)&pCounter, stuff->cid, RTCounter, - client, DixWriteAccess); - if (rc != Success) - return (rc == BadValue) ? SyncErrorBase + XSyncBadCounter : rc; - - if (IsSystemCounter(pCounter)) - { - client->errorValue = stuff->cid; - return BadAccess; - } - - XSyncIntsToValue(&newvalue, stuff->value_lo, stuff->value_hi); - SyncChangeCounter(pCounter, newvalue); - return Success; -} - -/* - * ** Change Counter value - */ -static int -ProcSyncChangeCounter(ClientPtr client) -{ - REQUEST(xSyncChangeCounterReq); - SyncCounter *pCounter; - CARD64 newvalue; - Bool overflow; - int rc; - - REQUEST_SIZE_MATCH(xSyncChangeCounterReq); - - rc = dixLookupResourceByType((pointer *)&pCounter, stuff->cid, RTCounter, - client, DixWriteAccess); - if (rc != Success) - return (rc == BadValue) ? SyncErrorBase + XSyncBadCounter : rc; - - if (IsSystemCounter(pCounter)) - { - client->errorValue = stuff->cid; - return BadAccess; - } - - XSyncIntsToValue(&newvalue, stuff->value_lo, stuff->value_hi); - XSyncValueAdd(&newvalue, pCounter->value, newvalue, &overflow); - if (overflow) - { - /* XXX 64 bit value can't fit in 32 bits; do the best we can */ - client->errorValue = stuff->value_hi; - return BadValue; - } - SyncChangeCounter(pCounter, newvalue); - return Success; -} - -/* - * ** Destroy a counter - */ -static int -ProcSyncDestroyCounter(ClientPtr client) -{ - REQUEST(xSyncDestroyCounterReq); - SyncCounter *pCounter; - int rc; - - REQUEST_SIZE_MATCH(xSyncDestroyCounterReq); - - rc = dixLookupResourceByType((pointer *)&pCounter, stuff->counter, RTCounter, - client, DixDestroyAccess); - if (rc != Success) - return (rc == BadValue) ? SyncErrorBase + XSyncBadCounter : rc; - - if (IsSystemCounter(pCounter)) - { - client->errorValue = stuff->counter; - return BadAccess; - } - FreeResource(pCounter->id, RT_NONE); - return Success; -} - - -/* - * ** Await - */ -static int -ProcSyncAwait(ClientPtr client) -{ - REQUEST(xSyncAwaitReq); - int len, items; - int i; - xSyncWaitCondition *pProtocolWaitConds; - SyncAwaitUnion *pAwaitUnion; - SyncAwait *pAwait; - int status; - - REQUEST_AT_LEAST_SIZE(xSyncAwaitReq); - - len = client->req_len << 2; - len -= sz_xSyncAwaitReq; - items = len / sz_xSyncWaitCondition; - - if (items * sz_xSyncWaitCondition != len) - { - return BadLength; - } - if (items == 0) - { - client->errorValue = items; /* XXX protocol change */ - return BadValue; - } - - pProtocolWaitConds = (xSyncWaitCondition *) & stuff[1]; - - /* all the memory for the entire await list is allocated - * here in one chunk - */ - pAwaitUnion = xalloc((items+1) * sizeof(SyncAwaitUnion)); - if (!pAwaitUnion) - return BadAlloc; - - /* first item is the header, remainder are real wait conditions */ - - pAwaitUnion->header.delete_id = FakeClientID(client->index); - if (!AddResource(pAwaitUnion->header.delete_id, RTAwait, pAwaitUnion)) - { - xfree(pAwaitUnion); - return BadAlloc; - } - - /* don't need to do any more memory allocation for this request! */ - - pAwaitUnion->header.client = client; - pAwaitUnion->header.num_waitconditions = 0; - - pAwait = &(pAwaitUnion+1)->await; /* skip over header */ - for (i = 0; i < items; i++, pProtocolWaitConds++, pAwait++) - { - if (pProtocolWaitConds->counter == None) /* XXX protocol change */ - { - /* this should take care of removing any triggers created by - * this request that have already been registered on counters - */ - FreeResource(pAwaitUnion->header.delete_id, RT_NONE); - client->errorValue = pProtocolWaitConds->counter; - return SyncErrorBase + XSyncBadCounter; - } - - /* sanity checks are in SyncInitTrigger */ - pAwait->trigger.pCounter = NULL; - pAwait->trigger.value_type = pProtocolWaitConds->value_type; - XSyncIntsToValue(&pAwait->trigger.wait_value, - pProtocolWaitConds->wait_value_lo, - pProtocolWaitConds->wait_value_hi); - pAwait->trigger.test_type = pProtocolWaitConds->test_type; - - status = SyncInitTrigger(client, &pAwait->trigger, - pProtocolWaitConds->counter, XSyncCAAllTrigger); - if (status != Success) - { - /* this should take care of removing any triggers created by - * this request that have already been registered on counters - */ - FreeResource(pAwaitUnion->header.delete_id, RT_NONE); - return status; - } - /* this is not a mistake -- same function works for both cases */ - pAwait->trigger.TriggerFired = SyncAwaitTriggerFired; - pAwait->trigger.CounterDestroyed = SyncAwaitTriggerFired; - XSyncIntsToValue(&pAwait->event_threshold, - pProtocolWaitConds->event_threshold_lo, - pProtocolWaitConds->event_threshold_hi); - pAwait->pHeader = &pAwaitUnion->header; - pAwaitUnion->header.num_waitconditions++; - } - - IgnoreClient(client); - - /* see if any of the triggers are already true */ - - pAwait = &(pAwaitUnion+1)->await; /* skip over header */ - for (i = 0; i < items; i++, pAwait++) - { - /* don't have to worry about NULL counters because the request - * errors before we get here out if they occur - */ - if ((*pAwait->trigger.CheckTrigger)(&pAwait->trigger, - pAwait->trigger.pCounter->value)) - { - (*pAwait->trigger.TriggerFired)(&pAwait->trigger); - break; /* once is enough */ - } - } - return Success; -} - - -/* - * ** Query a counter - */ -static int -ProcSyncQueryCounter(ClientPtr client) -{ - REQUEST(xSyncQueryCounterReq); - xSyncQueryCounterReply rep; - SyncCounter *pCounter; - int rc; - - REQUEST_SIZE_MATCH(xSyncQueryCounterReq); - - rc = dixLookupResourceByType((pointer *)&pCounter, stuff->counter, - RTCounter, client, DixReadAccess); - if (rc != Success) - return (rc == BadValue) ? SyncErrorBase + XSyncBadCounter : rc; - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - - /* if system counter, ask it what the current value is */ - - if (IsSystemCounter(pCounter)) - { - (*pCounter->pSysCounterInfo->QueryValue) ((pointer) pCounter, - &pCounter->value); - } - - rep.value_hi = XSyncValueHigh32(pCounter->value); - rep.value_lo = XSyncValueLow32(pCounter->value); - if (client->swapped) - { - char n; - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swapl(&rep.value_hi, n); - swapl(&rep.value_lo, n); - } - WriteToClient(client, sizeof(xSyncQueryCounterReply), (char *) &rep); - return client->noClientException; -} - - -/* - * ** Create Alarm - */ -static int -ProcSyncCreateAlarm(ClientPtr client) -{ - REQUEST(xSyncCreateAlarmReq); - SyncAlarm *pAlarm; - int status; - unsigned long len, vmask; - SyncTrigger *pTrigger; - - REQUEST_AT_LEAST_SIZE(xSyncCreateAlarmReq); - - LEGAL_NEW_RESOURCE(stuff->id, client); - - vmask = stuff->valueMask; - len = client->req_len - bytes_to_int32(sizeof(xSyncCreateAlarmReq)); - /* the "extra" call to Ones accounts for the presence of 64 bit values */ - if (len != (Ones(vmask) + Ones(vmask & (XSyncCAValue|XSyncCADelta)))) - return BadLength; - - if (!(pAlarm = xalloc(sizeof(SyncAlarm)))) - { - return BadAlloc; - } - - /* set up defaults */ - - pTrigger = &pAlarm->trigger; - pTrigger->pCounter = NULL; - pTrigger->value_type = XSyncAbsolute; - XSyncIntToValue(&pTrigger->wait_value, 0L); - pTrigger->test_type = XSyncPositiveComparison; - pTrigger->TriggerFired = SyncAlarmTriggerFired; - pTrigger->CounterDestroyed = SyncAlarmCounterDestroyed; - status = SyncInitTrigger(client, pTrigger, None, XSyncCAAllTrigger); - if (status != Success) - { - xfree(pAlarm); - return status; - } - - pAlarm->client = client; - pAlarm->alarm_id = stuff->id; - XSyncIntToValue(&pAlarm->delta, 1L); - pAlarm->events = TRUE; - pAlarm->state = XSyncAlarmInactive; - pAlarm->pEventClients = NULL; - status = SyncChangeAlarmAttributes(client, pAlarm, vmask, - (CARD32 *)&stuff[1]); - if (status != Success) - { - xfree(pAlarm); - return status; - } - - if (!AddResource(stuff->id, RTAlarm, pAlarm)) - { - xfree(pAlarm); - return BadAlloc; - } - - /* see if alarm already triggered. NULL counter will not trigger - * in CreateAlarm and sets alarm state to Inactive. - */ - - if (!pTrigger->pCounter) - { - pAlarm->state = XSyncAlarmInactive; /* XXX protocol change */ - } - else if ((*pTrigger->CheckTrigger)(pTrigger, pTrigger->pCounter->value)) - { - (*pTrigger->TriggerFired)(pTrigger); - } - - return Success; -} - -/* - * ** Change Alarm - */ -static int -ProcSyncChangeAlarm(ClientPtr client) -{ - REQUEST(xSyncChangeAlarmReq); - SyncAlarm *pAlarm; - long vmask; - int len, status; - - REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq); - - status = dixLookupResourceByType((pointer *)&pAlarm, stuff->alarm, RTAlarm, - client, DixWriteAccess); - if (status != Success) - return (status == BadValue) ? SyncErrorBase + XSyncBadAlarm : status; - - vmask = stuff->valueMask; - len = client->req_len - bytes_to_int32(sizeof(xSyncChangeAlarmReq)); - /* the "extra" call to Ones accounts for the presence of 64 bit values */ - if (len != (Ones(vmask) + Ones(vmask & (XSyncCAValue|XSyncCADelta)))) - return BadLength; - - if ((status = SyncChangeAlarmAttributes(client, pAlarm, vmask, - (CARD32 *)&stuff[1])) != Success) - return status; - - /* see if alarm already triggered. NULL counter WILL trigger - * in ChangeAlarm. - */ - - if (!pAlarm->trigger.pCounter || - (*pAlarm->trigger.CheckTrigger)(&pAlarm->trigger, - pAlarm->trigger.pCounter->value)) - { - (*pAlarm->trigger.TriggerFired)(&pAlarm->trigger); - } - return Success; -} - -static int -ProcSyncQueryAlarm(ClientPtr client) -{ - REQUEST(xSyncQueryAlarmReq); - SyncAlarm *pAlarm; - xSyncQueryAlarmReply rep; - SyncTrigger *pTrigger; - int rc; - - REQUEST_SIZE_MATCH(xSyncQueryAlarmReq); - - rc = dixLookupResourceByType((pointer *)&pAlarm, stuff->alarm, RTAlarm, - client, DixReadAccess); - if (rc != Success) - return (rc == BadValue) ? SyncErrorBase + XSyncBadAlarm : rc; - - rep.type = X_Reply; - rep.length = bytes_to_int32(sizeof(xSyncQueryAlarmReply) - sizeof(xGenericReply)); - rep.sequenceNumber = client->sequence; - - pTrigger = &pAlarm->trigger; - rep.counter = (pTrigger->pCounter) ? pTrigger->pCounter->id : None; - -#if 0 /* XXX unclear what to do, depends on whether relative value-types - * are "consumed" immediately and are considered absolute from then - * on. - */ - rep.value_type = pTrigger->value_type; - rep.wait_value_hi = XSyncValueHigh32(pTrigger->wait_value); - rep.wait_value_lo = XSyncValueLow32(pTrigger->wait_value); -#else - rep.value_type = XSyncAbsolute; - rep.wait_value_hi = XSyncValueHigh32(pTrigger->test_value); - rep.wait_value_lo = XSyncValueLow32(pTrigger->test_value); -#endif - - rep.test_type = pTrigger->test_type; - rep.delta_hi = XSyncValueHigh32(pAlarm->delta); - rep.delta_lo = XSyncValueLow32(pAlarm->delta); - rep.events = pAlarm->events; - rep.state = pAlarm->state; - - if (client->swapped) - { - char n; - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swapl(&rep.counter, n); - swapl(&rep.wait_value_hi, n); - swapl(&rep.wait_value_lo, n); - swapl(&rep.test_type, n); - swapl(&rep.delta_hi, n); - swapl(&rep.delta_lo, n); - } - - WriteToClient(client, sizeof(xSyncQueryAlarmReply), (char *) &rep); - return client->noClientException; -} - -static int -ProcSyncDestroyAlarm(ClientPtr client) -{ - SyncAlarm *pAlarm; - int rc; - REQUEST(xSyncDestroyAlarmReq); - - REQUEST_SIZE_MATCH(xSyncDestroyAlarmReq); - - rc = dixLookupResourceByType((pointer *)&pAlarm, stuff->alarm, RTAlarm, - client, DixDestroyAccess); - if (rc != Success) - return (rc == BadValue) ? SyncErrorBase + XSyncBadAlarm : rc; - - FreeResource(stuff->alarm, RT_NONE); - return client->noClientException; -} - -/* - * ** Given an extension request, call the appropriate request procedure - */ -static int -ProcSyncDispatch(ClientPtr client) -{ - REQUEST(xReq); - - switch (stuff->data) - { - case X_SyncInitialize: - return ProcSyncInitialize(client); - case X_SyncListSystemCounters: - return ProcSyncListSystemCounters(client); - case X_SyncCreateCounter: - return ProcSyncCreateCounter(client); - case X_SyncSetCounter: - return ProcSyncSetCounter(client); - case X_SyncChangeCounter: - return ProcSyncChangeCounter(client); - case X_SyncQueryCounter: - return ProcSyncQueryCounter(client); - case X_SyncDestroyCounter: - return ProcSyncDestroyCounter(client); - case X_SyncAwait: - return ProcSyncAwait(client); - case X_SyncCreateAlarm: - return ProcSyncCreateAlarm(client); - case X_SyncChangeAlarm: - return ProcSyncChangeAlarm(client); - case X_SyncQueryAlarm: - return ProcSyncQueryAlarm(client); - case X_SyncDestroyAlarm: - return ProcSyncDestroyAlarm(client); - case X_SyncSetPriority: - return ProcSyncSetPriority(client); - case X_SyncGetPriority: - return ProcSyncGetPriority(client); - default: - return BadRequest; - } -} - -/* - * Boring Swapping stuff ... - */ - -static int -SProcSyncInitialize(ClientPtr client) -{ - REQUEST(xSyncInitializeReq); - char n; - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH (xSyncInitializeReq); - - return ProcSyncInitialize(client); -} - -static int -SProcSyncListSystemCounters(ClientPtr client) -{ - REQUEST(xSyncListSystemCountersReq); - char n; - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH (xSyncListSystemCountersReq); - - return ProcSyncListSystemCounters(client); -} - -static int -SProcSyncCreateCounter(ClientPtr client) -{ - REQUEST(xSyncCreateCounterReq); - char n; - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH (xSyncCreateCounterReq); - swapl(&stuff->cid, n); - swapl(&stuff->initial_value_lo, n); - swapl(&stuff->initial_value_hi, n); - - return ProcSyncCreateCounter(client); -} - -static int -SProcSyncSetCounter(ClientPtr client) -{ - REQUEST(xSyncSetCounterReq); - char n; - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH (xSyncSetCounterReq); - swapl(&stuff->cid, n); - swapl(&stuff->value_lo, n); - swapl(&stuff->value_hi, n); - - return ProcSyncSetCounter(client); -} - -static int -SProcSyncChangeCounter(ClientPtr client) -{ - REQUEST(xSyncChangeCounterReq); - char n; - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH (xSyncChangeCounterReq); - swapl(&stuff->cid, n); - swapl(&stuff->value_lo, n); - swapl(&stuff->value_hi, n); - - return ProcSyncChangeCounter(client); -} - -static int -SProcSyncQueryCounter(ClientPtr client) -{ - REQUEST(xSyncQueryCounterReq); - char n; - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH (xSyncQueryCounterReq); - swapl(&stuff->counter, n); - - return ProcSyncQueryCounter(client); -} - -static int -SProcSyncDestroyCounter(ClientPtr client) -{ - REQUEST(xSyncDestroyCounterReq); - char n; - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH (xSyncDestroyCounterReq); - swapl(&stuff->counter, n); - - return ProcSyncDestroyCounter(client); -} - -static int -SProcSyncAwait(ClientPtr client) -{ - REQUEST(xSyncAwaitReq); - char n; - - swaps(&stuff->length, n); - REQUEST_AT_LEAST_SIZE(xSyncAwaitReq); - SwapRestL(stuff); - - return ProcSyncAwait(client); -} - -static int -SProcSyncCreateAlarm(ClientPtr client) -{ - REQUEST(xSyncCreateAlarmReq); - char n; - - swaps(&stuff->length, n); - REQUEST_AT_LEAST_SIZE(xSyncCreateAlarmReq); - swapl(&stuff->id, n); - swapl(&stuff->valueMask, n); - SwapRestL(stuff); - - return ProcSyncCreateAlarm(client); -} - -static int -SProcSyncChangeAlarm(ClientPtr client) -{ - REQUEST(xSyncChangeAlarmReq); - char n; - - swaps(&stuff->length, n); - REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq); - swapl(&stuff->alarm, n); - swapl(&stuff->valueMask, n); - SwapRestL(stuff); - return ProcSyncChangeAlarm(client); -} - -static int -SProcSyncQueryAlarm(ClientPtr client) -{ - REQUEST(xSyncQueryAlarmReq); - char n; - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH (xSyncQueryAlarmReq); - swapl(&stuff->alarm, n); - - return ProcSyncQueryAlarm(client); -} - -static int -SProcSyncDestroyAlarm(ClientPtr client) -{ - REQUEST(xSyncDestroyAlarmReq); - char n; - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH (xSyncDestroyAlarmReq); - swapl(&stuff->alarm, n); - - return ProcSyncDestroyAlarm(client); -} - -static int -SProcSyncSetPriority(ClientPtr client) -{ - REQUEST(xSyncSetPriorityReq); - char n; - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH (xSyncSetPriorityReq); - swapl(&stuff->id, n); - swapl(&stuff->priority, n); - - return ProcSyncSetPriority(client); -} - -static int -SProcSyncGetPriority(ClientPtr client) -{ - REQUEST(xSyncGetPriorityReq); - char n; - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH (xSyncGetPriorityReq); - swapl(&stuff->id, n); - - return ProcSyncGetPriority(client); -} - - -static int -SProcSyncDispatch(ClientPtr client) -{ - REQUEST(xReq); - - switch (stuff->data) - { - case X_SyncInitialize: - return SProcSyncInitialize(client); - case X_SyncListSystemCounters: - return SProcSyncListSystemCounters(client); - case X_SyncCreateCounter: - return SProcSyncCreateCounter(client); - case X_SyncSetCounter: - return SProcSyncSetCounter(client); - case X_SyncChangeCounter: - return SProcSyncChangeCounter(client); - case X_SyncQueryCounter: - return SProcSyncQueryCounter(client); - case X_SyncDestroyCounter: - return SProcSyncDestroyCounter(client); - case X_SyncAwait: - return SProcSyncAwait(client); - case X_SyncCreateAlarm: - return SProcSyncCreateAlarm(client); - case X_SyncChangeAlarm: - return SProcSyncChangeAlarm(client); - case X_SyncQueryAlarm: - return SProcSyncQueryAlarm(client); - case X_SyncDestroyAlarm: - return SProcSyncDestroyAlarm(client); - case X_SyncSetPriority: - return SProcSyncSetPriority(client); - case X_SyncGetPriority: - return SProcSyncGetPriority(client); - default: - return BadRequest; - } -} - -/* - * Event Swapping - */ - -static void -SCounterNotifyEvent(xSyncCounterNotifyEvent *from, xSyncCounterNotifyEvent *to) -{ - to->type = from->type; - to->kind = from->kind; - cpswaps(from->sequenceNumber, to->sequenceNumber); - cpswapl(from->counter, to->counter); - cpswapl(from->wait_value_lo, to->wait_value_lo); - cpswapl(from->wait_value_hi, to->wait_value_hi); - cpswapl(from->counter_value_lo, to->counter_value_lo); - cpswapl(from->counter_value_hi, to->counter_value_hi); - cpswapl(from->time, to->time); - cpswaps(from->count, to->count); - to->destroyed = from->destroyed; -} - - -static void -SAlarmNotifyEvent(xSyncAlarmNotifyEvent *from, xSyncAlarmNotifyEvent *to) -{ - to->type = from->type; - to->kind = from->kind; - cpswaps(from->sequenceNumber, to->sequenceNumber); - cpswapl(from->alarm, to->alarm); - cpswapl(from->counter_value_lo, to->counter_value_lo); - cpswapl(from->counter_value_hi, to->counter_value_hi); - cpswapl(from->alarm_value_lo, to->alarm_value_lo); - cpswapl(from->alarm_value_hi, to->alarm_value_hi); - cpswapl(from->time, to->time); - to->state = from->state; -} - -/* - * ** Close everything down. ** This is fairly simple for now. - */ -/* ARGSUSED */ -static void -SyncResetProc(ExtensionEntry *extEntry) -{ - xfree(SysCounterList); - SysCounterList = NULL; - RTCounter = 0; -} - - -/* - * ** Initialise the extension. - */ -void -SyncExtensionInit(void) -{ - ExtensionEntry *extEntry; - - if (RTCounter == 0) - { - RTCounter = CreateNewResourceType(FreeCounter, "SyncCounter"); - } - RTAlarm = CreateNewResourceType(FreeAlarm, "SyncAlarm"); - RTAwait = CreateNewResourceType(FreeAwait, "SyncAwait"); - if (RTAwait) - RTAwait |= RC_NEVERRETAIN; - RTAlarmClient = CreateNewResourceType(FreeAlarmClient, "SyncAlarmClient"); - if (RTAlarmClient) - RTAlarmClient |= RC_NEVERRETAIN; - - if (RTCounter == 0 || RTAwait == 0 || RTAlarm == 0 || - RTAlarmClient == 0 || - (extEntry = AddExtension(SYNC_NAME, - XSyncNumberEvents, XSyncNumberErrors, - ProcSyncDispatch, SProcSyncDispatch, - SyncResetProc, - StandardMinorOpcode)) == NULL) - { - ErrorF("Sync Extension %d.%d failed to Initialise\n", - SYNC_MAJOR_VERSION, SYNC_MINOR_VERSION); - return; - } - - SyncEventBase = extEntry->eventBase; - SyncErrorBase = extEntry->errorBase; - EventSwapVector[SyncEventBase + XSyncCounterNotify] = (EventSwapPtr) SCounterNotifyEvent; - EventSwapVector[SyncEventBase + XSyncAlarmNotify] = (EventSwapPtr) SAlarmNotifyEvent; - - /* - * Although SERVERTIME is implemented by the OS layer, we initialise it - * here because doing it in OsInit() is too early. The resource database - * is not initialised when OsInit() is called. This is just about OK - * because there is always a servertime counter. - */ - SyncInitServerTime(); - SyncInitIdleTime(); - -#ifdef DEBUG - fprintf(stderr, "Sync Extension %d.%d\n", - SYNC_MAJOR_VERSION, SYNC_MINOR_VERSION); -#endif -} - - -/* - * ***** SERVERTIME implementation - should go in its own file in OS directory? - */ - - - -static pointer ServertimeCounter; -static XSyncValue Now; -static XSyncValue *pnext_time; - -#define GetTime()\ -{\ - unsigned long millis = GetTimeInMillis();\ - unsigned long maxis = XSyncValueHigh32(Now);\ - if (millis < XSyncValueLow32(Now)) maxis++;\ - XSyncIntsToValue(&Now, millis, maxis);\ -} - -/* -*** Server Block Handler -*** code inspired by multibuffer extension (now deprecated) - */ -/*ARGSUSED*/ -static void -ServertimeBlockHandler(void *env, struct timeval **wt, void *LastSelectMask) -{ - XSyncValue delay; - unsigned long timeout; - - if (pnext_time) - { - GetTime(); - - if (XSyncValueGreaterOrEqual(Now, *pnext_time)) - { - timeout = 0; - } - else - { - Bool overflow; - XSyncValueSubtract(&delay, *pnext_time, Now, &overflow); - (void)overflow; - timeout = XSyncValueLow32(delay); - } - AdjustWaitForDelay(wt, timeout); /* os/utils.c */ - } -} - -/* -*** Wakeup Handler - */ -/*ARGSUSED*/ -static void -ServertimeWakeupHandler(void *env, int rc, void *LastSelectMask) -{ - if (pnext_time) - { - GetTime(); - - if (XSyncValueGreaterOrEqual(Now, *pnext_time)) - { - SyncChangeCounter(ServertimeCounter, Now); - } - } -} - -static void -ServertimeQueryValue(void *pCounter, CARD64 *pValue_return) -{ - GetTime(); - *pValue_return = Now; -} - -static void -ServertimeBracketValues(void *pCounter, CARD64 *pbracket_less, - CARD64 *pbracket_greater) -{ - if (!pnext_time && pbracket_greater) - { - RegisterBlockAndWakeupHandlers(ServertimeBlockHandler, - ServertimeWakeupHandler, - NULL); - } - else if (pnext_time && !pbracket_greater) - { - RemoveBlockAndWakeupHandlers(ServertimeBlockHandler, - ServertimeWakeupHandler, - NULL); - } - pnext_time = pbracket_greater; -} - -static void -SyncInitServerTime(void) -{ - CARD64 resolution; - - XSyncIntsToValue(&Now, GetTimeInMillis(), 0); - XSyncIntToValue(&resolution, 4); - ServertimeCounter = SyncCreateSystemCounter("SERVERTIME", Now, resolution, - XSyncCounterNeverDecreases, - ServertimeQueryValue, ServertimeBracketValues); - pnext_time = NULL; -} - - - -/* - * IDLETIME implementation - */ - -static SyncCounter *IdleTimeCounter; -static XSyncValue *pIdleTimeValueLess; -static XSyncValue *pIdleTimeValueGreater; - -static void -IdleTimeQueryValue (pointer pCounter, CARD64 *pValue_return) -{ - CARD32 idle = GetTimeInMillis() - lastDeviceEventTime.milliseconds; - XSyncIntsToValue (pValue_return, idle, 0); -} - -static void -IdleTimeBlockHandler(pointer env, struct timeval **wt, pointer LastSelectMask) -{ - XSyncValue idle, old_idle; - SyncTriggerList *list = IdleTimeCounter->pTriglist; - SyncTrigger *trig; - - if (!pIdleTimeValueLess && !pIdleTimeValueGreater) - return; - - old_idle = IdleTimeCounter->value; - IdleTimeQueryValue (NULL, &idle); - IdleTimeCounter->value = idle; /* push, so CheckTrigger works */ - - if (pIdleTimeValueLess && - XSyncValueLessOrEqual (idle, *pIdleTimeValueLess)) - { - /* - * We've been idle for less than the threshold value, and someone - * wants to know about that, but now we need to know whether they - * want level or edge trigger. Check the trigger list against the - * current idle time, and if any succeed, bomb out of select() - * immediately so we can reschedule. - */ - - for (list = IdleTimeCounter->pTriglist; list; list = list->next) { - trig = list->pTrigger; - if (trig->CheckTrigger(trig, old_idle)) { - AdjustWaitForDelay(wt, 0); - break; - } - } - } - else if (pIdleTimeValueGreater) - { - /* - * There's a threshold in the positive direction. If we've been - * idle less than it, schedule a wakeup for sometime in the future. - * If we've been idle more than it, and someone wants to know about - * that level-triggered, schedule an immediate wakeup. - */ - unsigned long timeout = -1; - - if (XSyncValueLessThan (idle, *pIdleTimeValueGreater)) { - XSyncValue value; - Bool overflow; - - XSyncValueSubtract (&value, *pIdleTimeValueGreater, - idle, &overflow); - timeout = min(timeout, XSyncValueLow32 (value)); - } else { - for (list = IdleTimeCounter->pTriglist; list; list = list->next) { - trig = list->pTrigger; - if (trig->CheckTrigger(trig, old_idle)) { - timeout = min(timeout, 0); - break; - } - } - } - - AdjustWaitForDelay (wt, timeout); - } - - IdleTimeCounter->value = old_idle; /* pop */ -} - -static void -IdleTimeWakeupHandler (pointer env, int rc, pointer LastSelectMask) -{ - XSyncValue idle; - - if (!pIdleTimeValueLess && !pIdleTimeValueGreater) - return; - - IdleTimeQueryValue (NULL, &idle); - - if ((pIdleTimeValueGreater && - XSyncValueGreaterOrEqual (idle, *pIdleTimeValueGreater)) || - (pIdleTimeValueLess && - XSyncValueLessOrEqual (idle, *pIdleTimeValueLess))) - { - SyncChangeCounter (IdleTimeCounter, idle); - } -} - -static void -IdleTimeBracketValues (pointer pCounter, CARD64 *pbracket_less, - CARD64 *pbracket_greater) -{ - Bool registered = (pIdleTimeValueLess || pIdleTimeValueGreater); - - if (registered && !pbracket_less && !pbracket_greater) - { - RemoveBlockAndWakeupHandlers(IdleTimeBlockHandler, - IdleTimeWakeupHandler, - NULL); - } - else if (!registered && (pbracket_less || pbracket_greater)) - { - RegisterBlockAndWakeupHandlers(IdleTimeBlockHandler, - IdleTimeWakeupHandler, - NULL); - } - - pIdleTimeValueGreater = pbracket_greater; - pIdleTimeValueLess = pbracket_less; -} - -static void -SyncInitIdleTime (void) -{ - CARD64 resolution; - XSyncValue idle; - - IdleTimeQueryValue (NULL, &idle); - XSyncIntToValue (&resolution, 4); - - IdleTimeCounter = SyncCreateSystemCounter ("IDLETIME", idle, resolution, - XSyncCounterUnrestricted, - IdleTimeQueryValue, - IdleTimeBracketValues); - - pIdleTimeValueLess = pIdleTimeValueGreater = NULL; -} +/* + +Copyright 1991, 1993, 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 1991, 1993 by Digital Equipment Corporation, Maynard, Massachusetts, +and Olivetti Research Limited, Cambridge, England. + + 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 names of Digital or Olivetti +not be used in advertising or publicity pertaining to distribution of the +software without specific, written prior permission. Digital and Olivetti +make no representations about the suitability of this software +for any purpose. It is provided "as is" without express or implied warranty. + +DIGITAL AND OLIVETTI DISCLAIM ALL WARRANTIES WITH REGARD TO THIS +SOFTWARE, INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND +FITNESS, IN NO EVENT SHALL THEY 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. + +*/ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include + +#include +#include +#include +#include "misc.h" +#include "os.h" +#include "extnsionst.h" +#include "dixstruct.h" +#include "resource.h" +#include "opaque.h" +#include +#include "syncsrv.h" + +#include +#if !defined(WIN32) +#include +#endif + +#include "modinit.h" + +/* + * Local Global Variables + */ +static int SyncEventBase; +static int SyncErrorBase; +static RESTYPE RTCounter = 0; +static RESTYPE RTAwait; +static RESTYPE RTAlarm; +static RESTYPE RTAlarmClient; +static int SyncNumSystemCounters = 0; +static SyncCounter **SysCounterList = NULL; + +#define IsSystemCounter(pCounter) \ + (pCounter && (pCounter->client == NULL)) + +/* these are all the alarm attributes that pertain to the alarm's trigger */ +#define XSyncCAAllTrigger \ + (XSyncCACounter | XSyncCAValueType | XSyncCAValue | XSyncCATestType) + +static void SyncComputeBracketValues(SyncCounter *); + +static void SyncInitServerTime(void); + +static void SyncInitIdleTime(void); + +static DISPATCH_PROC(ProcSyncAwait); +static DISPATCH_PROC(ProcSyncChangeAlarm); +static DISPATCH_PROC(ProcSyncChangeCounter); +static DISPATCH_PROC(ProcSyncCreateAlarm); +static DISPATCH_PROC(ProcSyncCreateCounter); +static DISPATCH_PROC(ProcSyncDestroyAlarm); +static DISPATCH_PROC(ProcSyncDestroyCounter); +static DISPATCH_PROC(ProcSyncDispatch); +static DISPATCH_PROC(ProcSyncGetPriority); +static DISPATCH_PROC(ProcSyncInitialize); +static DISPATCH_PROC(ProcSyncListSystemCounters); +static DISPATCH_PROC(ProcSyncQueryAlarm); +static DISPATCH_PROC(ProcSyncQueryCounter); +static DISPATCH_PROC(ProcSyncSetCounter); +static DISPATCH_PROC(ProcSyncSetPriority); +static DISPATCH_PROC(SProcSyncAwait); +static DISPATCH_PROC(SProcSyncChangeAlarm); +static DISPATCH_PROC(SProcSyncChangeCounter); +static DISPATCH_PROC(SProcSyncCreateAlarm); +static DISPATCH_PROC(SProcSyncCreateCounter); +static DISPATCH_PROC(SProcSyncDestroyAlarm); +static DISPATCH_PROC(SProcSyncDestroyCounter); +static DISPATCH_PROC(SProcSyncDispatch); +static DISPATCH_PROC(SProcSyncGetPriority); +static DISPATCH_PROC(SProcSyncInitialize); +static DISPATCH_PROC(SProcSyncListSystemCounters); +static DISPATCH_PROC(SProcSyncQueryAlarm); +static DISPATCH_PROC(SProcSyncQueryCounter); +static DISPATCH_PROC(SProcSyncSetCounter); +static DISPATCH_PROC(SProcSyncSetPriority); + +/* Each counter maintains a simple linked list of triggers that are + * interested in the counter. The two functions below are used to + * delete and add triggers on this list. + */ +static void +SyncDeleteTriggerFromCounter(SyncTrigger *pTrigger) +{ + SyncTriggerList *pCur; + SyncTriggerList *pPrev; + + /* pCounter needs to be stored in pTrigger before calling here. */ + + if (!pTrigger->pCounter) + return; + + pPrev = NULL; + pCur = pTrigger->pCounter->pTriglist; + + while (pCur) + { + if (pCur->pTrigger == pTrigger) + { + if (pPrev) + pPrev->next = pCur->next; + else + pTrigger->pCounter->pTriglist = pCur->next; + + free(pCur); + break; + } + + pPrev = pCur; + pCur = pCur->next; + } + + if (IsSystemCounter(pTrigger->pCounter)) + SyncComputeBracketValues(pTrigger->pCounter); +} + + +static int +SyncAddTriggerToCounter(SyncTrigger *pTrigger) +{ + SyncTriggerList *pCur; + + if (!pTrigger->pCounter) + return Success; + + /* don't do anything if it's already there */ + for (pCur = pTrigger->pCounter->pTriglist; pCur; pCur = pCur->next) + { + if (pCur->pTrigger == pTrigger) + return Success; + } + + if (!(pCur = malloc(sizeof(SyncTriggerList)))) + return BadAlloc; + + pCur->pTrigger = pTrigger; + pCur->next = pTrigger->pCounter->pTriglist; + pTrigger->pCounter->pTriglist = pCur; + + if (IsSystemCounter(pTrigger->pCounter)) + SyncComputeBracketValues(pTrigger->pCounter); + + return Success; +} + + +/* Below are four possible functions that can be plugged into + * pTrigger->CheckTrigger, corresponding to the four possible + * test-types. These functions are called after the counter's + * value changes but are also passed the old counter value + * so they can inspect both the old and new values. + * (PositiveTransition and NegativeTransition need to see both + * pieces of information.) These functions return the truth value + * of the trigger. + * + * All of them include the condition pTrigger->pCounter == NULL. + * This is because the spec says that a trigger with a counter value + * of None is always TRUE. + */ + +static Bool +SyncCheckTriggerPositiveComparison(SyncTrigger *pTrigger, CARD64 oldval) +{ + return (pTrigger->pCounter == NULL || + XSyncValueGreaterOrEqual(pTrigger->pCounter->value, + pTrigger->test_value)); +} + +static Bool +SyncCheckTriggerNegativeComparison(SyncTrigger *pTrigger, CARD64 oldval) +{ + return (pTrigger->pCounter == NULL || + XSyncValueLessOrEqual(pTrigger->pCounter->value, + pTrigger->test_value)); +} + +static Bool +SyncCheckTriggerPositiveTransition(SyncTrigger *pTrigger, CARD64 oldval) +{ + return (pTrigger->pCounter == NULL || + (XSyncValueLessThan(oldval, pTrigger->test_value) && + XSyncValueGreaterOrEqual(pTrigger->pCounter->value, + pTrigger->test_value))); +} + +static Bool +SyncCheckTriggerNegativeTransition(SyncTrigger *pTrigger, CARD64 oldval) +{ + return (pTrigger->pCounter == NULL || + (XSyncValueGreaterThan(oldval, pTrigger->test_value) && + XSyncValueLessOrEqual(pTrigger->pCounter->value, + pTrigger->test_value))); +} + +static int +SyncInitTrigger(ClientPtr client, SyncTrigger *pTrigger, XSyncCounter counter, + Mask changes) +{ + SyncCounter *pCounter = pTrigger->pCounter; + int rc; + Bool newcounter = FALSE; + + if (changes & XSyncCACounter) + { + if (counter == None) + pCounter = NULL; + else if (Success != (rc = dixLookupResourceByType ((pointer *)&pCounter, + counter, RTCounter, client, DixReadAccess))) + { + client->errorValue = counter; + return (rc == BadValue) ? SyncErrorBase + XSyncBadCounter : rc; + } + if (pCounter != pTrigger->pCounter) + { /* new counter for trigger */ + SyncDeleteTriggerFromCounter(pTrigger); + pTrigger->pCounter = pCounter; + newcounter = TRUE; + } + } + + /* if system counter, ask it what the current value is */ + + if (IsSystemCounter(pCounter)) + { + (*pCounter->pSysCounterInfo->QueryValue) ((pointer) pCounter, + &pCounter->value); + } + + if (changes & XSyncCAValueType) + { + if (pTrigger->value_type != XSyncRelative && + pTrigger->value_type != XSyncAbsolute) + { + client->errorValue = pTrigger->value_type; + return BadValue; + } + } + + if (changes & XSyncCATestType) + { + if (pTrigger->test_type != XSyncPositiveTransition && + pTrigger->test_type != XSyncNegativeTransition && + pTrigger->test_type != XSyncPositiveComparison && + pTrigger->test_type != XSyncNegativeComparison) + { + client->errorValue = pTrigger->test_type; + return BadValue; + } + /* select appropriate CheckTrigger function */ + + switch (pTrigger->test_type) + { + case XSyncPositiveTransition: + pTrigger->CheckTrigger = SyncCheckTriggerPositiveTransition; + break; + case XSyncNegativeTransition: + pTrigger->CheckTrigger = SyncCheckTriggerNegativeTransition; + break; + case XSyncPositiveComparison: + pTrigger->CheckTrigger = SyncCheckTriggerPositiveComparison; + break; + case XSyncNegativeComparison: + pTrigger->CheckTrigger = SyncCheckTriggerNegativeComparison; + break; + } + } + + if (changes & (XSyncCAValueType | XSyncCAValue)) + { + if (pTrigger->value_type == XSyncAbsolute) + pTrigger->test_value = pTrigger->wait_value; + else /* relative */ + { + Bool overflow; + if (pCounter == NULL) + return BadMatch; + + XSyncValueAdd(&pTrigger->test_value, pCounter->value, + pTrigger->wait_value, &overflow); + if (overflow) + { + client->errorValue = XSyncValueHigh32(pTrigger->wait_value); + return BadValue; + } + } + } + + /* we wait until we're sure there are no errors before registering + * a new counter on a trigger + */ + if (newcounter) + { + if ((rc = SyncAddTriggerToCounter(pTrigger)) != Success) + return rc; + } + else if (IsSystemCounter(pCounter)) + { + SyncComputeBracketValues(pCounter); + } + + return Success; +} + +/* AlarmNotify events happen in response to actions taken on an Alarm or + * the counter used by the alarm. AlarmNotify may be sent to multiple + * clients. The alarm maintains a list of clients interested in events. + */ +static void +SyncSendAlarmNotifyEvents(SyncAlarm *pAlarm) +{ + SyncAlarmClientList *pcl; + xSyncAlarmNotifyEvent ane; + SyncTrigger *pTrigger = &pAlarm->trigger; + + UpdateCurrentTime(); + + ane.type = SyncEventBase + XSyncAlarmNotify; + ane.kind = XSyncAlarmNotify; + ane.sequenceNumber = pAlarm->client->sequence; + ane.alarm = pAlarm->alarm_id; + if (pTrigger->pCounter) + { + ane.counter_value_hi = XSyncValueHigh32(pTrigger->pCounter->value); + ane.counter_value_lo = XSyncValueLow32(pTrigger->pCounter->value); + } + else + { /* XXX what else can we do if there's no counter? */ + ane.counter_value_hi = ane.counter_value_lo = 0; + } + + ane.alarm_value_hi = XSyncValueHigh32(pTrigger->test_value); + ane.alarm_value_lo = XSyncValueLow32(pTrigger->test_value); + ane.time = currentTime.milliseconds; + ane.state = pAlarm->state; + + /* send to owner */ + if (pAlarm->events && !pAlarm->client->clientGone) + WriteEventsToClient(pAlarm->client, 1, (xEvent *) &ane); + + /* send to other interested clients */ + for (pcl = pAlarm->pEventClients; pcl; pcl = pcl->next) + { + if (!pAlarm->client->clientGone) + { + ane.sequenceNumber = pcl->client->sequence; + WriteEventsToClient(pcl->client, 1, (xEvent *) &ane); + } + } +} + + +/* CounterNotify events only occur in response to an Await. The events + * go only to the Awaiting client. + */ +static void +SyncSendCounterNotifyEvents(ClientPtr client, SyncAwait **ppAwait, + int num_events) +{ + xSyncCounterNotifyEvent *pEvents, *pev; + int i; + + if (client->clientGone) + return; + pev = pEvents = malloc(num_events * sizeof(xSyncCounterNotifyEvent)); + if (!pEvents) + return; + UpdateCurrentTime(); + for (i = 0; i < num_events; i++, ppAwait++, pev++) + { + SyncTrigger *pTrigger = &(*ppAwait)->trigger; + pev->type = SyncEventBase + XSyncCounterNotify; + pev->kind = XSyncCounterNotify; + pev->sequenceNumber = client->sequence; + pev->counter = pTrigger->pCounter->id; + pev->wait_value_lo = XSyncValueLow32(pTrigger->test_value); + pev->wait_value_hi = XSyncValueHigh32(pTrigger->test_value); + pev->counter_value_lo = XSyncValueLow32(pTrigger->pCounter->value); + pev->counter_value_hi = XSyncValueHigh32(pTrigger->pCounter->value); + pev->time = currentTime.milliseconds; + pev->count = num_events - i - 1; /* events remaining */ + pev->destroyed = pTrigger->pCounter->beingDestroyed; + } + /* swapping will be taken care of by this */ + WriteEventsToClient(client, num_events, (xEvent *)pEvents); + free(pEvents); +} + + +/* This function is called when an alarm's counter is destroyed. + * It is plugged into pTrigger->CounterDestroyed (for alarm triggers). + */ +static void +SyncAlarmCounterDestroyed(SyncTrigger *pTrigger) +{ + SyncAlarm *pAlarm = (SyncAlarm *)pTrigger; + + pAlarm->state = XSyncAlarmInactive; + SyncSendAlarmNotifyEvents(pAlarm); + pTrigger->pCounter = NULL; +} + + +/* This function is called when an alarm "goes off." + * It is plugged into pTrigger->TriggerFired (for alarm triggers). + */ +static void +SyncAlarmTriggerFired(SyncTrigger *pTrigger) +{ + SyncAlarm *pAlarm = (SyncAlarm *)pTrigger; + CARD64 new_test_value; + + /* no need to check alarm unless it's active */ + if (pAlarm->state != XSyncAlarmActive) + return; + + /* " if the counter value is None, or if the delta is 0 and + * the test-type is PositiveComparison or NegativeComparison, + * no change is made to value (test-value) and the alarm + * state is changed to Inactive before the event is generated." + */ + if (pAlarm->trigger.pCounter == NULL + || (XSyncValueIsZero(pAlarm->delta) + && (pAlarm->trigger.test_type == XSyncPositiveComparison + || pAlarm->trigger.test_type == XSyncNegativeComparison))) + pAlarm->state = XSyncAlarmInactive; + + new_test_value = pAlarm->trigger.test_value; + + if (pAlarm->state == XSyncAlarmActive) + { + Bool overflow; + CARD64 oldvalue; + SyncTrigger *paTrigger = &pAlarm->trigger; + + /* "The alarm is updated by repeatedly adding delta to the + * value of the trigger and re-initializing it until it + * becomes FALSE." + */ + oldvalue = paTrigger->test_value; + + /* XXX really should do something smarter here */ + + do + { + XSyncValueAdd(&paTrigger->test_value, paTrigger->test_value, + pAlarm->delta, &overflow); + } while (!overflow && + (*paTrigger->CheckTrigger)(paTrigger, + paTrigger->pCounter->value)); + + new_test_value = paTrigger->test_value; + paTrigger->test_value = oldvalue; + + /* "If this update would cause value to fall outside the range + * for an INT64...no change is made to value (test-value) and + * the alarm state is changed to Inactive before the event is + * generated." + */ + if (overflow) + { + new_test_value = oldvalue; + pAlarm->state = XSyncAlarmInactive; + } + } + /* The AlarmNotify event has to have the "new state of the alarm" + * which we can't be sure of until this point. However, it has + * to have the "old" trigger test value. That's the reason for + * all the newvalue/oldvalue shuffling above. After we send the + * events, give the trigger its new test value. + */ + SyncSendAlarmNotifyEvents(pAlarm); + pTrigger->test_value = new_test_value; +} + + +/* This function is called when an Await unblocks, either as a result + * of the trigger firing OR the counter being destroyed. + * It goes into pTrigger->TriggerFired AND pTrigger->CounterDestroyed + * (for Await triggers). + */ +static void +SyncAwaitTriggerFired(SyncTrigger *pTrigger) +{ + SyncAwait *pAwait = (SyncAwait *)pTrigger; + int numwaits; + SyncAwaitUnion *pAwaitUnion; + SyncAwait **ppAwait; + int num_events = 0; + + pAwaitUnion = (SyncAwaitUnion *)pAwait->pHeader; + numwaits = pAwaitUnion->header.num_waitconditions; + ppAwait = malloc(numwaits * sizeof(SyncAwait *)); + if (!ppAwait) + goto bail; + + pAwait = &(pAwaitUnion+1)->await; + + /* "When a client is unblocked, all the CounterNotify events for + * the Await request are generated contiguously. If count is 0 + * there are no more events to follow for this request. If + * count is n, there are at least n more events to follow." + * + * Thus, it is best to find all the counters for which events + * need to be sent first, so that an accurate count field can + * be stored in the events. + */ + for ( ; numwaits; numwaits--, pAwait++) + { + CARD64 diff; + Bool overflow, diffgreater, diffequal; + + /* "A CounterNotify event with the destroyed flag set to TRUE is + * always generated if the counter for one of the triggers is + * destroyed." + */ + if (pAwait->trigger.pCounter->beingDestroyed) + { + ppAwait[num_events++] = pAwait; + continue; + } + + /* "The difference between the counter and the test value is + * calculated by subtracting the test value from the value of + * the counter." + */ + XSyncValueSubtract(&diff, pAwait->trigger.pCounter->value, + pAwait->trigger.test_value, &overflow); + + /* "If the difference lies outside the range for an INT64, an + * event is not generated." + */ + if (overflow) + continue; + diffgreater = XSyncValueGreaterThan(diff, pAwait->event_threshold); + diffequal = XSyncValueEqual(diff, pAwait->event_threshold); + + /* "If the test-type is PositiveTransition or + * PositiveComparison, a CounterNotify event is generated if + * the difference is at least event-threshold. If the test-type + * is NegativeTransition or NegativeComparison, a CounterNotify + * event is generated if the difference is at most + * event-threshold." + */ + + if ( ((pAwait->trigger.test_type == XSyncPositiveComparison || + pAwait->trigger.test_type == XSyncPositiveTransition) + && (diffgreater || diffequal)) + || + ((pAwait->trigger.test_type == XSyncNegativeComparison || + pAwait->trigger.test_type == XSyncNegativeTransition) + && (!diffgreater) /* less or equal */ + ) + ) + { + ppAwait[num_events++] = pAwait; + } + } + if (num_events) + SyncSendCounterNotifyEvents(pAwaitUnion->header.client, ppAwait, + num_events); + free(ppAwait); + +bail: + /* unblock the client */ + AttendClient(pAwaitUnion->header.client); + /* delete the await */ + FreeResource(pAwaitUnion->header.delete_id, RT_NONE); +} + + +/* This function should always be used to change a counter's value so that + * any triggers depending on the counter will be checked. + */ +void +SyncChangeCounter(SyncCounter *pCounter, CARD64 newval) +{ + SyncTriggerList *ptl, *pnext; + CARD64 oldval; + + oldval = pCounter->value; + pCounter->value = newval; + + /* run through triggers to see if any become true */ + for (ptl = pCounter->pTriglist; ptl; ptl = pnext) + { + pnext = ptl->next; + if ((*ptl->pTrigger->CheckTrigger)(ptl->pTrigger, oldval)) + (*ptl->pTrigger->TriggerFired)(ptl->pTrigger); + } + + if (IsSystemCounter(pCounter)) + { + SyncComputeBracketValues(pCounter); + } +} + + +/* loosely based on dix/events.c/EventSelectForWindow */ +static Bool +SyncEventSelectForAlarm(SyncAlarm *pAlarm, ClientPtr client, Bool wantevents) +{ + SyncAlarmClientList *pClients; + + if (client == pAlarm->client) /* alarm owner */ + { + pAlarm->events = wantevents; + return Success; + } + + /* see if the client is already on the list (has events selected) */ + + for (pClients = pAlarm->pEventClients; pClients; + pClients = pClients->next) + { + if (pClients->client == client) + { + /* client's presence on the list indicates desire for + * events. If the client doesn't want events, remove it + * from the list. If the client does want events, do + * nothing, since it's already got them. + */ + if (!wantevents) + { + FreeResource(pClients->delete_id, RT_NONE); + } + return Success; + } + } + + /* if we get here, this client does not currently have + * events selected on the alarm + */ + + if (!wantevents) + /* client doesn't want events, and we just discovered that it + * doesn't have them, so there's nothing to do. + */ + return Success; + + /* add new client to pAlarm->pEventClients */ + + pClients = malloc(sizeof(SyncAlarmClientList)); + if (!pClients) + return BadAlloc; + + /* register it as a resource so it will be cleaned up + * if the client dies + */ + + pClients->delete_id = FakeClientID(client->index); + if (!AddResource(pClients->delete_id, RTAlarmClient, pAlarm)) + { + free(pClients); + return BadAlloc; + } + + /* link it into list after we know all the allocations succeed */ + + pClients->next = pAlarm->pEventClients; + pAlarm->pEventClients = pClients; + pClients->client = client; + return Success; +} + +/* + * ** SyncChangeAlarmAttributes ** This is used by CreateAlarm and ChangeAlarm + */ +static int +SyncChangeAlarmAttributes(ClientPtr client, SyncAlarm *pAlarm, Mask mask, + CARD32 *values) +{ + int status; + XSyncCounter counter; + Mask origmask = mask; + + counter = pAlarm->trigger.pCounter ? pAlarm->trigger.pCounter->id : None; + + while (mask) + { + int index2 = lowbit(mask); + mask &= ~index2; + switch (index2) + { + case XSyncCACounter: + mask &= ~XSyncCACounter; + /* sanity check in SyncInitTrigger */ + counter = *values++; + break; + + case XSyncCAValueType: + mask &= ~XSyncCAValueType; + /* sanity check in SyncInitTrigger */ + pAlarm->trigger.value_type = *values++; + break; + + case XSyncCAValue: + mask &= ~XSyncCAValue; + XSyncIntsToValue(&pAlarm->trigger.wait_value, values[1], values[0]); + values += 2; + break; + + case XSyncCATestType: + mask &= ~XSyncCATestType; + /* sanity check in SyncInitTrigger */ + pAlarm->trigger.test_type = *values++; + break; + + case XSyncCADelta: + mask &= ~XSyncCADelta; + XSyncIntsToValue(&pAlarm->delta, values[1], values[0]); + values += 2; + break; + + case XSyncCAEvents: + mask &= ~XSyncCAEvents; + if ((*values != xTrue) && (*values != xFalse)) + { + client->errorValue = *values; + return BadValue; + } + status = SyncEventSelectForAlarm(pAlarm, client, + (Bool)(*values++)); + if (status != Success) + return status; + break; + + default: + client->errorValue = mask; + return BadValue; + } + } + + /* "If the test-type is PositiveComparison or PositiveTransition + * and delta is less than zero, or if the test-type is + * NegativeComparison or NegativeTransition and delta is + * greater than zero, a Match error is generated." + */ + if (origmask & (XSyncCADelta|XSyncCATestType)) + { + CARD64 zero; + XSyncIntToValue(&zero, 0); + if ((((pAlarm->trigger.test_type == XSyncPositiveComparison) || + (pAlarm->trigger.test_type == XSyncPositiveTransition)) + && XSyncValueLessThan(pAlarm->delta, zero)) + || + (((pAlarm->trigger.test_type == XSyncNegativeComparison) || + (pAlarm->trigger.test_type == XSyncNegativeTransition)) + && XSyncValueGreaterThan(pAlarm->delta, zero)) + ) + { + return BadMatch; + } + } + + /* postpone this until now, when we're sure nothing else can go wrong */ + if ((status = SyncInitTrigger(client, &pAlarm->trigger, counter, + origmask & XSyncCAAllTrigger)) != Success) + return status; + + /* XXX spec does not really say to do this - needs clarification */ + pAlarm->state = XSyncAlarmActive; + return Success; +} + + +static SyncCounter * +SyncCreateCounter(ClientPtr client, XSyncCounter id, CARD64 initialvalue) +{ + SyncCounter *pCounter; + + if (!(pCounter = malloc(sizeof(SyncCounter)))) + return NULL; + + if (!AddResource(id, RTCounter, (pointer) pCounter)) + { + free(pCounter); + return NULL; + } + + pCounter->client = client; + pCounter->id = id; + pCounter->value = initialvalue; + pCounter->pTriglist = NULL; + pCounter->beingDestroyed = FALSE; + pCounter->pSysCounterInfo = NULL; + return pCounter; +} + +static int FreeCounter(void *, XID); + +/* + * ***** System Counter utilities + */ + +pointer +SyncCreateSystemCounter( + char *name, + CARD64 initial, + CARD64 resolution, + SyncCounterType counterType, + void (*QueryValue)(pointer /* pCounter */, + CARD64 * /* pValue_return */), + void (*BracketValues)(pointer /* pCounter */, + CARD64 * /* pbracket_less */, + CARD64 * /* pbracket_greater */) + ) +{ + SyncCounter *pCounter; + + SysCounterList = realloc(SysCounterList, + (SyncNumSystemCounters+1)*sizeof(SyncCounter *)); + if (!SysCounterList) + return NULL; + + /* this function may be called before SYNC has been initialized, so we + * have to make sure RTCounter is created. + */ + if (RTCounter == 0) + { + RTCounter = CreateNewResourceType(FreeCounter, "SyncCounter"); + if (RTCounter == 0) + { + return NULL; + } + } + + pCounter = SyncCreateCounter(NULL, FakeClientID(0), initial); + + if (pCounter) + { + SysCounterInfo *psci; + + psci = malloc(sizeof(SysCounterInfo)); + if (!psci) + { + FreeResource(pCounter->id, RT_NONE); + return pCounter; + } + pCounter->pSysCounterInfo = psci; + psci->name = name; + psci->resolution = resolution; + psci->counterType = counterType; + psci->QueryValue = QueryValue; + psci->BracketValues = BracketValues; + XSyncMaxValue(&psci->bracket_greater); + XSyncMinValue(&psci->bracket_less); + SysCounterList[SyncNumSystemCounters++] = pCounter; + } + return pCounter; +} + +void +SyncDestroySystemCounter(pointer pSysCounter) +{ + SyncCounter *pCounter = (SyncCounter *)pSysCounter; + FreeResource(pCounter->id, RT_NONE); +} + +static void +SyncComputeBracketValues(SyncCounter *pCounter) +{ + SyncTriggerList *pCur; + SyncTrigger *pTrigger; + SysCounterInfo *psci; + CARD64 *pnewgtval = NULL; + CARD64 *pnewltval = NULL; + SyncCounterType ct; + + if (!pCounter) + return; + + psci = pCounter->pSysCounterInfo; + ct = pCounter->pSysCounterInfo->counterType; + if (ct == XSyncCounterNeverChanges) + return; + + XSyncMaxValue(&psci->bracket_greater); + XSyncMinValue(&psci->bracket_less); + + for (pCur = pCounter->pTriglist; pCur; pCur = pCur->next) + { + pTrigger = pCur->pTrigger; + + if (pTrigger->test_type == XSyncPositiveComparison && + ct != XSyncCounterNeverIncreases) + { + if (XSyncValueLessThan(pCounter->value, pTrigger->test_value) && + XSyncValueLessThan(pTrigger->test_value, + psci->bracket_greater)) + { + psci->bracket_greater = pTrigger->test_value; + pnewgtval = &psci->bracket_greater; + } + } + else if (pTrigger->test_type == XSyncNegativeComparison && + ct != XSyncCounterNeverDecreases) + { + if (XSyncValueGreaterThan(pCounter->value, pTrigger->test_value) && + XSyncValueGreaterThan(pTrigger->test_value, + psci->bracket_less)) + { + psci->bracket_less = pTrigger->test_value; + pnewltval = &psci->bracket_less; + } + } + else if (pTrigger->test_type == XSyncNegativeTransition && + ct != XSyncCounterNeverIncreases) + { + if (XSyncValueGreaterThan(pCounter->value, pTrigger->test_value) && + XSyncValueGreaterThan(pTrigger->test_value, psci->bracket_less)) + { + psci->bracket_less = pTrigger->test_value; + pnewltval = &psci->bracket_less; + } + } + else if (pTrigger->test_type == XSyncPositiveTransition && + ct != XSyncCounterNeverDecreases) + { + if (XSyncValueLessThan(pCounter->value, pTrigger->test_value) && + XSyncValueLessThan(pTrigger->test_value, psci->bracket_greater)) + { + psci->bracket_greater = pTrigger->test_value; + pnewgtval = &psci->bracket_greater; + } + } + } /* end for each trigger */ + + if (pnewgtval || pnewltval) + { + (*psci->BracketValues)((pointer)pCounter, pnewltval, pnewgtval); + } +} + +/* + * ***** Resource delete functions + */ + +/* ARGSUSED */ +static int +FreeAlarm(void *addr, XID id) +{ + SyncAlarm *pAlarm = (SyncAlarm *) addr; + + pAlarm->state = XSyncAlarmDestroyed; + + SyncSendAlarmNotifyEvents(pAlarm); + + /* delete event selections */ + + while (pAlarm->pEventClients) + FreeResource(pAlarm->pEventClients->delete_id, RT_NONE); + + SyncDeleteTriggerFromCounter(&pAlarm->trigger); + + free(pAlarm); + return Success; +} + + +/* + * ** Cleanup after the destruction of a Counter + */ +/* ARGSUSED */ +static int +FreeCounter(void *env, XID id) +{ + SyncCounter *pCounter = (SyncCounter *) env; + SyncTriggerList *ptl, *pnext; + + pCounter->beingDestroyed = TRUE; + /* tell all the counter's triggers that the counter has been destroyed */ + for (ptl = pCounter->pTriglist; ptl; ptl = pnext) + { + (*ptl->pTrigger->CounterDestroyed)(ptl->pTrigger); + pnext = ptl->next; + free(ptl); /* destroy the trigger list as we go */ + } + if (IsSystemCounter(pCounter)) + { + int i, found = 0; + + free(pCounter->pSysCounterInfo); + + /* find the counter in the list of system counters and remove it */ + + if (SysCounterList) + { + for (i = 0; i < SyncNumSystemCounters; i++) + { + if (SysCounterList[i] == pCounter) + { + found = i; + break; + } + } + if (found < (SyncNumSystemCounters-1)) + { + for (i = found; i < SyncNumSystemCounters-1; i++) + { + SysCounterList[i] = SysCounterList[i+1]; + } + } + } + SyncNumSystemCounters--; + } + free(pCounter); + return Success; +} + +/* + * ** Cleanup after Await + */ +/* ARGSUSED */ +static int +FreeAwait(void *addr, XID id) +{ + SyncAwaitUnion *pAwaitUnion = (SyncAwaitUnion *) addr; + SyncAwait *pAwait; + int numwaits; + + pAwait = &(pAwaitUnion+1)->await; /* first await on list */ + + /* remove triggers from counters */ + + for (numwaits = pAwaitUnion->header.num_waitconditions; numwaits; + numwaits--, pAwait++) + { + /* If the counter is being destroyed, FreeCounter will delete + * the trigger list itself, so don't do it here. + */ + SyncCounter *pCounter = pAwait->trigger.pCounter; + if (pCounter && !pCounter->beingDestroyed) + SyncDeleteTriggerFromCounter(&pAwait->trigger); + } + free(pAwaitUnion); + return Success; +} + +/* loosely based on dix/events.c/OtherClientGone */ +static int +FreeAlarmClient(void *value, XID id) +{ + SyncAlarm *pAlarm = (SyncAlarm *)value; + SyncAlarmClientList *pCur, *pPrev; + + for (pPrev = NULL, pCur = pAlarm->pEventClients; + pCur; + pPrev = pCur, pCur = pCur->next) + { + if (pCur->delete_id == id) + { + if (pPrev) + pPrev->next = pCur->next; + else + pAlarm->pEventClients = pCur->next; + free(pCur); + return Success; + } + } + FatalError("alarm client not on event list"); + /*NOTREACHED*/ +} + + +/* + * ***** Proc functions + */ + + +/* + * ** Initialize the extension + */ +static int +ProcSyncInitialize(ClientPtr client) +{ + xSyncInitializeReply rep; + int n; + + REQUEST_SIZE_MATCH(xSyncInitializeReq); + + memset(&rep, 0, sizeof(xSyncInitializeReply)); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.majorVersion = SYNC_MAJOR_VERSION; + rep.minorVersion = SYNC_MINOR_VERSION; + rep.length = 0; + + if (client->swapped) + { + swaps(&rep.sequenceNumber, n); + } + WriteToClient(client, sizeof(rep), (char *) &rep); + return Success; +} + +/* + * ** Get list of system counters available through the extension + */ +static int +ProcSyncListSystemCounters(ClientPtr client) +{ + xSyncListSystemCountersReply rep; + int i, len; + xSyncSystemCounter *list = NULL, *walklist = NULL; + + REQUEST_SIZE_MATCH(xSyncListSystemCountersReq); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.nCounters = SyncNumSystemCounters; + + for (i = len = 0; i < SyncNumSystemCounters; i++) + { + char *name = SysCounterList[i]->pSysCounterInfo->name; + /* pad to 4 byte boundary */ + len += pad_to_int32(sz_xSyncSystemCounter + strlen(name)); + } + + if (len) + { + walklist = list = malloc(len); + if (!list) + return BadAlloc; + } + + rep.length = bytes_to_int32(len); + + if (client->swapped) + { + char n; + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.nCounters, n); + } + + for (i = 0; i < SyncNumSystemCounters; i++) + { + int namelen; + char *pname_in_reply; + SysCounterInfo *psci = SysCounterList[i]->pSysCounterInfo; + + walklist->counter = SysCounterList[i]->id; + walklist->resolution_hi = XSyncValueHigh32(psci->resolution); + walklist->resolution_lo = XSyncValueLow32(psci->resolution); + namelen = strlen(psci->name); + walklist->name_length = namelen; + + if (client->swapped) + { + char n; + swapl(&walklist->counter, n); + swapl(&walklist->resolution_hi, n); + swapl(&walklist->resolution_lo, n); + swaps(&walklist->name_length, n); + } + + pname_in_reply = ((char *)walklist) + sz_xSyncSystemCounter; + strncpy(pname_in_reply, psci->name, namelen); + walklist = (xSyncSystemCounter *) (((char *)walklist) + + pad_to_int32(sz_xSyncSystemCounter + namelen)); + } + + WriteToClient(client, sizeof(rep), (char *) &rep); + if (len) + { + WriteToClient(client, len, (char *) list); + free(list); + } + + return Success; +} + +/* + * ** Set client Priority + */ +static int +ProcSyncSetPriority(ClientPtr client) +{ + REQUEST(xSyncSetPriorityReq); + ClientPtr priorityclient; + int rc; + + REQUEST_SIZE_MATCH(xSyncSetPriorityReq); + + if (stuff->id == None) + priorityclient = client; + else { + rc = dixLookupClient(&priorityclient, stuff->id, client, + DixSetAttrAccess); + if (rc != Success) + return rc; + } + + if (priorityclient->priority != stuff->priority) + { + priorityclient->priority = stuff->priority; + + /* The following will force the server back into WaitForSomething + * so that the change in this client's priority is immediately + * reflected. + */ + isItTimeToYield = TRUE; + dispatchException |= DE_PRIORITYCHANGE; + } + return Success; +} + +/* + * ** Get client Priority + */ +static int +ProcSyncGetPriority(ClientPtr client) +{ + REQUEST(xSyncGetPriorityReq); + xSyncGetPriorityReply rep; + ClientPtr priorityclient; + int rc; + + REQUEST_SIZE_MATCH(xSyncGetPriorityReq); + + if (stuff->id == None) + priorityclient = client; + else { + rc = dixLookupClient(&priorityclient, stuff->id, client, + DixGetAttrAccess); + if (rc != Success) + return rc; + } + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.priority = priorityclient->priority; + + if (client->swapped) + { + char n; + swaps(&rep.sequenceNumber, n); + swapl(&rep.priority, n); + } + + WriteToClient(client, sizeof(xSyncGetPriorityReply), (char *) &rep); + + return Success; +} + +/* + * ** Create a new counter + */ +static int +ProcSyncCreateCounter(ClientPtr client) +{ + REQUEST(xSyncCreateCounterReq); + CARD64 initial; + + REQUEST_SIZE_MATCH(xSyncCreateCounterReq); + + LEGAL_NEW_RESOURCE(stuff->cid, client); + + XSyncIntsToValue(&initial, stuff->initial_value_lo, stuff->initial_value_hi); + if (!SyncCreateCounter(client, stuff->cid, initial)) + return BadAlloc; + + return Success; +} + +/* + * ** Set Counter value + */ +static int +ProcSyncSetCounter(ClientPtr client) +{ + REQUEST(xSyncSetCounterReq); + SyncCounter *pCounter; + CARD64 newvalue; + int rc; + + REQUEST_SIZE_MATCH(xSyncSetCounterReq); + + rc = dixLookupResourceByType((pointer *)&pCounter, stuff->cid, RTCounter, + client, DixWriteAccess); + if (rc != Success) + return (rc == BadValue) ? SyncErrorBase + XSyncBadCounter : rc; + + if (IsSystemCounter(pCounter)) + { + client->errorValue = stuff->cid; + return BadAccess; + } + + XSyncIntsToValue(&newvalue, stuff->value_lo, stuff->value_hi); + SyncChangeCounter(pCounter, newvalue); + return Success; +} + +/* + * ** Change Counter value + */ +static int +ProcSyncChangeCounter(ClientPtr client) +{ + REQUEST(xSyncChangeCounterReq); + SyncCounter *pCounter; + CARD64 newvalue; + Bool overflow; + int rc; + + REQUEST_SIZE_MATCH(xSyncChangeCounterReq); + + rc = dixLookupResourceByType((pointer *)&pCounter, stuff->cid, RTCounter, + client, DixWriteAccess); + if (rc != Success) + return (rc == BadValue) ? SyncErrorBase + XSyncBadCounter : rc; + + if (IsSystemCounter(pCounter)) + { + client->errorValue = stuff->cid; + return BadAccess; + } + + XSyncIntsToValue(&newvalue, stuff->value_lo, stuff->value_hi); + XSyncValueAdd(&newvalue, pCounter->value, newvalue, &overflow); + if (overflow) + { + /* XXX 64 bit value can't fit in 32 bits; do the best we can */ + client->errorValue = stuff->value_hi; + return BadValue; + } + SyncChangeCounter(pCounter, newvalue); + return Success; +} + +/* + * ** Destroy a counter + */ +static int +ProcSyncDestroyCounter(ClientPtr client) +{ + REQUEST(xSyncDestroyCounterReq); + SyncCounter *pCounter; + int rc; + + REQUEST_SIZE_MATCH(xSyncDestroyCounterReq); + + rc = dixLookupResourceByType((pointer *)&pCounter, stuff->counter, RTCounter, + client, DixDestroyAccess); + if (rc != Success) + return (rc == BadValue) ? SyncErrorBase + XSyncBadCounter : rc; + + if (IsSystemCounter(pCounter)) + { + client->errorValue = stuff->counter; + return BadAccess; + } + FreeResource(pCounter->id, RT_NONE); + return Success; +} + + +/* + * ** Await + */ +static int +ProcSyncAwait(ClientPtr client) +{ + REQUEST(xSyncAwaitReq); + int len, items; + int i; + xSyncWaitCondition *pProtocolWaitConds; + SyncAwaitUnion *pAwaitUnion; + SyncAwait *pAwait; + int status; + + REQUEST_AT_LEAST_SIZE(xSyncAwaitReq); + + len = client->req_len << 2; + len -= sz_xSyncAwaitReq; + items = len / sz_xSyncWaitCondition; + + if (items * sz_xSyncWaitCondition != len) + { + return BadLength; + } + if (items == 0) + { + client->errorValue = items; /* XXX protocol change */ + return BadValue; + } + + pProtocolWaitConds = (xSyncWaitCondition *) & stuff[1]; + + /* all the memory for the entire await list is allocated + * here in one chunk + */ + pAwaitUnion = malloc((items+1) * sizeof(SyncAwaitUnion)); + if (!pAwaitUnion) + return BadAlloc; + + /* first item is the header, remainder are real wait conditions */ + + pAwaitUnion->header.delete_id = FakeClientID(client->index); + if (!AddResource(pAwaitUnion->header.delete_id, RTAwait, pAwaitUnion)) + { + free(pAwaitUnion); + return BadAlloc; + } + + /* don't need to do any more memory allocation for this request! */ + + pAwaitUnion->header.client = client; + pAwaitUnion->header.num_waitconditions = 0; + + pAwait = &(pAwaitUnion+1)->await; /* skip over header */ + for (i = 0; i < items; i++, pProtocolWaitConds++, pAwait++) + { + if (pProtocolWaitConds->counter == None) /* XXX protocol change */ + { + /* this should take care of removing any triggers created by + * this request that have already been registered on counters + */ + FreeResource(pAwaitUnion->header.delete_id, RT_NONE); + client->errorValue = pProtocolWaitConds->counter; + return SyncErrorBase + XSyncBadCounter; + } + + /* sanity checks are in SyncInitTrigger */ + pAwait->trigger.pCounter = NULL; + pAwait->trigger.value_type = pProtocolWaitConds->value_type; + XSyncIntsToValue(&pAwait->trigger.wait_value, + pProtocolWaitConds->wait_value_lo, + pProtocolWaitConds->wait_value_hi); + pAwait->trigger.test_type = pProtocolWaitConds->test_type; + + status = SyncInitTrigger(client, &pAwait->trigger, + pProtocolWaitConds->counter, XSyncCAAllTrigger); + if (status != Success) + { + /* this should take care of removing any triggers created by + * this request that have already been registered on counters + */ + FreeResource(pAwaitUnion->header.delete_id, RT_NONE); + return status; + } + /* this is not a mistake -- same function works for both cases */ + pAwait->trigger.TriggerFired = SyncAwaitTriggerFired; + pAwait->trigger.CounterDestroyed = SyncAwaitTriggerFired; + XSyncIntsToValue(&pAwait->event_threshold, + pProtocolWaitConds->event_threshold_lo, + pProtocolWaitConds->event_threshold_hi); + pAwait->pHeader = &pAwaitUnion->header; + pAwaitUnion->header.num_waitconditions++; + } + + IgnoreClient(client); + + /* see if any of the triggers are already true */ + + pAwait = &(pAwaitUnion+1)->await; /* skip over header */ + for (i = 0; i < items; i++, pAwait++) + { + /* don't have to worry about NULL counters because the request + * errors before we get here out if they occur + */ + if ((*pAwait->trigger.CheckTrigger)(&pAwait->trigger, + pAwait->trigger.pCounter->value)) + { + (*pAwait->trigger.TriggerFired)(&pAwait->trigger); + break; /* once is enough */ + } + } + return Success; +} + + +/* + * ** Query a counter + */ +static int +ProcSyncQueryCounter(ClientPtr client) +{ + REQUEST(xSyncQueryCounterReq); + xSyncQueryCounterReply rep; + SyncCounter *pCounter; + int rc; + + REQUEST_SIZE_MATCH(xSyncQueryCounterReq); + + rc = dixLookupResourceByType((pointer *)&pCounter, stuff->counter, + RTCounter, client, DixReadAccess); + if (rc != Success) + return (rc == BadValue) ? SyncErrorBase + XSyncBadCounter : rc; + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + + /* if system counter, ask it what the current value is */ + + if (IsSystemCounter(pCounter)) + { + (*pCounter->pSysCounterInfo->QueryValue) ((pointer) pCounter, + &pCounter->value); + } + + rep.value_hi = XSyncValueHigh32(pCounter->value); + rep.value_lo = XSyncValueLow32(pCounter->value); + if (client->swapped) + { + char n; + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.value_hi, n); + swapl(&rep.value_lo, n); + } + WriteToClient(client, sizeof(xSyncQueryCounterReply), (char *) &rep); + return Success; +} + + +/* + * ** Create Alarm + */ +static int +ProcSyncCreateAlarm(ClientPtr client) +{ + REQUEST(xSyncCreateAlarmReq); + SyncAlarm *pAlarm; + int status; + unsigned long len, vmask; + SyncTrigger *pTrigger; + + REQUEST_AT_LEAST_SIZE(xSyncCreateAlarmReq); + + LEGAL_NEW_RESOURCE(stuff->id, client); + + vmask = stuff->valueMask; + len = client->req_len - bytes_to_int32(sizeof(xSyncCreateAlarmReq)); + /* the "extra" call to Ones accounts for the presence of 64 bit values */ + if (len != (Ones(vmask) + Ones(vmask & (XSyncCAValue|XSyncCADelta)))) + return BadLength; + + if (!(pAlarm = malloc(sizeof(SyncAlarm)))) + { + return BadAlloc; + } + + /* set up defaults */ + + pTrigger = &pAlarm->trigger; + pTrigger->pCounter = NULL; + pTrigger->value_type = XSyncAbsolute; + XSyncIntToValue(&pTrigger->wait_value, 0L); + pTrigger->test_type = XSyncPositiveComparison; + pTrigger->TriggerFired = SyncAlarmTriggerFired; + pTrigger->CounterDestroyed = SyncAlarmCounterDestroyed; + status = SyncInitTrigger(client, pTrigger, None, XSyncCAAllTrigger); + if (status != Success) + { + free(pAlarm); + return status; + } + + pAlarm->client = client; + pAlarm->alarm_id = stuff->id; + XSyncIntToValue(&pAlarm->delta, 1L); + pAlarm->events = TRUE; + pAlarm->state = XSyncAlarmInactive; + pAlarm->pEventClients = NULL; + status = SyncChangeAlarmAttributes(client, pAlarm, vmask, + (CARD32 *)&stuff[1]); + if (status != Success) + { + free(pAlarm); + return status; + } + + if (!AddResource(stuff->id, RTAlarm, pAlarm)) + { + free(pAlarm); + return BadAlloc; + } + + /* see if alarm already triggered. NULL counter will not trigger + * in CreateAlarm and sets alarm state to Inactive. + */ + + if (!pTrigger->pCounter) + { + pAlarm->state = XSyncAlarmInactive; /* XXX protocol change */ + } + else if ((*pTrigger->CheckTrigger)(pTrigger, pTrigger->pCounter->value)) + { + (*pTrigger->TriggerFired)(pTrigger); + } + + return Success; +} + +/* + * ** Change Alarm + */ +static int +ProcSyncChangeAlarm(ClientPtr client) +{ + REQUEST(xSyncChangeAlarmReq); + SyncAlarm *pAlarm; + long vmask; + int len, status; + + REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq); + + status = dixLookupResourceByType((pointer *)&pAlarm, stuff->alarm, RTAlarm, + client, DixWriteAccess); + if (status != Success) + return (status == BadValue) ? SyncErrorBase + XSyncBadAlarm : status; + + vmask = stuff->valueMask; + len = client->req_len - bytes_to_int32(sizeof(xSyncChangeAlarmReq)); + /* the "extra" call to Ones accounts for the presence of 64 bit values */ + if (len != (Ones(vmask) + Ones(vmask & (XSyncCAValue|XSyncCADelta)))) + return BadLength; + + if ((status = SyncChangeAlarmAttributes(client, pAlarm, vmask, + (CARD32 *)&stuff[1])) != Success) + return status; + + /* see if alarm already triggered. NULL counter WILL trigger + * in ChangeAlarm. + */ + + if (!pAlarm->trigger.pCounter || + (*pAlarm->trigger.CheckTrigger)(&pAlarm->trigger, + pAlarm->trigger.pCounter->value)) + { + (*pAlarm->trigger.TriggerFired)(&pAlarm->trigger); + } + return Success; +} + +static int +ProcSyncQueryAlarm(ClientPtr client) +{ + REQUEST(xSyncQueryAlarmReq); + SyncAlarm *pAlarm; + xSyncQueryAlarmReply rep; + SyncTrigger *pTrigger; + int rc; + + REQUEST_SIZE_MATCH(xSyncQueryAlarmReq); + + rc = dixLookupResourceByType((pointer *)&pAlarm, stuff->alarm, RTAlarm, + client, DixReadAccess); + if (rc != Success) + return (rc == BadValue) ? SyncErrorBase + XSyncBadAlarm : rc; + + rep.type = X_Reply; + rep.length = bytes_to_int32(sizeof(xSyncQueryAlarmReply) - sizeof(xGenericReply)); + rep.sequenceNumber = client->sequence; + + pTrigger = &pAlarm->trigger; + rep.counter = (pTrigger->pCounter) ? pTrigger->pCounter->id : None; + +#if 0 /* XXX unclear what to do, depends on whether relative value-types + * are "consumed" immediately and are considered absolute from then + * on. + */ + rep.value_type = pTrigger->value_type; + rep.wait_value_hi = XSyncValueHigh32(pTrigger->wait_value); + rep.wait_value_lo = XSyncValueLow32(pTrigger->wait_value); +#else + rep.value_type = XSyncAbsolute; + rep.wait_value_hi = XSyncValueHigh32(pTrigger->test_value); + rep.wait_value_lo = XSyncValueLow32(pTrigger->test_value); +#endif + + rep.test_type = pTrigger->test_type; + rep.delta_hi = XSyncValueHigh32(pAlarm->delta); + rep.delta_lo = XSyncValueLow32(pAlarm->delta); + rep.events = pAlarm->events; + rep.state = pAlarm->state; + + if (client->swapped) + { + char n; + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.counter, n); + swapl(&rep.wait_value_hi, n); + swapl(&rep.wait_value_lo, n); + swapl(&rep.test_type, n); + swapl(&rep.delta_hi, n); + swapl(&rep.delta_lo, n); + } + + WriteToClient(client, sizeof(xSyncQueryAlarmReply), (char *) &rep); + return Success; +} + +static int +ProcSyncDestroyAlarm(ClientPtr client) +{ + SyncAlarm *pAlarm; + int rc; + REQUEST(xSyncDestroyAlarmReq); + + REQUEST_SIZE_MATCH(xSyncDestroyAlarmReq); + + rc = dixLookupResourceByType((pointer *)&pAlarm, stuff->alarm, RTAlarm, + client, DixDestroyAccess); + if (rc != Success) + return (rc == BadValue) ? SyncErrorBase + XSyncBadAlarm : rc; + + FreeResource(stuff->alarm, RT_NONE); + return Success; +} + +/* + * ** Given an extension request, call the appropriate request procedure + */ +static int +ProcSyncDispatch(ClientPtr client) +{ + REQUEST(xReq); + + switch (stuff->data) + { + case X_SyncInitialize: + return ProcSyncInitialize(client); + case X_SyncListSystemCounters: + return ProcSyncListSystemCounters(client); + case X_SyncCreateCounter: + return ProcSyncCreateCounter(client); + case X_SyncSetCounter: + return ProcSyncSetCounter(client); + case X_SyncChangeCounter: + return ProcSyncChangeCounter(client); + case X_SyncQueryCounter: + return ProcSyncQueryCounter(client); + case X_SyncDestroyCounter: + return ProcSyncDestroyCounter(client); + case X_SyncAwait: + return ProcSyncAwait(client); + case X_SyncCreateAlarm: + return ProcSyncCreateAlarm(client); + case X_SyncChangeAlarm: + return ProcSyncChangeAlarm(client); + case X_SyncQueryAlarm: + return ProcSyncQueryAlarm(client); + case X_SyncDestroyAlarm: + return ProcSyncDestroyAlarm(client); + case X_SyncSetPriority: + return ProcSyncSetPriority(client); + case X_SyncGetPriority: + return ProcSyncGetPriority(client); + default: + return BadRequest; + } +} + +/* + * Boring Swapping stuff ... + */ + +static int +SProcSyncInitialize(ClientPtr client) +{ + REQUEST(xSyncInitializeReq); + char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH (xSyncInitializeReq); + + return ProcSyncInitialize(client); +} + +static int +SProcSyncListSystemCounters(ClientPtr client) +{ + REQUEST(xSyncListSystemCountersReq); + char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH (xSyncListSystemCountersReq); + + return ProcSyncListSystemCounters(client); +} + +static int +SProcSyncCreateCounter(ClientPtr client) +{ + REQUEST(xSyncCreateCounterReq); + char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH (xSyncCreateCounterReq); + swapl(&stuff->cid, n); + swapl(&stuff->initial_value_lo, n); + swapl(&stuff->initial_value_hi, n); + + return ProcSyncCreateCounter(client); +} + +static int +SProcSyncSetCounter(ClientPtr client) +{ + REQUEST(xSyncSetCounterReq); + char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH (xSyncSetCounterReq); + swapl(&stuff->cid, n); + swapl(&stuff->value_lo, n); + swapl(&stuff->value_hi, n); + + return ProcSyncSetCounter(client); +} + +static int +SProcSyncChangeCounter(ClientPtr client) +{ + REQUEST(xSyncChangeCounterReq); + char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH (xSyncChangeCounterReq); + swapl(&stuff->cid, n); + swapl(&stuff->value_lo, n); + swapl(&stuff->value_hi, n); + + return ProcSyncChangeCounter(client); +} + +static int +SProcSyncQueryCounter(ClientPtr client) +{ + REQUEST(xSyncQueryCounterReq); + char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH (xSyncQueryCounterReq); + swapl(&stuff->counter, n); + + return ProcSyncQueryCounter(client); +} + +static int +SProcSyncDestroyCounter(ClientPtr client) +{ + REQUEST(xSyncDestroyCounterReq); + char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH (xSyncDestroyCounterReq); + swapl(&stuff->counter, n); + + return ProcSyncDestroyCounter(client); +} + +static int +SProcSyncAwait(ClientPtr client) +{ + REQUEST(xSyncAwaitReq); + char n; + + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xSyncAwaitReq); + SwapRestL(stuff); + + return ProcSyncAwait(client); +} + +static int +SProcSyncCreateAlarm(ClientPtr client) +{ + REQUEST(xSyncCreateAlarmReq); + char n; + + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xSyncCreateAlarmReq); + swapl(&stuff->id, n); + swapl(&stuff->valueMask, n); + SwapRestL(stuff); + + return ProcSyncCreateAlarm(client); +} + +static int +SProcSyncChangeAlarm(ClientPtr client) +{ + REQUEST(xSyncChangeAlarmReq); + char n; + + swaps(&stuff->length, n); + REQUEST_AT_LEAST_SIZE(xSyncChangeAlarmReq); + swapl(&stuff->alarm, n); + swapl(&stuff->valueMask, n); + SwapRestL(stuff); + return ProcSyncChangeAlarm(client); +} + +static int +SProcSyncQueryAlarm(ClientPtr client) +{ + REQUEST(xSyncQueryAlarmReq); + char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH (xSyncQueryAlarmReq); + swapl(&stuff->alarm, n); + + return ProcSyncQueryAlarm(client); +} + +static int +SProcSyncDestroyAlarm(ClientPtr client) +{ + REQUEST(xSyncDestroyAlarmReq); + char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH (xSyncDestroyAlarmReq); + swapl(&stuff->alarm, n); + + return ProcSyncDestroyAlarm(client); +} + +static int +SProcSyncSetPriority(ClientPtr client) +{ + REQUEST(xSyncSetPriorityReq); + char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH (xSyncSetPriorityReq); + swapl(&stuff->id, n); + swapl(&stuff->priority, n); + + return ProcSyncSetPriority(client); +} + +static int +SProcSyncGetPriority(ClientPtr client) +{ + REQUEST(xSyncGetPriorityReq); + char n; + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH (xSyncGetPriorityReq); + swapl(&stuff->id, n); + + return ProcSyncGetPriority(client); +} + + +static int +SProcSyncDispatch(ClientPtr client) +{ + REQUEST(xReq); + + switch (stuff->data) + { + case X_SyncInitialize: + return SProcSyncInitialize(client); + case X_SyncListSystemCounters: + return SProcSyncListSystemCounters(client); + case X_SyncCreateCounter: + return SProcSyncCreateCounter(client); + case X_SyncSetCounter: + return SProcSyncSetCounter(client); + case X_SyncChangeCounter: + return SProcSyncChangeCounter(client); + case X_SyncQueryCounter: + return SProcSyncQueryCounter(client); + case X_SyncDestroyCounter: + return SProcSyncDestroyCounter(client); + case X_SyncAwait: + return SProcSyncAwait(client); + case X_SyncCreateAlarm: + return SProcSyncCreateAlarm(client); + case X_SyncChangeAlarm: + return SProcSyncChangeAlarm(client); + case X_SyncQueryAlarm: + return SProcSyncQueryAlarm(client); + case X_SyncDestroyAlarm: + return SProcSyncDestroyAlarm(client); + case X_SyncSetPriority: + return SProcSyncSetPriority(client); + case X_SyncGetPriority: + return SProcSyncGetPriority(client); + default: + return BadRequest; + } +} + +/* + * Event Swapping + */ + +static void +SCounterNotifyEvent(xSyncCounterNotifyEvent *from, xSyncCounterNotifyEvent *to) +{ + to->type = from->type; + to->kind = from->kind; + cpswaps(from->sequenceNumber, to->sequenceNumber); + cpswapl(from->counter, to->counter); + cpswapl(from->wait_value_lo, to->wait_value_lo); + cpswapl(from->wait_value_hi, to->wait_value_hi); + cpswapl(from->counter_value_lo, to->counter_value_lo); + cpswapl(from->counter_value_hi, to->counter_value_hi); + cpswapl(from->time, to->time); + cpswaps(from->count, to->count); + to->destroyed = from->destroyed; +} + + +static void +SAlarmNotifyEvent(xSyncAlarmNotifyEvent *from, xSyncAlarmNotifyEvent *to) +{ + to->type = from->type; + to->kind = from->kind; + cpswaps(from->sequenceNumber, to->sequenceNumber); + cpswapl(from->alarm, to->alarm); + cpswapl(from->counter_value_lo, to->counter_value_lo); + cpswapl(from->counter_value_hi, to->counter_value_hi); + cpswapl(from->alarm_value_lo, to->alarm_value_lo); + cpswapl(from->alarm_value_hi, to->alarm_value_hi); + cpswapl(from->time, to->time); + to->state = from->state; +} + +/* + * ** Close everything down. ** This is fairly simple for now. + */ +/* ARGSUSED */ +static void +SyncResetProc(ExtensionEntry *extEntry) +{ + free(SysCounterList); + SysCounterList = NULL; + RTCounter = 0; +} + + +/* + * ** Initialise the extension. + */ +void +SyncExtensionInit(void) +{ + ExtensionEntry *extEntry; + + if (RTCounter == 0) + { + RTCounter = CreateNewResourceType(FreeCounter, "SyncCounter"); + } + RTAlarm = CreateNewResourceType(FreeAlarm, "SyncAlarm"); + RTAwait = CreateNewResourceType(FreeAwait, "SyncAwait"); + if (RTAwait) + RTAwait |= RC_NEVERRETAIN; + RTAlarmClient = CreateNewResourceType(FreeAlarmClient, "SyncAlarmClient"); + if (RTAlarmClient) + RTAlarmClient |= RC_NEVERRETAIN; + + if (RTCounter == 0 || RTAwait == 0 || RTAlarm == 0 || + RTAlarmClient == 0 || + (extEntry = AddExtension(SYNC_NAME, + XSyncNumberEvents, XSyncNumberErrors, + ProcSyncDispatch, SProcSyncDispatch, + SyncResetProc, + StandardMinorOpcode)) == NULL) + { + ErrorF("Sync Extension %d.%d failed to Initialise\n", + SYNC_MAJOR_VERSION, SYNC_MINOR_VERSION); + return; + } + + SyncEventBase = extEntry->eventBase; + SyncErrorBase = extEntry->errorBase; + EventSwapVector[SyncEventBase + XSyncCounterNotify] = (EventSwapPtr) SCounterNotifyEvent; + EventSwapVector[SyncEventBase + XSyncAlarmNotify] = (EventSwapPtr) SAlarmNotifyEvent; + + /* + * Although SERVERTIME is implemented by the OS layer, we initialise it + * here because doing it in OsInit() is too early. The resource database + * is not initialised when OsInit() is called. This is just about OK + * because there is always a servertime counter. + */ + SyncInitServerTime(); + SyncInitIdleTime(); + +#ifdef DEBUG + fprintf(stderr, "Sync Extension %d.%d\n", + SYNC_MAJOR_VERSION, SYNC_MINOR_VERSION); +#endif +} + + +/* + * ***** SERVERTIME implementation - should go in its own file in OS directory? + */ + + + +static pointer ServertimeCounter; +static XSyncValue Now; +static XSyncValue *pnext_time; + +#define GetTime()\ +{\ + unsigned long millis = GetTimeInMillis();\ + unsigned long maxis = XSyncValueHigh32(Now);\ + if (millis < XSyncValueLow32(Now)) maxis++;\ + XSyncIntsToValue(&Now, millis, maxis);\ +} + +/* +*** Server Block Handler +*** code inspired by multibuffer extension (now deprecated) + */ +/*ARGSUSED*/ +static void +ServertimeBlockHandler(void *env, struct timeval **wt, void *LastSelectMask) +{ + XSyncValue delay; + unsigned long timeout; + + if (pnext_time) + { + GetTime(); + + if (XSyncValueGreaterOrEqual(Now, *pnext_time)) + { + timeout = 0; + } + else + { + Bool overflow; + XSyncValueSubtract(&delay, *pnext_time, Now, &overflow); + (void)overflow; + timeout = XSyncValueLow32(delay); + } + AdjustWaitForDelay(wt, timeout); /* os/utils.c */ + } +} + +/* +*** Wakeup Handler + */ +/*ARGSUSED*/ +static void +ServertimeWakeupHandler(void *env, int rc, void *LastSelectMask) +{ + if (pnext_time) + { + GetTime(); + + if (XSyncValueGreaterOrEqual(Now, *pnext_time)) + { + SyncChangeCounter(ServertimeCounter, Now); + } + } +} + +static void +ServertimeQueryValue(void *pCounter, CARD64 *pValue_return) +{ + GetTime(); + *pValue_return = Now; +} + +static void +ServertimeBracketValues(void *pCounter, CARD64 *pbracket_less, + CARD64 *pbracket_greater) +{ + if (!pnext_time && pbracket_greater) + { + RegisterBlockAndWakeupHandlers(ServertimeBlockHandler, + ServertimeWakeupHandler, + NULL); + } + else if (pnext_time && !pbracket_greater) + { + RemoveBlockAndWakeupHandlers(ServertimeBlockHandler, + ServertimeWakeupHandler, + NULL); + } + pnext_time = pbracket_greater; +} + +static void +SyncInitServerTime(void) +{ + CARD64 resolution; + + XSyncIntsToValue(&Now, GetTimeInMillis(), 0); + XSyncIntToValue(&resolution, 4); + ServertimeCounter = SyncCreateSystemCounter("SERVERTIME", Now, resolution, + XSyncCounterNeverDecreases, + ServertimeQueryValue, ServertimeBracketValues); + pnext_time = NULL; +} + + + +/* + * IDLETIME implementation + */ + +static SyncCounter *IdleTimeCounter; +static XSyncValue *pIdleTimeValueLess; +static XSyncValue *pIdleTimeValueGreater; + +static void +IdleTimeQueryValue (pointer pCounter, CARD64 *pValue_return) +{ + CARD32 idle = GetTimeInMillis() - lastDeviceEventTime.milliseconds; + XSyncIntsToValue (pValue_return, idle, 0); +} + +static void +IdleTimeBlockHandler(pointer env, struct timeval **wt, pointer LastSelectMask) +{ + XSyncValue idle, old_idle; + SyncTriggerList *list = IdleTimeCounter->pTriglist; + SyncTrigger *trig; + + if (!pIdleTimeValueLess && !pIdleTimeValueGreater) + return; + + old_idle = IdleTimeCounter->value; + IdleTimeQueryValue (NULL, &idle); + IdleTimeCounter->value = idle; /* push, so CheckTrigger works */ + + if (pIdleTimeValueLess && + XSyncValueLessOrEqual (idle, *pIdleTimeValueLess)) + { + /* + * We've been idle for less than the threshold value, and someone + * wants to know about that, but now we need to know whether they + * want level or edge trigger. Check the trigger list against the + * current idle time, and if any succeed, bomb out of select() + * immediately so we can reschedule. + */ + + for (list = IdleTimeCounter->pTriglist; list; list = list->next) { + trig = list->pTrigger; + if (trig->CheckTrigger(trig, old_idle)) { + AdjustWaitForDelay(wt, 0); + break; + } + } + } + else if (pIdleTimeValueGreater) + { + /* + * There's a threshold in the positive direction. If we've been + * idle less than it, schedule a wakeup for sometime in the future. + * If we've been idle more than it, and someone wants to know about + * that level-triggered, schedule an immediate wakeup. + */ + unsigned long timeout = -1; + + if (XSyncValueLessThan (idle, *pIdleTimeValueGreater)) { + XSyncValue value; + Bool overflow; + + XSyncValueSubtract (&value, *pIdleTimeValueGreater, + idle, &overflow); + timeout = min(timeout, XSyncValueLow32 (value)); + } else { + for (list = IdleTimeCounter->pTriglist; list; list = list->next) { + trig = list->pTrigger; + if (trig->CheckTrigger(trig, old_idle)) { + timeout = min(timeout, 0); + break; + } + } + } + + AdjustWaitForDelay (wt, timeout); + } + + IdleTimeCounter->value = old_idle; /* pop */ +} + +static void +IdleTimeWakeupHandler (pointer env, int rc, pointer LastSelectMask) +{ + XSyncValue idle; + + if (!pIdleTimeValueLess && !pIdleTimeValueGreater) + return; + + IdleTimeQueryValue (NULL, &idle); + + if ((pIdleTimeValueGreater && + XSyncValueGreaterOrEqual (idle, *pIdleTimeValueGreater)) || + (pIdleTimeValueLess && + XSyncValueLessOrEqual (idle, *pIdleTimeValueLess))) + { + SyncChangeCounter (IdleTimeCounter, idle); + } +} + +static void +IdleTimeBracketValues (pointer pCounter, CARD64 *pbracket_less, + CARD64 *pbracket_greater) +{ + Bool registered = (pIdleTimeValueLess || pIdleTimeValueGreater); + + if (registered && !pbracket_less && !pbracket_greater) + { + RemoveBlockAndWakeupHandlers(IdleTimeBlockHandler, + IdleTimeWakeupHandler, + NULL); + } + else if (!registered && (pbracket_less || pbracket_greater)) + { + RegisterBlockAndWakeupHandlers(IdleTimeBlockHandler, + IdleTimeWakeupHandler, + NULL); + } + + pIdleTimeValueGreater = pbracket_greater; + pIdleTimeValueLess = pbracket_less; +} + +static void +SyncInitIdleTime (void) +{ + CARD64 resolution; + XSyncValue idle; + + IdleTimeQueryValue (NULL, &idle); + XSyncIntToValue (&resolution, 4); + + IdleTimeCounter = SyncCreateSystemCounter ("IDLETIME", idle, resolution, + XSyncCounterUnrestricted, + IdleTimeQueryValue, + IdleTimeBracketValues); + + pIdleTimeValueLess = pIdleTimeValueGreater = NULL; +} diff --git a/xorg-server/Xext/xace.c b/xorg-server/Xext/xace.c index bf0e98fb0..648de53fe 100644 --- a/xorg-server/Xext/xace.c +++ b/xorg-server/Xext/xace.c @@ -1,350 +1,350 @@ -/************************************************************ - -Author: Eamon Walsh - -Permission to use, copy, modify, distribute, and sell this software and its -documentation for any purpose is hereby granted without fee, provided that -this permission notice appear in supporting documentation. 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 -AUTHOR 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 -#endif - -#include -#include "scrnintstr.h" -#include "extnsionst.h" -#include "pixmapstr.h" -#include "regionstr.h" -#include "gcstruct.h" -#include "xacestr.h" - -#define XSERV_t -#define TRANS_SERVER -#include -#include "../os/osdep.h" - -_X_EXPORT CallbackListPtr XaceHooks[XACE_NUM_HOOKS] = {0}; - -/* Special-cased hook functions. Called by Xserver. - */ -int XaceHookDispatch(ClientPtr client, int major) -{ - /* Call the audit begin callback, there is no return value. */ - XaceAuditRec rec = { client, 0 }; - CallCallbacks(&XaceHooks[XACE_AUDIT_BEGIN], &rec); - - if (major < 128) { - /* Call the core dispatch hook */ - XaceCoreDispatchRec rec = { client, Success /* default allow */ }; - CallCallbacks(&XaceHooks[XACE_CORE_DISPATCH], &rec); - return rec.status; - } else { - /* Call the extension dispatch hook */ - ExtensionEntry *ext = GetExtensionEntry(major); - XaceExtAccessRec rec = { client, ext, DixUseAccess, Success }; - if (ext) - CallCallbacks(&XaceHooks[XACE_EXT_DISPATCH], &rec); - /* On error, pretend extension doesn't exist */ - return (rec.status == Success) ? Success : BadRequest; - } -} - -int XaceHookPropertyAccess(ClientPtr client, WindowPtr pWin, - PropertyPtr *ppProp, Mask access_mode) -{ - XacePropertyAccessRec rec = { client, pWin, ppProp, access_mode, Success }; - CallCallbacks(&XaceHooks[XACE_PROPERTY_ACCESS], &rec); - return rec.status; -} - -int XaceHookSelectionAccess(ClientPtr client, - Selection **ppSel, Mask access_mode) -{ - XaceSelectionAccessRec rec = { client, ppSel, access_mode, Success }; - CallCallbacks(&XaceHooks[XACE_SELECTION_ACCESS], &rec); - return rec.status; -} - -void XaceHookAuditEnd(ClientPtr ptr, int result) -{ - XaceAuditRec rec = { ptr, result }; - /* call callbacks, there is no return value. */ - CallCallbacks(&XaceHooks[XACE_AUDIT_END], &rec); -} - -/* Entry point for hook functions. Called by Xserver. - */ -int XaceHook(int hook, ...) -{ - pointer calldata; /* data passed to callback */ - int *prv = NULL; /* points to return value from callback */ - va_list ap; /* argument list */ - va_start(ap, hook); - - /* Marshal arguments for passing to callback. - * Each callback has its own case, which sets up a structure to hold - * the arguments and integer return parameter, or in some cases just - * sets calldata directly to a single argument (with no return result) - */ - switch (hook) - { - case XACE_RESOURCE_ACCESS: { - XaceResourceAccessRec rec; - rec.client = va_arg(ap, ClientPtr); - rec.id = va_arg(ap, XID); - rec.rtype = va_arg(ap, RESTYPE); - rec.res = va_arg(ap, pointer); - rec.ptype = va_arg(ap, RESTYPE); - rec.parent = va_arg(ap, pointer); - rec.access_mode = va_arg(ap, Mask); - rec.status = Success; /* default allow */ - calldata = &rec; - prv = &rec.status; - break; - } - case XACE_DEVICE_ACCESS: { - XaceDeviceAccessRec rec; - rec.client = va_arg(ap, ClientPtr); - rec.dev = va_arg(ap, DeviceIntPtr); - rec.access_mode = va_arg(ap, Mask); - rec.status = Success; /* default allow */ - calldata = &rec; - prv = &rec.status; - break; - } - case XACE_SEND_ACCESS: { - XaceSendAccessRec rec; - rec.client = va_arg(ap, ClientPtr); - rec.dev = va_arg(ap, DeviceIntPtr); - rec.pWin = va_arg(ap, WindowPtr); - rec.events = va_arg(ap, xEventPtr); - rec.count = va_arg(ap, int); - rec.status = Success; /* default allow */ - calldata = &rec; - prv = &rec.status; - break; - } - case XACE_RECEIVE_ACCESS: { - XaceReceiveAccessRec rec; - rec.client = va_arg(ap, ClientPtr); - rec.pWin = va_arg(ap, WindowPtr); - rec.events = va_arg(ap, xEventPtr); - rec.count = va_arg(ap, int); - rec.status = Success; /* default allow */ - calldata = &rec; - prv = &rec.status; - break; - } - case XACE_CLIENT_ACCESS: { - XaceClientAccessRec rec; - rec.client = va_arg(ap, ClientPtr); - rec.target = va_arg(ap, ClientPtr); - rec.access_mode = va_arg(ap, Mask); - rec.status = Success; /* default allow */ - calldata = &rec; - prv = &rec.status; - break; - } - case XACE_EXT_ACCESS: { - XaceExtAccessRec rec; - rec.client = va_arg(ap, ClientPtr); - rec.ext = va_arg(ap, ExtensionEntry*); - rec.access_mode = DixGetAttrAccess; - rec.status = Success; /* default allow */ - calldata = &rec; - prv = &rec.status; - break; - } - case XACE_SERVER_ACCESS: { - XaceServerAccessRec rec; - rec.client = va_arg(ap, ClientPtr); - rec.access_mode = va_arg(ap, Mask); - rec.status = Success; /* default allow */ - calldata = &rec; - prv = &rec.status; - break; - } - case XACE_SCREEN_ACCESS: - case XACE_SCREENSAVER_ACCESS: { - XaceScreenAccessRec rec; - rec.client = va_arg(ap, ClientPtr); - rec.screen = va_arg(ap, ScreenPtr); - rec.access_mode = va_arg(ap, Mask); - rec.status = Success; /* default allow */ - calldata = &rec; - prv = &rec.status; - break; - } - case XACE_AUTH_AVAIL: { - XaceAuthAvailRec rec; - rec.client = va_arg(ap, ClientPtr); - rec.authId = va_arg(ap, XID); - calldata = &rec; - break; - } - case XACE_KEY_AVAIL: { - XaceKeyAvailRec rec; - rec.event = va_arg(ap, xEventPtr); - rec.keybd = va_arg(ap, DeviceIntPtr); - rec.count = va_arg(ap, int); - calldata = &rec; - break; - } - default: { - va_end(ap); - return 0; /* unimplemented hook number */ - } - } - va_end(ap); - - /* call callbacks and return result, if any. */ - CallCallbacks(&XaceHooks[hook], calldata); - return prv ? *prv : Success; -} - -/* XaceCensorImage - * - * Called after pScreen->GetImage to prevent pieces or trusted windows from - * being returned in image data from an untrusted window. - * - * Arguments: - * client is the client doing the GetImage. - * pVisibleRegion is the visible region of the window. - * widthBytesLine is the width in bytes of one horizontal line in pBuf. - * pDraw is the source window. - * x, y, w, h is the rectangle of image data from pDraw in pBuf. - * format is the format of the image data in pBuf: ZPixmap or XYPixmap. - * pBuf is the image data. - * - * Returns: nothing. - * - * Side Effects: - * Any part of the rectangle (x, y, w, h) that is outside the visible - * region of the window will be destroyed (overwritten) in pBuf. - */ -void -XaceCensorImage( - ClientPtr client, - RegionPtr pVisibleRegion, - long widthBytesLine, - DrawablePtr pDraw, - int x, int y, int w, int h, - unsigned int format, - char *pBuf) -{ - ScreenPtr pScreen; - RegionRec imageRegion; /* region representing x,y,w,h */ - RegionRec censorRegion; /* region to obliterate */ - BoxRec imageBox; - int nRects; - - pScreen = pDraw->pScreen; - - imageBox.x1 = x; - imageBox.y1 = y; - imageBox.x2 = x + w; - imageBox.y2 = y + h; - REGION_INIT(pScreen, &imageRegion, &imageBox, 1); - REGION_NULL(pScreen, &censorRegion); - - /* censorRegion = imageRegion - visibleRegion */ - REGION_SUBTRACT(pScreen, &censorRegion, &imageRegion, pVisibleRegion); - nRects = REGION_NUM_RECTS(&censorRegion); - if (nRects > 0) - { /* we have something to censor */ - GCPtr pScratchGC = NULL; - PixmapPtr pPix = NULL; - xRectangle *pRects = NULL; - Bool failed = FALSE; - int depth = 1; - int bitsPerPixel = 1; - int i; - BoxPtr pBox; - - /* convert region to list-of-rectangles for PolyFillRect */ - - pRects = xalloc(nRects * sizeof(xRectangle)); - if (!pRects) - { - failed = TRUE; - goto failSafe; - } - for (pBox = REGION_RECTS(&censorRegion), i = 0; - i < nRects; - i++, pBox++) - { - pRects[i].x = pBox->x1; - pRects[i].y = pBox->y1 - imageBox.y1; - pRects[i].width = pBox->x2 - pBox->x1; - pRects[i].height = pBox->y2 - pBox->y1; - } - - /* use pBuf as a fake pixmap */ - - if (format == ZPixmap) - { - depth = pDraw->depth; - bitsPerPixel = pDraw->bitsPerPixel; - } - - pPix = GetScratchPixmapHeader(pDraw->pScreen, w, h, - depth, bitsPerPixel, - widthBytesLine, (pointer)pBuf); - if (!pPix) - { - failed = TRUE; - goto failSafe; - } - - pScratchGC = GetScratchGC(depth, pPix->drawable.pScreen); - if (!pScratchGC) - { - failed = TRUE; - goto failSafe; - } - - ValidateGC(&pPix->drawable, pScratchGC); - (* pScratchGC->ops->PolyFillRect)(&pPix->drawable, - pScratchGC, nRects, pRects); - - failSafe: - if (failed) - { - /* Censoring was not completed above. To be safe, wipe out - * all the image data so that nothing trusted gets out. - */ - bzero(pBuf, (int)(widthBytesLine * h)); - } - if (pRects) xfree(pRects); - if (pScratchGC) FreeScratchGC(pScratchGC); - if (pPix) FreeScratchPixmapHeader(pPix); - } - REGION_UNINIT(pScreen, &imageRegion); - REGION_UNINIT(pScreen, &censorRegion); -} /* XaceCensorImage */ - -/* - * Xtrans wrappers for use by modules - */ -int XaceGetConnectionNumber(ClientPtr client) -{ - XtransConnInfo ci = ((OsCommPtr)client->osPrivate)->trans_conn; - return _XSERVTransGetConnectionNumber(ci); -} - -int XaceIsLocal(ClientPtr client) -{ - XtransConnInfo ci = ((OsCommPtr)client->osPrivate)->trans_conn; - return _XSERVTransIsLocal(ci); -} +/************************************************************ + +Author: Eamon Walsh + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +this permission notice appear in supporting documentation. 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 +AUTHOR 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 +#endif + +#include +#include "scrnintstr.h" +#include "extnsionst.h" +#include "pixmapstr.h" +#include "regionstr.h" +#include "gcstruct.h" +#include "xacestr.h" + +#define XSERV_t +#define TRANS_SERVER +#include +#include "../os/osdep.h" + +_X_EXPORT CallbackListPtr XaceHooks[XACE_NUM_HOOKS] = {0}; + +/* Special-cased hook functions. Called by Xserver. + */ +int XaceHookDispatch(ClientPtr client, int major) +{ + /* Call the audit begin callback, there is no return value. */ + XaceAuditRec rec = { client, 0 }; + CallCallbacks(&XaceHooks[XACE_AUDIT_BEGIN], &rec); + + if (major < 128) { + /* Call the core dispatch hook */ + XaceCoreDispatchRec rec = { client, Success /* default allow */ }; + CallCallbacks(&XaceHooks[XACE_CORE_DISPATCH], &rec); + return rec.status; + } else { + /* Call the extension dispatch hook */ + ExtensionEntry *ext = GetExtensionEntry(major); + XaceExtAccessRec rec = { client, ext, DixUseAccess, Success }; + if (ext) + CallCallbacks(&XaceHooks[XACE_EXT_DISPATCH], &rec); + /* On error, pretend extension doesn't exist */ + return (rec.status == Success) ? Success : BadRequest; + } +} + +int XaceHookPropertyAccess(ClientPtr client, WindowPtr pWin, + PropertyPtr *ppProp, Mask access_mode) +{ + XacePropertyAccessRec rec = { client, pWin, ppProp, access_mode, Success }; + CallCallbacks(&XaceHooks[XACE_PROPERTY_ACCESS], &rec); + return rec.status; +} + +int XaceHookSelectionAccess(ClientPtr client, + Selection **ppSel, Mask access_mode) +{ + XaceSelectionAccessRec rec = { client, ppSel, access_mode, Success }; + CallCallbacks(&XaceHooks[XACE_SELECTION_ACCESS], &rec); + return rec.status; +} + +void XaceHookAuditEnd(ClientPtr ptr, int result) +{ + XaceAuditRec rec = { ptr, result }; + /* call callbacks, there is no return value. */ + CallCallbacks(&XaceHooks[XACE_AUDIT_END], &rec); +} + +/* Entry point for hook functions. Called by Xserver. + */ +int XaceHook(int hook, ...) +{ + pointer calldata; /* data passed to callback */ + int *prv = NULL; /* points to return value from callback */ + va_list ap; /* argument list */ + va_start(ap, hook); + + /* Marshal arguments for passing to callback. + * Each callback has its own case, which sets up a structure to hold + * the arguments and integer return parameter, or in some cases just + * sets calldata directly to a single argument (with no return result) + */ + switch (hook) + { + case XACE_RESOURCE_ACCESS: { + XaceResourceAccessRec rec; + rec.client = va_arg(ap, ClientPtr); + rec.id = va_arg(ap, XID); + rec.rtype = va_arg(ap, RESTYPE); + rec.res = va_arg(ap, pointer); + rec.ptype = va_arg(ap, RESTYPE); + rec.parent = va_arg(ap, pointer); + rec.access_mode = va_arg(ap, Mask); + rec.status = Success; /* default allow */ + calldata = &rec; + prv = &rec.status; + break; + } + case XACE_DEVICE_ACCESS: { + XaceDeviceAccessRec rec; + rec.client = va_arg(ap, ClientPtr); + rec.dev = va_arg(ap, DeviceIntPtr); + rec.access_mode = va_arg(ap, Mask); + rec.status = Success; /* default allow */ + calldata = &rec; + prv = &rec.status; + break; + } + case XACE_SEND_ACCESS: { + XaceSendAccessRec rec; + rec.client = va_arg(ap, ClientPtr); + rec.dev = va_arg(ap, DeviceIntPtr); + rec.pWin = va_arg(ap, WindowPtr); + rec.events = va_arg(ap, xEventPtr); + rec.count = va_arg(ap, int); + rec.status = Success; /* default allow */ + calldata = &rec; + prv = &rec.status; + break; + } + case XACE_RECEIVE_ACCESS: { + XaceReceiveAccessRec rec; + rec.client = va_arg(ap, ClientPtr); + rec.pWin = va_arg(ap, WindowPtr); + rec.events = va_arg(ap, xEventPtr); + rec.count = va_arg(ap, int); + rec.status = Success; /* default allow */ + calldata = &rec; + prv = &rec.status; + break; + } + case XACE_CLIENT_ACCESS: { + XaceClientAccessRec rec; + rec.client = va_arg(ap, ClientPtr); + rec.target = va_arg(ap, ClientPtr); + rec.access_mode = va_arg(ap, Mask); + rec.status = Success; /* default allow */ + calldata = &rec; + prv = &rec.status; + break; + } + case XACE_EXT_ACCESS: { + XaceExtAccessRec rec; + rec.client = va_arg(ap, ClientPtr); + rec.ext = va_arg(ap, ExtensionEntry*); + rec.access_mode = DixGetAttrAccess; + rec.status = Success; /* default allow */ + calldata = &rec; + prv = &rec.status; + break; + } + case XACE_SERVER_ACCESS: { + XaceServerAccessRec rec; + rec.client = va_arg(ap, ClientPtr); + rec.access_mode = va_arg(ap, Mask); + rec.status = Success; /* default allow */ + calldata = &rec; + prv = &rec.status; + break; + } + case XACE_SCREEN_ACCESS: + case XACE_SCREENSAVER_ACCESS: { + XaceScreenAccessRec rec; + rec.client = va_arg(ap, ClientPtr); + rec.screen = va_arg(ap, ScreenPtr); + rec.access_mode = va_arg(ap, Mask); + rec.status = Success; /* default allow */ + calldata = &rec; + prv = &rec.status; + break; + } + case XACE_AUTH_AVAIL: { + XaceAuthAvailRec rec; + rec.client = va_arg(ap, ClientPtr); + rec.authId = va_arg(ap, XID); + calldata = &rec; + break; + } + case XACE_KEY_AVAIL: { + XaceKeyAvailRec rec; + rec.event = va_arg(ap, xEventPtr); + rec.keybd = va_arg(ap, DeviceIntPtr); + rec.count = va_arg(ap, int); + calldata = &rec; + break; + } + default: { + va_end(ap); + return 0; /* unimplemented hook number */ + } + } + va_end(ap); + + /* call callbacks and return result, if any. */ + CallCallbacks(&XaceHooks[hook], calldata); + return prv ? *prv : Success; +} + +/* XaceCensorImage + * + * Called after pScreen->GetImage to prevent pieces or trusted windows from + * being returned in image data from an untrusted window. + * + * Arguments: + * client is the client doing the GetImage. + * pVisibleRegion is the visible region of the window. + * widthBytesLine is the width in bytes of one horizontal line in pBuf. + * pDraw is the source window. + * x, y, w, h is the rectangle of image data from pDraw in pBuf. + * format is the format of the image data in pBuf: ZPixmap or XYPixmap. + * pBuf is the image data. + * + * Returns: nothing. + * + * Side Effects: + * Any part of the rectangle (x, y, w, h) that is outside the visible + * region of the window will be destroyed (overwritten) in pBuf. + */ +void +XaceCensorImage( + ClientPtr client, + RegionPtr pVisibleRegion, + long widthBytesLine, + DrawablePtr pDraw, + int x, int y, int w, int h, + unsigned int format, + char *pBuf) +{ + ScreenPtr pScreen; + RegionRec imageRegion; /* region representing x,y,w,h */ + RegionRec censorRegion; /* region to obliterate */ + BoxRec imageBox; + int nRects; + + pScreen = pDraw->pScreen; + + imageBox.x1 = x; + imageBox.y1 = y; + imageBox.x2 = x + w; + imageBox.y2 = y + h; + REGION_INIT(pScreen, &imageRegion, &imageBox, 1); + REGION_NULL(pScreen, &censorRegion); + + /* censorRegion = imageRegion - visibleRegion */ + REGION_SUBTRACT(pScreen, &censorRegion, &imageRegion, pVisibleRegion); + nRects = REGION_NUM_RECTS(&censorRegion); + if (nRects > 0) + { /* we have something to censor */ + GCPtr pScratchGC = NULL; + PixmapPtr pPix = NULL; + xRectangle *pRects = NULL; + Bool failed = FALSE; + int depth = 1; + int bitsPerPixel = 1; + int i; + BoxPtr pBox; + + /* convert region to list-of-rectangles for PolyFillRect */ + + pRects = malloc(nRects * sizeof(xRectangle)); + if (!pRects) + { + failed = TRUE; + goto failSafe; + } + for (pBox = REGION_RECTS(&censorRegion), i = 0; + i < nRects; + i++, pBox++) + { + pRects[i].x = pBox->x1; + pRects[i].y = pBox->y1 - imageBox.y1; + pRects[i].width = pBox->x2 - pBox->x1; + pRects[i].height = pBox->y2 - pBox->y1; + } + + /* use pBuf as a fake pixmap */ + + if (format == ZPixmap) + { + depth = pDraw->depth; + bitsPerPixel = pDraw->bitsPerPixel; + } + + pPix = GetScratchPixmapHeader(pDraw->pScreen, w, h, + depth, bitsPerPixel, + widthBytesLine, (pointer)pBuf); + if (!pPix) + { + failed = TRUE; + goto failSafe; + } + + pScratchGC = GetScratchGC(depth, pPix->drawable.pScreen); + if (!pScratchGC) + { + failed = TRUE; + goto failSafe; + } + + ValidateGC(&pPix->drawable, pScratchGC); + (* pScratchGC->ops->PolyFillRect)(&pPix->drawable, + pScratchGC, nRects, pRects); + + failSafe: + if (failed) + { + /* Censoring was not completed above. To be safe, wipe out + * all the image data so that nothing trusted gets out. + */ + bzero(pBuf, (int)(widthBytesLine * h)); + } + if (pRects) free(pRects); + if (pScratchGC) FreeScratchGC(pScratchGC); + if (pPix) FreeScratchPixmapHeader(pPix); + } + REGION_UNINIT(pScreen, &imageRegion); + REGION_UNINIT(pScreen, &censorRegion); +} /* XaceCensorImage */ + +/* + * Xtrans wrappers for use by modules + */ +int XaceGetConnectionNumber(ClientPtr client) +{ + XtransConnInfo ci = ((OsCommPtr)client->osPrivate)->trans_conn; + return _XSERVTransGetConnectionNumber(ci); +} + +int XaceIsLocal(ClientPtr client) +{ + XtransConnInfo ci = ((OsCommPtr)client->osPrivate)->trans_conn; + return _XSERVTransIsLocal(ci); +} diff --git a/xorg-server/Xext/xcalibrate.c b/xorg-server/Xext/xcalibrate.c index 6e6461a5f..029154fa0 100644 --- a/xorg-server/Xext/xcalibrate.c +++ b/xorg-server/Xext/xcalibrate.c @@ -1,299 +1,299 @@ -/* - * Copyright © 2003 Philip Blundell - * - * 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, and that the name of Philip Blundell not be used in - * advertising or publicity pertaining to distribution of the software without - * specific, written prior permission. Philip Blundell makes no - * representations about the suitability of this software for any purpose. It - * is provided "as is" without express or implied warranty. - * - * PHILIP BLUNDELL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, - * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO - * EVENT SHALL PHILIP BLUNDELL 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. - */ - -#ifdef HAVE_KDRIVE_CONFIG_H -#include -#endif - - -#include -#include -#include "misc.h" -#include "os.h" -#include "dixstruct.h" -#include "extnsionst.h" -#include "swaprep.h" -#include "protocol-versions.h" - -#include -#include - -extern void (*tslib_raw_event_hook)(int x, int y, int pressure, void *closure); -extern void *tslib_raw_event_closure; - -static CARD8 XCalibrateReqCode; -int XCalibrateEventBase; -int XCalibrateReqBase; -int XCalibrateErrorBase; - -static ClientPtr xcalibrate_client; - -static void -xcalibrate_event_hook (int x, int y, int pressure, void *closure) -{ - ClientPtr pClient = (ClientPtr) closure; - xXCalibrateRawTouchscreenEvent ev; - - ev.type = XCalibrateEventBase + X_XCalibrateRawTouchscreen; - ev.sequenceNumber = pClient->sequence; - ev.x = x; - ev.y = y; - ev.pressure = pressure; - - if (!pClient->clientGone) - WriteEventsToClient (pClient, 1, (xEvent *) &ev); -} - -static int -ProcXCalibrateQueryVersion (ClientPtr client) -{ - REQUEST(xXCalibrateQueryVersionReq); - xXCalibrateQueryVersionReply rep; - CARD16 client_major, client_minor; /* not used */ - - REQUEST_SIZE_MATCH (xXCalibrateQueryVersionReq); - - client_major = stuff->majorVersion; - client_minor = stuff->minorVersion; - - fprintf(stderr, "%s(): called\n", __func__); - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.majorVersion = SERVER_XCALIBRATE_MAJOR_VERSION; - rep.minorVersion = SERVER_XCALIBRATE_MINOR_VERSION; - if (client->swapped) { - int n; - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swaps(&rep.majorVersion, n); - swaps(&rep.minorVersion, n); - } - WriteToClient(client, sizeof (xXCalibrateQueryVersionReply), (char *)&rep); - return (client->noClientException); -} - -static int -SProcXCalibrateQueryVersion (ClientPtr client) -{ - REQUEST(xXCalibrateQueryVersionReq); - int n; - - REQUEST_SIZE_MATCH (xXCalibrateQueryVersionReq); - swaps(&stuff->majorVersion,n); - swaps(&stuff->minorVersion,n); - return ProcXCalibrateQueryVersion(client); -} - -static int -ProcXCalibrateSetRawMode (ClientPtr client) -{ - REQUEST(xXCalibrateRawModeReq); - xXCalibrateRawModeReply rep; - - REQUEST_SIZE_MATCH (xXCalibrateRawModeReq); - - memset (&rep, 0, sizeof (rep)); - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - - if (stuff->on) - { - if (xcalibrate_client == NULL) - { - /* Start calibrating. */ - xcalibrate_client = client; - tslib_raw_event_hook = xcalibrate_event_hook; - tslib_raw_event_closure = client; - rep.status = GrabSuccess; - } - else - { - rep.status = AlreadyGrabbed; - } - } - else - { - if (xcalibrate_client == client) - { - /* Stop calibrating. */ - xcalibrate_client = NULL; - tslib_raw_event_hook = NULL; - tslib_raw_event_closure = NULL; - rep.status = GrabSuccess; - - /* Cycle input off and on to reload configuration. */ - KdDisableInput (); - KdEnableInput (); - } - else - { - rep.status = AlreadyGrabbed; - } - } - - if (client->swapped) - { - int n; - - swaps (&rep.sequenceNumber, n); - swaps (&rep.status, n); - } - WriteToClient(client, sizeof (rep), (char *) &rep); - return (client->noClientException); -} - -static int -SProcXCalibrateSetRawMode (ClientPtr client) -{ - REQUEST(xXCalibrateRawModeReq); - int n; - - REQUEST_SIZE_MATCH (xXCalibrateRawModeReq); - - swaps(&stuff->on, n); - - return ProcXCalibrateSetRawMode(client); -} - -static int -ProcXCalibrateScreenToCoord (ClientPtr client) -{ - REQUEST(xXCalibrateScreenToCoordReq); - xXCalibrateScreenToCoordReply rep; - - REQUEST_SIZE_MATCH (xXCalibrateScreenToCoordReq); - - memset (&rep, 0, sizeof (rep)); - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.x = stuff->x; - rep.y = stuff->y; - - KdScreenToPointerCoords(&rep.x, &rep.y); - - if (client->swapped) - { - int n; - - swaps (&rep.x, n); - swaps (&rep.y, n); - } - WriteToClient(client, sizeof (rep), (char *) &rep); - return (client->noClientException); -} - -static int -SProcXCalibrateScreenToCoord (ClientPtr client) -{ - REQUEST(xXCalibrateScreenToCoordReq); - int n; - - REQUEST_SIZE_MATCH (xXCalibrateScreenToCoordReq); - - swaps(&stuff->x, n); - swaps(&stuff->y, n); - - return ProcXCalibrateScreenToCoord(client); -} - -static int -ProcXCalibrateDispatch (ClientPtr client) -{ - REQUEST(xReq); - switch (stuff->data) { - case X_XCalibrateQueryVersion: - return ProcXCalibrateQueryVersion(client); - case X_XCalibrateRawMode: - return ProcXCalibrateSetRawMode(client); - case X_XCalibrateScreenToCoord: - return ProcXCalibrateScreenToCoord(client); - - default: break; - } - - return BadRequest; -} - -static int -SProcXCalibrateDispatch (ClientPtr client) -{ - REQUEST(xReq); - int n; - - swaps(&stuff->length,n); - - switch (stuff->data) { - case X_XCalibrateQueryVersion: - return SProcXCalibrateQueryVersion(client); - case X_XCalibrateRawMode: - return SProcXCalibrateSetRawMode(client); - case X_XCalibrateScreenToCoord: - return SProcXCalibrateScreenToCoord(client); - - default: break; - } - - return BadRequest; -} - -static void -XCalibrateClientCallback (CallbackListPtr *list, - pointer closure, - pointer data) -{ - NewClientInfoRec *clientinfo = (NewClientInfoRec *) data; - ClientPtr pClient = clientinfo->client; - - if (clientinfo->setup == NULL - && xcalibrate_client != NULL - && xcalibrate_client == pClient) - { - /* Stop calibrating. */ - xcalibrate_client = NULL; - tslib_raw_event_hook = NULL; - tslib_raw_event_closure = NULL; - } -} - -void -XCalibrateExtensionInit(void) -{ - ExtensionEntry *extEntry; - - if (!AddCallback (&ClientStateCallback, XCalibrateClientCallback, 0)) - return; - - extEntry = AddExtension(XCALIBRATE_NAME, XCalibrateNumberEvents, XCalibrateNumberErrors, - ProcXCalibrateDispatch, SProcXCalibrateDispatch, - NULL, StandardMinorOpcode); - - if (!extEntry) - return; - - XCalibrateReqCode = (unsigned char)extEntry->base; - XCalibrateEventBase = extEntry->eventBase; - XCalibrateErrorBase = extEntry->errorBase; - - xcalibrate_client = 0; -} +/* + * Copyright © 2003 Philip Blundell + * + * 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, and that the name of Philip Blundell not be used in + * advertising or publicity pertaining to distribution of the software without + * specific, written prior permission. Philip Blundell makes no + * representations about the suitability of this software for any purpose. It + * is provided "as is" without express or implied warranty. + * + * PHILIP BLUNDELL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, + * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO + * EVENT SHALL PHILIP BLUNDELL 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. + */ + +#ifdef HAVE_KDRIVE_CONFIG_H +#include +#endif + + +#include +#include +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "swaprep.h" +#include "protocol-versions.h" + +#include +#include + +extern void (*tslib_raw_event_hook)(int x, int y, int pressure, void *closure); +extern void *tslib_raw_event_closure; + +static CARD8 XCalibrateReqCode; +int XCalibrateEventBase; +int XCalibrateReqBase; +int XCalibrateErrorBase; + +static ClientPtr xcalibrate_client; + +static void +xcalibrate_event_hook (int x, int y, int pressure, void *closure) +{ + ClientPtr pClient = (ClientPtr) closure; + xXCalibrateRawTouchscreenEvent ev; + + ev.type = XCalibrateEventBase + X_XCalibrateRawTouchscreen; + ev.sequenceNumber = pClient->sequence; + ev.x = x; + ev.y = y; + ev.pressure = pressure; + + if (!pClient->clientGone) + WriteEventsToClient (pClient, 1, (xEvent *) &ev); +} + +static int +ProcXCalibrateQueryVersion (ClientPtr client) +{ + REQUEST(xXCalibrateQueryVersionReq); + xXCalibrateQueryVersionReply rep; + CARD16 client_major, client_minor; /* not used */ + + REQUEST_SIZE_MATCH (xXCalibrateQueryVersionReq); + + client_major = stuff->majorVersion; + client_minor = stuff->minorVersion; + + fprintf(stderr, "%s(): called\n", __func__); + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = SERVER_XCALIBRATE_MAJOR_VERSION; + rep.minorVersion = SERVER_XCALIBRATE_MINOR_VERSION; + if (client->swapped) { + int n; + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.majorVersion, n); + swaps(&rep.minorVersion, n); + } + WriteToClient(client, sizeof (xXCalibrateQueryVersionReply), (char *)&rep); + return Success; +} + +static int +SProcXCalibrateQueryVersion (ClientPtr client) +{ + REQUEST(xXCalibrateQueryVersionReq); + int n; + + REQUEST_SIZE_MATCH (xXCalibrateQueryVersionReq); + swaps(&stuff->majorVersion,n); + swaps(&stuff->minorVersion,n); + return ProcXCalibrateQueryVersion(client); +} + +static int +ProcXCalibrateSetRawMode (ClientPtr client) +{ + REQUEST(xXCalibrateRawModeReq); + xXCalibrateRawModeReply rep; + + REQUEST_SIZE_MATCH (xXCalibrateRawModeReq); + + memset (&rep, 0, sizeof (rep)); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + + if (stuff->on) + { + if (xcalibrate_client == NULL) + { + /* Start calibrating. */ + xcalibrate_client = client; + tslib_raw_event_hook = xcalibrate_event_hook; + tslib_raw_event_closure = client; + rep.status = GrabSuccess; + } + else + { + rep.status = AlreadyGrabbed; + } + } + else + { + if (xcalibrate_client == client) + { + /* Stop calibrating. */ + xcalibrate_client = NULL; + tslib_raw_event_hook = NULL; + tslib_raw_event_closure = NULL; + rep.status = GrabSuccess; + + /* Cycle input off and on to reload configuration. */ + KdDisableInput (); + KdEnableInput (); + } + else + { + rep.status = AlreadyGrabbed; + } + } + + if (client->swapped) + { + int n; + + swaps (&rep.sequenceNumber, n); + swaps (&rep.status, n); + } + WriteToClient(client, sizeof (rep), (char *) &rep); + return Success; +} + +static int +SProcXCalibrateSetRawMode (ClientPtr client) +{ + REQUEST(xXCalibrateRawModeReq); + int n; + + REQUEST_SIZE_MATCH (xXCalibrateRawModeReq); + + swaps(&stuff->on, n); + + return ProcXCalibrateSetRawMode(client); +} + +static int +ProcXCalibrateScreenToCoord (ClientPtr client) +{ + REQUEST(xXCalibrateScreenToCoordReq); + xXCalibrateScreenToCoordReply rep; + + REQUEST_SIZE_MATCH (xXCalibrateScreenToCoordReq); + + memset (&rep, 0, sizeof (rep)); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.x = stuff->x; + rep.y = stuff->y; + + KdScreenToPointerCoords(&rep.x, &rep.y); + + if (client->swapped) + { + int n; + + swaps (&rep.x, n); + swaps (&rep.y, n); + } + WriteToClient(client, sizeof (rep), (char *) &rep); + return Success; +} + +static int +SProcXCalibrateScreenToCoord (ClientPtr client) +{ + REQUEST(xXCalibrateScreenToCoordReq); + int n; + + REQUEST_SIZE_MATCH (xXCalibrateScreenToCoordReq); + + swaps(&stuff->x, n); + swaps(&stuff->y, n); + + return ProcXCalibrateScreenToCoord(client); +} + +static int +ProcXCalibrateDispatch (ClientPtr client) +{ + REQUEST(xReq); + switch (stuff->data) { + case X_XCalibrateQueryVersion: + return ProcXCalibrateQueryVersion(client); + case X_XCalibrateRawMode: + return ProcXCalibrateSetRawMode(client); + case X_XCalibrateScreenToCoord: + return ProcXCalibrateScreenToCoord(client); + + default: break; + } + + return BadRequest; +} + +static int +SProcXCalibrateDispatch (ClientPtr client) +{ + REQUEST(xReq); + int n; + + swaps(&stuff->length,n); + + switch (stuff->data) { + case X_XCalibrateQueryVersion: + return SProcXCalibrateQueryVersion(client); + case X_XCalibrateRawMode: + return SProcXCalibrateSetRawMode(client); + case X_XCalibrateScreenToCoord: + return SProcXCalibrateScreenToCoord(client); + + default: break; + } + + return BadRequest; +} + +static void +XCalibrateClientCallback (CallbackListPtr *list, + pointer closure, + pointer data) +{ + NewClientInfoRec *clientinfo = (NewClientInfoRec *) data; + ClientPtr pClient = clientinfo->client; + + if (clientinfo->setup == NULL + && xcalibrate_client != NULL + && xcalibrate_client == pClient) + { + /* Stop calibrating. */ + xcalibrate_client = NULL; + tslib_raw_event_hook = NULL; + tslib_raw_event_closure = NULL; + } +} + +void +XCalibrateExtensionInit(void) +{ + ExtensionEntry *extEntry; + + if (!AddCallback (&ClientStateCallback, XCalibrateClientCallback, 0)) + return; + + extEntry = AddExtension(XCALIBRATE_NAME, XCalibrateNumberEvents, XCalibrateNumberErrors, + ProcXCalibrateDispatch, SProcXCalibrateDispatch, + NULL, StandardMinorOpcode); + + if (!extEntry) + return; + + XCalibrateReqCode = (unsigned char)extEntry->base; + XCalibrateEventBase = extEntry->eventBase; + XCalibrateErrorBase = extEntry->errorBase; + + xcalibrate_client = 0; +} diff --git a/xorg-server/Xext/xcmisc.c b/xorg-server/Xext/xcmisc.c index 39079a294..625351f51 100644 --- a/xorg-server/Xext/xcmisc.c +++ b/xorg-server/Xext/xcmisc.c @@ -1,217 +1,217 @@ -/* - -Copyright 1993, 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. - -*/ - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include -#include -#include "misc.h" -#include "os.h" -#include "dixstruct.h" -#include "extnsionst.h" -#include "swaprep.h" -#include -#include "modinit.h" - -#if HAVE_STDINT_H -#include -#elif !defined(UINT32_MAX) -#define UINT32_MAX 0xffffffffU -#endif - -static DISPATCH_PROC(ProcXCMiscDispatch); -static DISPATCH_PROC(ProcXCMiscGetVersion); -static DISPATCH_PROC(ProcXCMiscGetXIDList); -static DISPATCH_PROC(ProcXCMiscGetXIDRange); -static DISPATCH_PROC(SProcXCMiscDispatch); -static DISPATCH_PROC(SProcXCMiscGetVersion); -static DISPATCH_PROC(SProcXCMiscGetXIDList); -static DISPATCH_PROC(SProcXCMiscGetXIDRange); - -void XCMiscExtensionInit(INITARGS); - -void -XCMiscExtensionInit(INITARGS) -{ - AddExtension(XCMiscExtensionName, 0, 0, - ProcXCMiscDispatch, SProcXCMiscDispatch, - NULL, StandardMinorOpcode); -} - -static int -ProcXCMiscGetVersion(ClientPtr client) -{ - xXCMiscGetVersionReply rep; - int n; - - REQUEST_SIZE_MATCH(xXCMiscGetVersionReq); - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.majorVersion = XCMiscMajorVersion; - rep.minorVersion = XCMiscMinorVersion; - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - swaps(&rep.majorVersion, n); - swaps(&rep.minorVersion, n); - } - WriteToClient(client, sizeof(xXCMiscGetVersionReply), (char *)&rep); - return(client->noClientException); -} - -static int -ProcXCMiscGetXIDRange(ClientPtr client) -{ - xXCMiscGetXIDRangeReply rep; - int n; - XID min_id, max_id; - - REQUEST_SIZE_MATCH(xXCMiscGetXIDRangeReq); - GetXIDRange(client->index, FALSE, &min_id, &max_id); - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.start_id = min_id; - rep.count = max_id - min_id + 1; - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.start_id, n); - swapl(&rep.count, n); - } - WriteToClient(client, sizeof(xXCMiscGetXIDRangeReply), (char *)&rep); - return(client->noClientException); -} - -static int -ProcXCMiscGetXIDList(ClientPtr client) -{ - REQUEST(xXCMiscGetXIDListReq); - xXCMiscGetXIDListReply rep; - int n; - XID *pids; - unsigned int count; - - REQUEST_SIZE_MATCH(xXCMiscGetXIDListReq); - - if (stuff->count > UINT32_MAX / sizeof(XID)) - return BadAlloc; - - pids = (XID *)Xalloc(stuff->count * sizeof(XID)); - if (!pids) - { - return BadAlloc; - } - count = GetXIDList(client, stuff->count, pids); - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.length = count; - rep.count = count; - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swapl(&rep.count, n); - } - WriteToClient(client, sizeof(xXCMiscGetXIDListReply), (char *)&rep); - if (count) - { - client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; - WriteSwappedDataToClient(client, count * sizeof(XID), pids); - } - Xfree(pids); - return(client->noClientException); -} - -static int -ProcXCMiscDispatch (ClientPtr client) -{ - REQUEST(xReq); - switch (stuff->data) - { - case X_XCMiscGetVersion: - return ProcXCMiscGetVersion(client); - case X_XCMiscGetXIDRange: - return ProcXCMiscGetXIDRange(client); - case X_XCMiscGetXIDList: - return ProcXCMiscGetXIDList(client); - default: - return BadRequest; - } -} - -static int -SProcXCMiscGetVersion(ClientPtr client) -{ - int n; - REQUEST(xXCMiscGetVersionReq); - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH(xXCMiscGetVersionReq); - swaps(&stuff->majorVersion, n); - swaps(&stuff->minorVersion, n); - return ProcXCMiscGetVersion(client); -} - -static int -SProcXCMiscGetXIDRange(ClientPtr client) -{ - int n; - REQUEST(xReq); - - swaps(&stuff->length, n); - return ProcXCMiscGetXIDRange(client); -} - -static int -SProcXCMiscGetXIDList(ClientPtr client) -{ - int n; - REQUEST(xXCMiscGetXIDListReq); - - swaps(&stuff->length, n); - swapl(&stuff->count, n); - return ProcXCMiscGetXIDList(client); -} - -static int -SProcXCMiscDispatch (ClientPtr client) -{ - REQUEST(xReq); - switch (stuff->data) - { - case X_XCMiscGetVersion: - return SProcXCMiscGetVersion(client); - case X_XCMiscGetXIDRange: - return SProcXCMiscGetXIDRange(client); - case X_XCMiscGetXIDList: - return SProcXCMiscGetXIDList(client); - default: - return BadRequest; - } -} +/* + +Copyright 1993, 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. + +*/ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "swaprep.h" +#include +#include "modinit.h" + +#if HAVE_STDINT_H +#include +#elif !defined(UINT32_MAX) +#define UINT32_MAX 0xffffffffU +#endif + +static DISPATCH_PROC(ProcXCMiscDispatch); +static DISPATCH_PROC(ProcXCMiscGetVersion); +static DISPATCH_PROC(ProcXCMiscGetXIDList); +static DISPATCH_PROC(ProcXCMiscGetXIDRange); +static DISPATCH_PROC(SProcXCMiscDispatch); +static DISPATCH_PROC(SProcXCMiscGetVersion); +static DISPATCH_PROC(SProcXCMiscGetXIDList); +static DISPATCH_PROC(SProcXCMiscGetXIDRange); + +void XCMiscExtensionInit(INITARGS); + +void +XCMiscExtensionInit(INITARGS) +{ + AddExtension(XCMiscExtensionName, 0, 0, + ProcXCMiscDispatch, SProcXCMiscDispatch, + NULL, StandardMinorOpcode); +} + +static int +ProcXCMiscGetVersion(ClientPtr client) +{ + xXCMiscGetVersionReply rep; + int n; + + REQUEST_SIZE_MATCH(xXCMiscGetVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = XCMiscMajorVersion; + rep.minorVersion = XCMiscMinorVersion; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swaps(&rep.majorVersion, n); + swaps(&rep.minorVersion, n); + } + WriteToClient(client, sizeof(xXCMiscGetVersionReply), (char *)&rep); + return Success; +} + +static int +ProcXCMiscGetXIDRange(ClientPtr client) +{ + xXCMiscGetXIDRangeReply rep; + int n; + XID min_id, max_id; + + REQUEST_SIZE_MATCH(xXCMiscGetXIDRangeReq); + GetXIDRange(client->index, FALSE, &min_id, &max_id); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.start_id = min_id; + rep.count = max_id - min_id + 1; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.start_id, n); + swapl(&rep.count, n); + } + WriteToClient(client, sizeof(xXCMiscGetXIDRangeReply), (char *)&rep); + return Success; +} + +static int +ProcXCMiscGetXIDList(ClientPtr client) +{ + REQUEST(xXCMiscGetXIDListReq); + xXCMiscGetXIDListReply rep; + int n; + XID *pids; + unsigned int count; + + REQUEST_SIZE_MATCH(xXCMiscGetXIDListReq); + + if (stuff->count > UINT32_MAX / sizeof(XID)) + return BadAlloc; + + pids = (XID *)malloc(stuff->count * sizeof(XID)); + if (!pids) + { + return BadAlloc; + } + count = GetXIDList(client, stuff->count, pids); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = count; + rep.count = count; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swapl(&rep.count, n); + } + WriteToClient(client, sizeof(xXCMiscGetXIDListReply), (char *)&rep); + if (count) + { + client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; + WriteSwappedDataToClient(client, count * sizeof(XID), pids); + } + free(pids); + return Success; +} + +static int +ProcXCMiscDispatch (ClientPtr client) +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_XCMiscGetVersion: + return ProcXCMiscGetVersion(client); + case X_XCMiscGetXIDRange: + return ProcXCMiscGetXIDRange(client); + case X_XCMiscGetXIDList: + return ProcXCMiscGetXIDList(client); + default: + return BadRequest; + } +} + +static int +SProcXCMiscGetVersion(ClientPtr client) +{ + int n; + REQUEST(xXCMiscGetVersionReq); + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXCMiscGetVersionReq); + swaps(&stuff->majorVersion, n); + swaps(&stuff->minorVersion, n); + return ProcXCMiscGetVersion(client); +} + +static int +SProcXCMiscGetXIDRange(ClientPtr client) +{ + int n; + REQUEST(xReq); + + swaps(&stuff->length, n); + return ProcXCMiscGetXIDRange(client); +} + +static int +SProcXCMiscGetXIDList(ClientPtr client) +{ + int n; + REQUEST(xXCMiscGetXIDListReq); + + swaps(&stuff->length, n); + swapl(&stuff->count, n); + return ProcXCMiscGetXIDList(client); +} + +static int +SProcXCMiscDispatch (ClientPtr client) +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_XCMiscGetVersion: + return SProcXCMiscGetVersion(client); + case X_XCMiscGetXIDRange: + return SProcXCMiscGetXIDRange(client); + case X_XCMiscGetXIDList: + return SProcXCMiscGetXIDList(client); + default: + return BadRequest; + } +} diff --git a/xorg-server/Xext/xf86bigfont.c b/xorg-server/Xext/xf86bigfont.c index 8e8d460e5..8d7071507 100644 --- a/xorg-server/Xext/xf86bigfont.c +++ b/xorg-server/Xext/xf86bigfont.c @@ -230,7 +230,7 @@ shmalloc( if (size < 3500) return (ShmDescPtr) NULL; - pDesc = xalloc(sizeof(ShmDescRec)); + pDesc = malloc(sizeof(ShmDescRec)); if (!pDesc) return (ShmDescPtr) NULL; @@ -239,7 +239,7 @@ shmalloc( if (shmid == -1) { ErrorF(XF86BIGFONTNAME " extension: shmget() failed, size = %u, %s\n", size, strerror(errno)); - xfree(pDesc); + free(pDesc); return (ShmDescPtr) NULL; } @@ -247,7 +247,7 @@ shmalloc( ErrorF(XF86BIGFONTNAME " extension: shmat() failed, size = %u, %s\n", size, strerror(errno)); shmctl(shmid, IPC_RMID, (void *) 0); - xfree(pDesc); + free(pDesc); return (ShmDescPtr) NULL; } @@ -276,7 +276,7 @@ shmdealloc( if (pDesc->next) pDesc->next->prev = pDesc->prev; *pDesc->prev = pDesc->next; - xfree(pDesc); + free(pDesc); } #endif @@ -368,7 +368,7 @@ ProcXF86BigfontQueryVersion( } WriteToClient(client, sizeof(xXF86BigfontQueryVersionReply), (char *)&reply); - return client->noClientException; + return Success; } static void @@ -464,7 +464,7 @@ ProcXF86BigfontQueryFont( shmid = pDesc->shmid; } else { #endif - pCI = xalloc(nCharInfos * sizeof(xCharInfo)); + pCI = malloc(nCharInfos * sizeof(xCharInfo)); if (!pCI) return BadAlloc; #ifdef HAS_SHM @@ -526,9 +526,9 @@ ProcXF86BigfontQueryFont( if (hashModulus > nCharInfos+1) hashModulus = nCharInfos+1; - tmp = xalloc((4*nCharInfos+1) * sizeof(CARD16)); + tmp = malloc((4*nCharInfos+1) * sizeof(CARD16)); if (!tmp) { - if (!pDesc) xfree(pCI); + if (!pDesc) free(pCI); return BadAlloc; } pIndex2UniqIndex = tmp; @@ -610,12 +610,12 @@ ProcXF86BigfontQueryFont( ? nUniqCharInfos * sizeof(xCharInfo) + (nCharInfos+1)/2 * 2 * sizeof(CARD16) : 0); - xXF86BigfontQueryFontReply* reply = xalloc(rlength); + xXF86BigfontQueryFontReply* reply = malloc(rlength); char* p; if (!reply) { if (nCharInfos > 0) { - if (shmid == -1) xfree(pIndex2UniqIndex); - if (!pDesc) xfree(pCI); + if (shmid == -1) free(pIndex2UniqIndex); + if (!pDesc) free(pCI); } return BadAlloc; } @@ -693,12 +693,12 @@ ProcXF86BigfontQueryFont( } } WriteToClient(client, rlength, (char *)reply); - xfree(reply); + free(reply); if (nCharInfos > 0) { - if (shmid == -1) xfree(pIndex2UniqIndex); - if (!pDesc) xfree(pCI); + if (shmid == -1) free(pIndex2UniqIndex); + if (!pDesc) free(pCI); } - return (client->noClientException); + return Success; } } diff --git a/xorg-server/Xext/xres.c b/xorg-server/Xext/xres.c index 109aa639a..4a5bffa81 100644 --- a/xorg-server/Xext/xres.c +++ b/xorg-server/Xext/xres.c @@ -1,383 +1,383 @@ -/* - Copyright (c) 2002 XFree86 Inc -*/ - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include -#include -#include -#include -#include "misc.h" -#include "os.h" -#include "dixstruct.h" -#include "extnsionst.h" -#include "swaprep.h" -#include "registry.h" -#include -#include "pixmapstr.h" -#include "windowstr.h" -#include "gcstruct.h" -#include "modinit.h" -#include "protocol-versions.h" - -static int -ProcXResQueryVersion (ClientPtr client) -{ - REQUEST(xXResQueryVersionReq); - xXResQueryVersionReply rep; - CARD16 client_major, client_minor; /* not used */ - - REQUEST_SIZE_MATCH (xXResQueryVersionReq); - - client_major = stuff->client_major; - client_minor = stuff->client_minor; - (void) client_major; - (void) client_minor; - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.server_major = SERVER_XRES_MAJOR_VERSION; - rep.server_minor = SERVER_XRES_MINOR_VERSION; - if (client->swapped) { - int n; - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swaps(&rep.server_major, n); - swaps(&rep.server_minor, n); - } - WriteToClient(client, sizeof (xXResQueryVersionReply), (char *)&rep); - return (client->noClientException); -} - -static int -ProcXResQueryClients (ClientPtr client) -{ - /* REQUEST(xXResQueryClientsReq); */ - xXResQueryClientsReply rep; - int *current_clients; - int i, num_clients; - - REQUEST_SIZE_MATCH(xXResQueryClientsReq); - - current_clients = xalloc(currentMaxClients * sizeof(int)); - - num_clients = 0; - for(i = 0; i < currentMaxClients; i++) { - if(clients[i]) { - current_clients[num_clients] = i; - num_clients++; - } - } - - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.num_clients = num_clients; - rep.length = bytes_to_int32(rep.num_clients * sz_xXResClient); - if (client->swapped) { - int n; - swaps (&rep.sequenceNumber, n); - swapl (&rep.length, n); - swapl (&rep.num_clients, n); - } - WriteToClient (client, sizeof (xXResQueryClientsReply), (char *) &rep); - - if(num_clients) { - xXResClient scratch; - - for(i = 0; i < num_clients; i++) { - scratch.resource_base = clients[current_clients[i]]->clientAsMask; - scratch.resource_mask = RESOURCE_ID_MASK; - - if(client->swapped) { - int n; - swapl (&scratch.resource_base, n); - swapl (&scratch.resource_mask, n); - } - WriteToClient (client, sz_xXResClient, (char *) &scratch); - } - } - - xfree(current_clients); - - return (client->noClientException); -} - - -static void -ResFindAllRes (pointer value, XID id, RESTYPE type, pointer cdata) -{ - int *counts = (int *)cdata; - - counts[(type & TypeMask) - 1]++; -} - -static int -ProcXResQueryClientResources (ClientPtr client) -{ - REQUEST(xXResQueryClientResourcesReq); - xXResQueryClientResourcesReply rep; - int i, clientID, num_types; - int *counts; - - REQUEST_SIZE_MATCH(xXResQueryClientResourcesReq); - - clientID = CLIENT_ID(stuff->xid); - - if((clientID >= currentMaxClients) || !clients[clientID]) { - client->errorValue = stuff->xid; - return BadValue; - } - - counts = xcalloc(lastResourceType + 1, sizeof(int)); - - FindAllClientResources(clients[clientID], ResFindAllRes, counts); - - num_types = 0; - - for(i = 0; i <= lastResourceType; i++) { - if(counts[i]) num_types++; - } - - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.num_types = num_types; - rep.length = bytes_to_int32(rep.num_types * sz_xXResType); - if (client->swapped) { - int n; - swaps (&rep.sequenceNumber, n); - swapl (&rep.length, n); - swapl (&rep.num_types, n); - } - - WriteToClient (client,sizeof(xXResQueryClientResourcesReply),(char*)&rep); - - if(num_types) { - xXResType scratch; - char *name; - - for(i = 0; i < lastResourceType; i++) { - if(!counts[i]) continue; - - name = (char *)LookupResourceName(i + 1); - if (strcmp(name, XREGISTRY_UNKNOWN)) - scratch.resource_type = MakeAtom(name, strlen(name), TRUE); - else { - char buf[40]; - snprintf(buf, sizeof(buf), "Unregistered resource %i", i + 1); - scratch.resource_type = MakeAtom(buf, strlen(buf), TRUE); - } - - scratch.count = counts[i]; - - if(client->swapped) { - int n; - swapl (&scratch.resource_type, n); - swapl (&scratch.count, n); - } - WriteToClient (client, sz_xXResType, (char *) &scratch); - } - } - - xfree(counts); - - return (client->noClientException); -} - -static unsigned long -ResGetApproxPixmapBytes (PixmapPtr pix) -{ - unsigned long nPixels; - int bytesPerPixel; - - bytesPerPixel = pix->drawable.bitsPerPixel>>3; - nPixels = pix->drawable.width * pix->drawable.height; - - /* Divide by refcnt as pixmap could be shared between clients, - * so total pixmap mem is shared between these. - */ - return ( nPixels * bytesPerPixel ) / pix->refcnt; -} - -static void -ResFindPixmaps (pointer value, XID id, pointer cdata) -{ - unsigned long *bytes = (unsigned long *)cdata; - PixmapPtr pix = (PixmapPtr)value; - - *bytes += ResGetApproxPixmapBytes(pix); -} - -static void -ResFindWindowPixmaps (pointer value, XID id, pointer cdata) -{ - unsigned long *bytes = (unsigned long *)cdata; - WindowPtr pWin = (WindowPtr)value; - - if (pWin->backgroundState == BackgroundPixmap) - *bytes += ResGetApproxPixmapBytes(pWin->background.pixmap); - - if (pWin->border.pixmap != NULL && !pWin->borderIsPixel) - *bytes += ResGetApproxPixmapBytes(pWin->border.pixmap); -} - -static void -ResFindGCPixmaps (pointer value, XID id, pointer cdata) -{ - unsigned long *bytes = (unsigned long *)cdata; - GCPtr pGC = (GCPtr)value; - - if (pGC->stipple != NULL) - *bytes += ResGetApproxPixmapBytes(pGC->stipple); - - if (pGC->tile.pixmap != NULL && !pGC->tileIsPixel) - *bytes += ResGetApproxPixmapBytes(pGC->tile.pixmap); -} - -static int -ProcXResQueryClientPixmapBytes (ClientPtr client) -{ - REQUEST(xXResQueryClientPixmapBytesReq); - xXResQueryClientPixmapBytesReply rep; - int clientID; - unsigned long bytes; - - REQUEST_SIZE_MATCH(xXResQueryClientPixmapBytesReq); - - clientID = CLIENT_ID(stuff->xid); - - if((clientID >= currentMaxClients) || !clients[clientID]) { - client->errorValue = stuff->xid; - return BadValue; - } - - bytes = 0; - - FindClientResourcesByType(clients[clientID], RT_PIXMAP, ResFindPixmaps, - (pointer)(&bytes)); - - /* - * Make sure win background pixmaps also held to account. - */ - FindClientResourcesByType(clients[clientID], RT_WINDOW, - ResFindWindowPixmaps, - (pointer)(&bytes)); - - /* - * GC Tile & Stipple pixmaps too. - */ - FindClientResourcesByType(clients[clientID], RT_GC, - ResFindGCPixmaps, - (pointer)(&bytes)); - -#ifdef COMPOSITE - /* FIXME: include composite pixmaps too */ -#endif - - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.length = 0; - rep.bytes = bytes; -#ifdef _XSERVER64 - rep.bytes_overflow = bytes >> 32; -#else - rep.bytes_overflow = 0; -#endif - if (client->swapped) { - int n; - swaps (&rep.sequenceNumber, n); - swapl (&rep.length, n); - swapl (&rep.bytes, n); - swapl (&rep.bytes_overflow, n); - } - WriteToClient (client,sizeof(xXResQueryClientPixmapBytesReply),(char*)&rep); - - return (client->noClientException); -} - -static int -ProcResDispatch (ClientPtr client) -{ - REQUEST(xReq); - switch (stuff->data) { - case X_XResQueryVersion: - return ProcXResQueryVersion(client); - case X_XResQueryClients: - return ProcXResQueryClients(client); - case X_XResQueryClientResources: - return ProcXResQueryClientResources(client); - case X_XResQueryClientPixmapBytes: - return ProcXResQueryClientPixmapBytes(client); - default: break; - } - - return BadRequest; -} - -static int -SProcXResQueryVersion (ClientPtr client) -{ - REQUEST(xXResQueryVersionReq); - int n; - - REQUEST_SIZE_MATCH (xXResQueryVersionReq); - swaps(&stuff->client_major,n); - swaps(&stuff->client_minor,n); - return ProcXResQueryVersion(client); -} - -static int -SProcXResQueryClientResources (ClientPtr client) -{ - REQUEST(xXResQueryClientResourcesReq); - int n; - - REQUEST_SIZE_MATCH (xXResQueryClientResourcesReq); - swaps(&stuff->xid,n); - return ProcXResQueryClientResources(client); -} - -static int -SProcXResQueryClientPixmapBytes (ClientPtr client) -{ - REQUEST(xXResQueryClientPixmapBytesReq); - int n; - - REQUEST_SIZE_MATCH (xXResQueryClientPixmapBytesReq); - swaps(&stuff->xid,n); - return ProcXResQueryClientPixmapBytes(client); -} - -static int -SProcResDispatch (ClientPtr client) -{ - REQUEST(xReq); - int n; - - swaps(&stuff->length,n); - - switch (stuff->data) { - case X_XResQueryVersion: - return SProcXResQueryVersion(client); - case X_XResQueryClients: /* nothing to swap */ - return ProcXResQueryClients(client); - case X_XResQueryClientResources: - return SProcXResQueryClientResources(client); - case X_XResQueryClientPixmapBytes: - return SProcXResQueryClientPixmapBytes(client); - default: break; - } - - return BadRequest; -} - -void -ResExtensionInit(INITARGS) -{ - (void) AddExtension(XRES_NAME, 0, 0, - ProcResDispatch, SProcResDispatch, - NULL, StandardMinorOpcode); -} +/* + Copyright (c) 2002 XFree86 Inc +*/ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include +#include +#include +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "swaprep.h" +#include "registry.h" +#include +#include "pixmapstr.h" +#include "windowstr.h" +#include "gcstruct.h" +#include "modinit.h" +#include "protocol-versions.h" + +static int +ProcXResQueryVersion (ClientPtr client) +{ + REQUEST(xXResQueryVersionReq); + xXResQueryVersionReply rep; + CARD16 client_major, client_minor; /* not used */ + + REQUEST_SIZE_MATCH (xXResQueryVersionReq); + + client_major = stuff->client_major; + client_minor = stuff->client_minor; + (void) client_major; + (void) client_minor; + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.server_major = SERVER_XRES_MAJOR_VERSION; + rep.server_minor = SERVER_XRES_MINOR_VERSION; + if (client->swapped) { + int n; + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.server_major, n); + swaps(&rep.server_minor, n); + } + WriteToClient(client, sizeof (xXResQueryVersionReply), (char *)&rep); + return Success; +} + +static int +ProcXResQueryClients (ClientPtr client) +{ + /* REQUEST(xXResQueryClientsReq); */ + xXResQueryClientsReply rep; + int *current_clients; + int i, num_clients; + + REQUEST_SIZE_MATCH(xXResQueryClientsReq); + + current_clients = malloc(currentMaxClients * sizeof(int)); + + num_clients = 0; + for(i = 0; i < currentMaxClients; i++) { + if(clients[i]) { + current_clients[num_clients] = i; + num_clients++; + } + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.num_clients = num_clients; + rep.length = bytes_to_int32(rep.num_clients * sz_xXResClient); + if (client->swapped) { + int n; + swaps (&rep.sequenceNumber, n); + swapl (&rep.length, n); + swapl (&rep.num_clients, n); + } + WriteToClient (client, sizeof (xXResQueryClientsReply), (char *) &rep); + + if(num_clients) { + xXResClient scratch; + + for(i = 0; i < num_clients; i++) { + scratch.resource_base = clients[current_clients[i]]->clientAsMask; + scratch.resource_mask = RESOURCE_ID_MASK; + + if(client->swapped) { + int n; + swapl (&scratch.resource_base, n); + swapl (&scratch.resource_mask, n); + } + WriteToClient (client, sz_xXResClient, (char *) &scratch); + } + } + + free(current_clients); + + return Success; +} + + +static void +ResFindAllRes (pointer value, XID id, RESTYPE type, pointer cdata) +{ + int *counts = (int *)cdata; + + counts[(type & TypeMask) - 1]++; +} + +static int +ProcXResQueryClientResources (ClientPtr client) +{ + REQUEST(xXResQueryClientResourcesReq); + xXResQueryClientResourcesReply rep; + int i, clientID, num_types; + int *counts; + + REQUEST_SIZE_MATCH(xXResQueryClientResourcesReq); + + clientID = CLIENT_ID(stuff->xid); + + if((clientID >= currentMaxClients) || !clients[clientID]) { + client->errorValue = stuff->xid; + return BadValue; + } + + counts = calloc(lastResourceType + 1, sizeof(int)); + + FindAllClientResources(clients[clientID], ResFindAllRes, counts); + + num_types = 0; + + for(i = 0; i <= lastResourceType; i++) { + if(counts[i]) num_types++; + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.num_types = num_types; + rep.length = bytes_to_int32(rep.num_types * sz_xXResType); + if (client->swapped) { + int n; + swaps (&rep.sequenceNumber, n); + swapl (&rep.length, n); + swapl (&rep.num_types, n); + } + + WriteToClient (client,sizeof(xXResQueryClientResourcesReply),(char*)&rep); + + if(num_types) { + xXResType scratch; + char *name; + + for(i = 0; i < lastResourceType; i++) { + if(!counts[i]) continue; + + name = (char *)LookupResourceName(i + 1); + if (strcmp(name, XREGISTRY_UNKNOWN)) + scratch.resource_type = MakeAtom(name, strlen(name), TRUE); + else { + char buf[40]; + snprintf(buf, sizeof(buf), "Unregistered resource %i", i + 1); + scratch.resource_type = MakeAtom(buf, strlen(buf), TRUE); + } + + scratch.count = counts[i]; + + if(client->swapped) { + int n; + swapl (&scratch.resource_type, n); + swapl (&scratch.count, n); + } + WriteToClient (client, sz_xXResType, (char *) &scratch); + } + } + + free(counts); + + return Success; +} + +static unsigned long +ResGetApproxPixmapBytes (PixmapPtr pix) +{ + unsigned long nPixels; + int bytesPerPixel; + + bytesPerPixel = pix->drawable.bitsPerPixel>>3; + nPixels = pix->drawable.width * pix->drawable.height; + + /* Divide by refcnt as pixmap could be shared between clients, + * so total pixmap mem is shared between these. + */ + return ( nPixels * bytesPerPixel ) / pix->refcnt; +} + +static void +ResFindPixmaps (pointer value, XID id, pointer cdata) +{ + unsigned long *bytes = (unsigned long *)cdata; + PixmapPtr pix = (PixmapPtr)value; + + *bytes += ResGetApproxPixmapBytes(pix); +} + +static void +ResFindWindowPixmaps (pointer value, XID id, pointer cdata) +{ + unsigned long *bytes = (unsigned long *)cdata; + WindowPtr pWin = (WindowPtr)value; + + if (pWin->backgroundState == BackgroundPixmap) + *bytes += ResGetApproxPixmapBytes(pWin->background.pixmap); + + if (pWin->border.pixmap != NULL && !pWin->borderIsPixel) + *bytes += ResGetApproxPixmapBytes(pWin->border.pixmap); +} + +static void +ResFindGCPixmaps (pointer value, XID id, pointer cdata) +{ + unsigned long *bytes = (unsigned long *)cdata; + GCPtr pGC = (GCPtr)value; + + if (pGC->stipple != NULL) + *bytes += ResGetApproxPixmapBytes(pGC->stipple); + + if (pGC->tile.pixmap != NULL && !pGC->tileIsPixel) + *bytes += ResGetApproxPixmapBytes(pGC->tile.pixmap); +} + +static int +ProcXResQueryClientPixmapBytes (ClientPtr client) +{ + REQUEST(xXResQueryClientPixmapBytesReq); + xXResQueryClientPixmapBytesReply rep; + int clientID; + unsigned long bytes; + + REQUEST_SIZE_MATCH(xXResQueryClientPixmapBytesReq); + + clientID = CLIENT_ID(stuff->xid); + + if((clientID >= currentMaxClients) || !clients[clientID]) { + client->errorValue = stuff->xid; + return BadValue; + } + + bytes = 0; + + FindClientResourcesByType(clients[clientID], RT_PIXMAP, ResFindPixmaps, + (pointer)(&bytes)); + + /* + * Make sure win background pixmaps also held to account. + */ + FindClientResourcesByType(clients[clientID], RT_WINDOW, + ResFindWindowPixmaps, + (pointer)(&bytes)); + + /* + * GC Tile & Stipple pixmaps too. + */ + FindClientResourcesByType(clients[clientID], RT_GC, + ResFindGCPixmaps, + (pointer)(&bytes)); + +#ifdef COMPOSITE + /* FIXME: include composite pixmaps too */ +#endif + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.bytes = bytes; +#ifdef _XSERVER64 + rep.bytes_overflow = bytes >> 32; +#else + rep.bytes_overflow = 0; +#endif + if (client->swapped) { + int n; + swaps (&rep.sequenceNumber, n); + swapl (&rep.length, n); + swapl (&rep.bytes, n); + swapl (&rep.bytes_overflow, n); + } + WriteToClient (client,sizeof(xXResQueryClientPixmapBytesReply),(char*)&rep); + + return Success; +} + +static int +ProcResDispatch (ClientPtr client) +{ + REQUEST(xReq); + switch (stuff->data) { + case X_XResQueryVersion: + return ProcXResQueryVersion(client); + case X_XResQueryClients: + return ProcXResQueryClients(client); + case X_XResQueryClientResources: + return ProcXResQueryClientResources(client); + case X_XResQueryClientPixmapBytes: + return ProcXResQueryClientPixmapBytes(client); + default: break; + } + + return BadRequest; +} + +static int +SProcXResQueryVersion (ClientPtr client) +{ + REQUEST(xXResQueryVersionReq); + int n; + + REQUEST_SIZE_MATCH (xXResQueryVersionReq); + swaps(&stuff->client_major,n); + swaps(&stuff->client_minor,n); + return ProcXResQueryVersion(client); +} + +static int +SProcXResQueryClientResources (ClientPtr client) +{ + REQUEST(xXResQueryClientResourcesReq); + int n; + + REQUEST_SIZE_MATCH (xXResQueryClientResourcesReq); + swaps(&stuff->xid,n); + return ProcXResQueryClientResources(client); +} + +static int +SProcXResQueryClientPixmapBytes (ClientPtr client) +{ + REQUEST(xXResQueryClientPixmapBytesReq); + int n; + + REQUEST_SIZE_MATCH (xXResQueryClientPixmapBytesReq); + swaps(&stuff->xid,n); + return ProcXResQueryClientPixmapBytes(client); +} + +static int +SProcResDispatch (ClientPtr client) +{ + REQUEST(xReq); + int n; + + swaps(&stuff->length,n); + + switch (stuff->data) { + case X_XResQueryVersion: + return SProcXResQueryVersion(client); + case X_XResQueryClients: /* nothing to swap */ + return ProcXResQueryClients(client); + case X_XResQueryClientResources: + return SProcXResQueryClientResources(client); + case X_XResQueryClientPixmapBytes: + return SProcXResQueryClientPixmapBytes(client); + default: break; + } + + return BadRequest; +} + +void +ResExtensionInit(INITARGS) +{ + (void) AddExtension(XRES_NAME, 0, 0, + ProcResDispatch, SProcResDispatch, + NULL, StandardMinorOpcode); +} diff --git a/xorg-server/Xext/xselinux_ext.c b/xorg-server/Xext/xselinux_ext.c index aa5573455..0076cedb4 100644 --- a/xorg-server/Xext/xselinux_ext.c +++ b/xorg-server/Xext/xselinux_ext.c @@ -1,734 +1,734 @@ -/************************************************************ - -Author: Eamon Walsh - -Permission to use, copy, modify, distribute, and sell this software and its -documentation for any purpose is hereby granted without fee, provided that -this permission notice appear in supporting documentation. 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 -AUTHOR 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 -#endif - -#include "selection.h" -#include "inputstr.h" -#include "windowstr.h" -#include "propertyst.h" -#include "extnsionst.h" -#include "modinit.h" -#include "xselinuxint.h" - -#define CTX_DEV offsetof(SELinuxSubjectRec, dev_create_sid) -#define CTX_WIN offsetof(SELinuxSubjectRec, win_create_sid) -#define CTX_PRP offsetof(SELinuxSubjectRec, prp_create_sid) -#define CTX_SEL offsetof(SELinuxSubjectRec, sel_create_sid) -#define USE_PRP offsetof(SELinuxSubjectRec, prp_use_sid) -#define USE_SEL offsetof(SELinuxSubjectRec, sel_use_sid) - -typedef struct { - security_context_t octx; - security_context_t dctx; - CARD32 octx_len; - CARD32 dctx_len; - CARD32 id; -} SELinuxListItemRec; - - -/* - * Extension Dispatch - */ - -static security_context_t -SELinuxCopyContext(char *ptr, unsigned len) -{ - security_context_t copy = xalloc(len + 1); - if (!copy) - return NULL; - strncpy(copy, ptr, len); - copy[len] = '\0'; - return copy; -} - -static int -ProcSELinuxQueryVersion(ClientPtr client) -{ - SELinuxQueryVersionReply rep; - - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.server_major = SELINUX_MAJOR_VERSION; - rep.server_minor = SELINUX_MINOR_VERSION; - if (client->swapped) { - int n; - swaps(&rep.sequenceNumber, n); - swapl(&rep.length, n); - swaps(&rep.server_major, n); - swaps(&rep.server_minor, n); - } - WriteToClient(client, sizeof(rep), (char *)&rep); - return (client->noClientException); -} - -static int -SELinuxSendContextReply(ClientPtr client, security_id_t sid) -{ - SELinuxGetContextReply rep; - security_context_t ctx = NULL; - int len = 0; - - if (sid) { - if (avc_sid_to_context_raw(sid, &ctx) < 0) - return BadValue; - len = strlen(ctx) + 1; - } - - rep.type = X_Reply; - rep.length = bytes_to_int32(len); - rep.sequenceNumber = client->sequence; - rep.context_len = len; - - if (client->swapped) { - int n; - swapl(&rep.length, n); - swaps(&rep.sequenceNumber, n); - swapl(&rep.context_len, n); - } - - WriteToClient(client, sizeof(SELinuxGetContextReply), (char *)&rep); - WriteToClient(client, len, ctx); - freecon(ctx); - return client->noClientException; -} - -static int -ProcSELinuxSetCreateContext(ClientPtr client, unsigned offset) -{ - PrivateRec **privPtr = &client->devPrivates; - security_id_t *pSid; - security_context_t ctx = NULL; - char *ptr; - int rc; - - REQUEST(SELinuxSetCreateContextReq); - REQUEST_FIXED_SIZE(SELinuxSetCreateContextReq, stuff->context_len); - - if (stuff->context_len > 0) { - ctx = SELinuxCopyContext((char *)(stuff + 1), stuff->context_len); - if (!ctx) - return BadAlloc; - } - - ptr = dixLookupPrivate(privPtr, subjectKey); - pSid = (security_id_t *)(ptr + offset); - *pSid = NULL; - - rc = Success; - if (stuff->context_len > 0) { - if (security_check_context_raw(ctx) < 0 || - avc_context_to_sid_raw(ctx, pSid) < 0) - rc = BadValue; - } - - xfree(ctx); - return rc; -} - -static int -ProcSELinuxGetCreateContext(ClientPtr client, unsigned offset) -{ - security_id_t *pSid; - char *ptr; - - REQUEST_SIZE_MATCH(SELinuxGetCreateContextReq); - - if (offset == CTX_DEV) - ptr = dixLookupPrivate(&serverClient->devPrivates, subjectKey); - else - ptr = dixLookupPrivate(&client->devPrivates, subjectKey); - - pSid = (security_id_t *)(ptr + offset); - return SELinuxSendContextReply(client, *pSid); -} - -static int -ProcSELinuxSetDeviceContext(ClientPtr client) -{ - security_context_t ctx; - security_id_t sid; - DeviceIntPtr dev; - SELinuxSubjectRec *subj; - SELinuxObjectRec *obj; - int rc; - - REQUEST(SELinuxSetContextReq); - REQUEST_FIXED_SIZE(SELinuxSetContextReq, stuff->context_len); - - if (stuff->context_len < 1) - return BadLength; - ctx = SELinuxCopyContext((char *)(stuff + 1), stuff->context_len); - if (!ctx) - return BadAlloc; - - rc = dixLookupDevice(&dev, stuff->id, client, DixManageAccess); - if (rc != Success) - goto out; - - if (security_check_context_raw(ctx) < 0 || - avc_context_to_sid_raw(ctx, &sid) < 0) { - rc = BadValue; - goto out; - } - - subj = dixLookupPrivate(&dev->devPrivates, subjectKey); - subj->sid = sid; - obj = dixLookupPrivate(&dev->devPrivates, objectKey); - obj->sid = sid; - - rc = Success; -out: - xfree(ctx); - return rc; -} - -static int -ProcSELinuxGetDeviceContext(ClientPtr client) -{ - DeviceIntPtr dev; - SELinuxSubjectRec *subj; - int rc; - - REQUEST(SELinuxGetContextReq); - REQUEST_SIZE_MATCH(SELinuxGetContextReq); - - rc = dixLookupDevice(&dev, stuff->id, client, DixGetAttrAccess); - if (rc != Success) - return rc; - - subj = dixLookupPrivate(&dev->devPrivates, subjectKey); - return SELinuxSendContextReply(client, subj->sid); -} - -static int -ProcSELinuxGetDrawableContext(ClientPtr client) -{ - DrawablePtr pDraw; - PrivateRec **privatePtr; - SELinuxObjectRec *obj; - int rc; - - REQUEST(SELinuxGetContextReq); - REQUEST_SIZE_MATCH(SELinuxGetContextReq); - - rc = dixLookupDrawable(&pDraw, stuff->id, client, - M_WINDOW | M_DRAWABLE_PIXMAP, - DixGetAttrAccess); - if (rc != Success) - return rc; - - if (pDraw->type == M_DRAWABLE_PIXMAP) - privatePtr = &((PixmapPtr)pDraw)->devPrivates; - else - privatePtr = &((WindowPtr)pDraw)->devPrivates; - - obj = dixLookupPrivate(privatePtr, objectKey); - return SELinuxSendContextReply(client, obj->sid); -} - -static int -ProcSELinuxGetPropertyContext(ClientPtr client, pointer privKey) -{ - WindowPtr pWin; - PropertyPtr pProp; - SELinuxObjectRec *obj; - int rc; - - REQUEST(SELinuxGetPropertyContextReq); - REQUEST_SIZE_MATCH(SELinuxGetPropertyContextReq); - - rc = dixLookupWindow(&pWin, stuff->window, client, DixGetPropAccess); - if (rc != Success) - return rc; - - rc = dixLookupProperty(&pProp, pWin, stuff->property, client, - DixGetAttrAccess); - if (rc != Success) - return rc; - - obj = dixLookupPrivate(&pProp->devPrivates, privKey); - return SELinuxSendContextReply(client, obj->sid); -} - -static int -ProcSELinuxGetSelectionContext(ClientPtr client, pointer privKey) -{ - Selection *pSel; - SELinuxObjectRec *obj; - int rc; - - REQUEST(SELinuxGetContextReq); - REQUEST_SIZE_MATCH(SELinuxGetContextReq); - - rc = dixLookupSelection(&pSel, stuff->id, client, DixGetAttrAccess); - if (rc != Success) - return rc; - - obj = dixLookupPrivate(&pSel->devPrivates, privKey); - return SELinuxSendContextReply(client, obj->sid); -} - -static int -ProcSELinuxGetClientContext(ClientPtr client) -{ - ClientPtr target; - SELinuxSubjectRec *subj; - int rc; - - REQUEST(SELinuxGetContextReq); - REQUEST_SIZE_MATCH(SELinuxGetContextReq); - - rc = dixLookupClient(&target, stuff->id, client, DixGetAttrAccess); - if (rc != Success) - return rc; - - subj = dixLookupPrivate(&target->devPrivates, subjectKey); - return SELinuxSendContextReply(client, subj->sid); -} - -static int -SELinuxPopulateItem(SELinuxListItemRec *i, PrivateRec **privPtr, CARD32 id, - int *size) -{ - SELinuxObjectRec *obj = dixLookupPrivate(privPtr, objectKey); - SELinuxObjectRec *data = dixLookupPrivate(privPtr, dataKey); - - if (avc_sid_to_context_raw(obj->sid, &i->octx) < 0) - return BadValue; - if (avc_sid_to_context_raw(data->sid, &i->dctx) < 0) - return BadValue; - - i->id = id; - i->octx_len = bytes_to_int32(strlen(i->octx) + 1); - i->dctx_len = bytes_to_int32(strlen(i->dctx) + 1); - - *size += i->octx_len + i->dctx_len + 3; - return Success; -} - -static void -SELinuxFreeItems(SELinuxListItemRec *items, int count) -{ - int k; - for (k = 0; k < count; k++) { - freecon(items[k].octx); - freecon(items[k].dctx); - } - xfree(items); -} - -static int -SELinuxSendItemsToClient(ClientPtr client, SELinuxListItemRec *items, - int size, int count) -{ - int rc, k, n, pos = 0; - SELinuxListItemsReply rep; - CARD32 *buf; - - buf = xcalloc(size, sizeof(CARD32)); - if (size && !buf) { - rc = BadAlloc; - goto out; - } - - /* Fill in the buffer */ - for (k = 0; k < count; k++) { - buf[pos] = items[k].id; - if (client->swapped) - swapl(buf + pos, n); - pos++; - - buf[pos] = items[k].octx_len * 4; - if (client->swapped) - swapl(buf + pos, n); - pos++; - - buf[pos] = items[k].dctx_len * 4; - if (client->swapped) - swapl(buf + pos, n); - pos++; - - memcpy((char *)(buf + pos), items[k].octx, strlen(items[k].octx) + 1); - pos += items[k].octx_len; - memcpy((char *)(buf + pos), items[k].dctx, strlen(items[k].dctx) + 1); - pos += items[k].dctx_len; - } - - /* Send reply to client */ - rep.type = X_Reply; - rep.length = size; - rep.sequenceNumber = client->sequence; - rep.count = count; - - if (client->swapped) { - swapl(&rep.length, n); - swaps(&rep.sequenceNumber, n); - swapl(&rep.count, n); - } - - WriteToClient(client, sizeof(SELinuxListItemsReply), (char *)&rep); - WriteToClient(client, size * 4, (char *)buf); - - /* Free stuff and return */ - rc = client->noClientException; - xfree(buf); -out: - SELinuxFreeItems(items, count); - return rc; -} - -static int -ProcSELinuxListProperties(ClientPtr client) -{ - WindowPtr pWin; - PropertyPtr pProp; - SELinuxListItemRec *items; - int rc, count, size, i; - CARD32 id; - - REQUEST(SELinuxGetContextReq); - REQUEST_SIZE_MATCH(SELinuxGetContextReq); - - rc = dixLookupWindow(&pWin, stuff->id, client, DixListPropAccess); - if (rc != Success) - return rc; - - /* Count the number of properties and allocate items */ - count = 0; - for (pProp = wUserProps(pWin); pProp; pProp = pProp->next) - count++; - items = xcalloc(count, sizeof(SELinuxListItemRec)); - if (count && !items) - return BadAlloc; - - /* Fill in the items and calculate size */ - i = 0; - size = 0; - for (pProp = wUserProps(pWin); pProp; pProp = pProp->next) { - id = pProp->propertyName; - rc = SELinuxPopulateItem(items + i, &pProp->devPrivates, id, &size); - if (rc != Success) { - SELinuxFreeItems(items, count); - return rc; - } - i++; - } - - return SELinuxSendItemsToClient(client, items, size, count); -} - -static int -ProcSELinuxListSelections(ClientPtr client) -{ - Selection *pSel; - SELinuxListItemRec *items; - int rc, count, size, i; - CARD32 id; - - REQUEST_SIZE_MATCH(SELinuxGetCreateContextReq); - - /* Count the number of selections and allocate items */ - count = 0; - for (pSel = CurrentSelections; pSel; pSel = pSel->next) - count++; - items = xcalloc(count, sizeof(SELinuxListItemRec)); - if (count && !items) - return BadAlloc; - - /* Fill in the items and calculate size */ - i = 0; - size = 0; - for (pSel = CurrentSelections; pSel; pSel = pSel->next) { - id = pSel->selection; - rc = SELinuxPopulateItem(items + i, &pSel->devPrivates, id, &size); - if (rc != Success) { - SELinuxFreeItems(items, count); - return rc; - } - i++; - } - - return SELinuxSendItemsToClient(client, items, size, count); -} - -static int -ProcSELinuxDispatch(ClientPtr client) -{ - REQUEST(xReq); - switch (stuff->data) { - case X_SELinuxQueryVersion: - return ProcSELinuxQueryVersion(client); - case X_SELinuxSetDeviceCreateContext: - return ProcSELinuxSetCreateContext(client, CTX_DEV); - case X_SELinuxGetDeviceCreateContext: - return ProcSELinuxGetCreateContext(client, CTX_DEV); - case X_SELinuxSetDeviceContext: - return ProcSELinuxSetDeviceContext(client); - case X_SELinuxGetDeviceContext: - return ProcSELinuxGetDeviceContext(client); - case X_SELinuxSetDrawableCreateContext: - return ProcSELinuxSetCreateContext(client, CTX_WIN); - case X_SELinuxGetDrawableCreateContext: - return ProcSELinuxGetCreateContext(client, CTX_WIN); - case X_SELinuxGetDrawableContext: - return ProcSELinuxGetDrawableContext(client); - case X_SELinuxSetPropertyCreateContext: - return ProcSELinuxSetCreateContext(client, CTX_PRP); - case X_SELinuxGetPropertyCreateContext: - return ProcSELinuxGetCreateContext(client, CTX_PRP); - case X_SELinuxSetPropertyUseContext: - return ProcSELinuxSetCreateContext(client, USE_PRP); - case X_SELinuxGetPropertyUseContext: - return ProcSELinuxGetCreateContext(client, USE_PRP); - case X_SELinuxGetPropertyContext: - return ProcSELinuxGetPropertyContext(client, objectKey); - case X_SELinuxGetPropertyDataContext: - return ProcSELinuxGetPropertyContext(client, dataKey); - case X_SELinuxListProperties: - return ProcSELinuxListProperties(client); - case X_SELinuxSetSelectionCreateContext: - return ProcSELinuxSetCreateContext(client, CTX_SEL); - case X_SELinuxGetSelectionCreateContext: - return ProcSELinuxGetCreateContext(client, CTX_SEL); - case X_SELinuxSetSelectionUseContext: - return ProcSELinuxSetCreateContext(client, USE_SEL); - case X_SELinuxGetSelectionUseContext: - return ProcSELinuxGetCreateContext(client, USE_SEL); - case X_SELinuxGetSelectionContext: - return ProcSELinuxGetSelectionContext(client, objectKey); - case X_SELinuxGetSelectionDataContext: - return ProcSELinuxGetSelectionContext(client, dataKey); - case X_SELinuxListSelections: - return ProcSELinuxListSelections(client); - case X_SELinuxGetClientContext: - return ProcSELinuxGetClientContext(client); - default: - return BadRequest; - } -} - -static int -SProcSELinuxQueryVersion(ClientPtr client) -{ - REQUEST(SELinuxQueryVersionReq); - int n; - - REQUEST_SIZE_MATCH(SELinuxQueryVersionReq); - swaps(&stuff->client_major, n); - swaps(&stuff->client_minor, n); - return ProcSELinuxQueryVersion(client); -} - -static int -SProcSELinuxSetCreateContext(ClientPtr client, unsigned offset) -{ - REQUEST(SELinuxSetCreateContextReq); - int n; - - REQUEST_AT_LEAST_SIZE(SELinuxSetCreateContextReq); - swapl(&stuff->context_len, n); - return ProcSELinuxSetCreateContext(client, offset); -} - -static int -SProcSELinuxSetDeviceContext(ClientPtr client) -{ - REQUEST(SELinuxSetContextReq); - int n; - - REQUEST_AT_LEAST_SIZE(SELinuxSetContextReq); - swapl(&stuff->id, n); - swapl(&stuff->context_len, n); - return ProcSELinuxSetDeviceContext(client); -} - -static int -SProcSELinuxGetDeviceContext(ClientPtr client) -{ - REQUEST(SELinuxGetContextReq); - int n; - - REQUEST_SIZE_MATCH(SELinuxGetContextReq); - swapl(&stuff->id, n); - return ProcSELinuxGetDeviceContext(client); -} - -static int -SProcSELinuxGetDrawableContext(ClientPtr client) -{ - REQUEST(SELinuxGetContextReq); - int n; - - REQUEST_SIZE_MATCH(SELinuxGetContextReq); - swapl(&stuff->id, n); - return ProcSELinuxGetDrawableContext(client); -} - -static int -SProcSELinuxGetPropertyContext(ClientPtr client, pointer privKey) -{ - REQUEST(SELinuxGetPropertyContextReq); - int n; - - REQUEST_SIZE_MATCH(SELinuxGetPropertyContextReq); - swapl(&stuff->window, n); - swapl(&stuff->property, n); - return ProcSELinuxGetPropertyContext(client, privKey); -} - -static int -SProcSELinuxGetSelectionContext(ClientPtr client, pointer privKey) -{ - REQUEST(SELinuxGetContextReq); - int n; - - REQUEST_SIZE_MATCH(SELinuxGetContextReq); - swapl(&stuff->id, n); - return ProcSELinuxGetSelectionContext(client, privKey); -} - -static int -SProcSELinuxListProperties(ClientPtr client) -{ - REQUEST(SELinuxGetContextReq); - int n; - - REQUEST_SIZE_MATCH(SELinuxGetContextReq); - swapl(&stuff->id, n); - return ProcSELinuxListProperties(client); -} - -static int -SProcSELinuxGetClientContext(ClientPtr client) -{ - REQUEST(SELinuxGetContextReq); - int n; - - REQUEST_SIZE_MATCH(SELinuxGetContextReq); - swapl(&stuff->id, n); - return ProcSELinuxGetClientContext(client); -} - -static int -SProcSELinuxDispatch(ClientPtr client) -{ - REQUEST(xReq); - int n; - - swaps(&stuff->length, n); - - switch (stuff->data) { - case X_SELinuxQueryVersion: - return SProcSELinuxQueryVersion(client); - case X_SELinuxSetDeviceCreateContext: - return SProcSELinuxSetCreateContext(client, CTX_DEV); - case X_SELinuxGetDeviceCreateContext: - return ProcSELinuxGetCreateContext(client, CTX_DEV); - case X_SELinuxSetDeviceContext: - return SProcSELinuxSetDeviceContext(client); - case X_SELinuxGetDeviceContext: - return SProcSELinuxGetDeviceContext(client); - case X_SELinuxSetDrawableCreateContext: - return SProcSELinuxSetCreateContext(client, CTX_WIN); - case X_SELinuxGetDrawableCreateContext: - return ProcSELinuxGetCreateContext(client, CTX_WIN); - case X_SELinuxGetDrawableContext: - return SProcSELinuxGetDrawableContext(client); - case X_SELinuxSetPropertyCreateContext: - return SProcSELinuxSetCreateContext(client, CTX_PRP); - case X_SELinuxGetPropertyCreateContext: - return ProcSELinuxGetCreateContext(client, CTX_PRP); - case X_SELinuxSetPropertyUseContext: - return SProcSELinuxSetCreateContext(client, USE_PRP); - case X_SELinuxGetPropertyUseContext: - return ProcSELinuxGetCreateContext(client, USE_PRP); - case X_SELinuxGetPropertyContext: - return SProcSELinuxGetPropertyContext(client, objectKey); - case X_SELinuxGetPropertyDataContext: - return SProcSELinuxGetPropertyContext(client, dataKey); - case X_SELinuxListProperties: - return SProcSELinuxListProperties(client); - case X_SELinuxSetSelectionCreateContext: - return SProcSELinuxSetCreateContext(client, CTX_SEL); - case X_SELinuxGetSelectionCreateContext: - return ProcSELinuxGetCreateContext(client, CTX_SEL); - case X_SELinuxSetSelectionUseContext: - return SProcSELinuxSetCreateContext(client, USE_SEL); - case X_SELinuxGetSelectionUseContext: - return ProcSELinuxGetCreateContext(client, USE_SEL); - case X_SELinuxGetSelectionContext: - return SProcSELinuxGetSelectionContext(client, objectKey); - case X_SELinuxGetSelectionDataContext: - return SProcSELinuxGetSelectionContext(client, dataKey); - case X_SELinuxListSelections: - return ProcSELinuxListSelections(client); - case X_SELinuxGetClientContext: - return SProcSELinuxGetClientContext(client); - default: - return BadRequest; - } -} - - -/* - * Extension Setup / Teardown - */ - -static void -SELinuxResetProc(ExtensionEntry *extEntry) -{ - SELinuxFlaskReset(); - SELinuxLabelReset(); -} - -void -SELinuxExtensionInit(INITARGS) -{ - ExtensionEntry *extEntry; - - /* Check SELinux mode on system, configuration file, and boolean */ - if (!is_selinux_enabled()) { - LogMessage(X_INFO, "SELinux: Disabled on system\n"); - return; - } - if (selinuxEnforcingState == SELINUX_MODE_DISABLED) { - LogMessage(X_INFO, "SELinux: Disabled in configuration file\n"); - return; - } - if (!security_get_boolean_active("xserver_object_manager")) { - LogMessage(X_INFO, "SELinux: Disabled by boolean\n"); - return; - } - - /* Set up XACE hooks */ - SELinuxLabelInit(); - SELinuxFlaskInit(); - - /* Add extension to server */ - extEntry = AddExtension(SELINUX_EXTENSION_NAME, - SELinuxNumberEvents, SELinuxNumberErrors, - ProcSELinuxDispatch, SProcSELinuxDispatch, - SELinuxResetProc, StandardMinorOpcode); - - AddExtensionAlias("Flask", extEntry); -} +/************************************************************ + +Author: Eamon Walsh + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +this permission notice appear in supporting documentation. 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 +AUTHOR 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 +#endif + +#include "selection.h" +#include "inputstr.h" +#include "windowstr.h" +#include "propertyst.h" +#include "extnsionst.h" +#include "modinit.h" +#include "xselinuxint.h" + +#define CTX_DEV offsetof(SELinuxSubjectRec, dev_create_sid) +#define CTX_WIN offsetof(SELinuxSubjectRec, win_create_sid) +#define CTX_PRP offsetof(SELinuxSubjectRec, prp_create_sid) +#define CTX_SEL offsetof(SELinuxSubjectRec, sel_create_sid) +#define USE_PRP offsetof(SELinuxSubjectRec, prp_use_sid) +#define USE_SEL offsetof(SELinuxSubjectRec, sel_use_sid) + +typedef struct { + security_context_t octx; + security_context_t dctx; + CARD32 octx_len; + CARD32 dctx_len; + CARD32 id; +} SELinuxListItemRec; + + +/* + * Extension Dispatch + */ + +static security_context_t +SELinuxCopyContext(char *ptr, unsigned len) +{ + security_context_t copy = malloc(len + 1); + if (!copy) + return NULL; + strncpy(copy, ptr, len); + copy[len] = '\0'; + return copy; +} + +static int +ProcSELinuxQueryVersion(ClientPtr client) +{ + SELinuxQueryVersionReply rep; + + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.server_major = SELINUX_MAJOR_VERSION; + rep.server_minor = SELINUX_MINOR_VERSION; + if (client->swapped) { + int n; + swaps(&rep.sequenceNumber, n); + swapl(&rep.length, n); + swaps(&rep.server_major, n); + swaps(&rep.server_minor, n); + } + WriteToClient(client, sizeof(rep), (char *)&rep); + return Success; +} + +static int +SELinuxSendContextReply(ClientPtr client, security_id_t sid) +{ + SELinuxGetContextReply rep; + security_context_t ctx = NULL; + int len = 0; + + if (sid) { + if (avc_sid_to_context_raw(sid, &ctx) < 0) + return BadValue; + len = strlen(ctx) + 1; + } + + rep.type = X_Reply; + rep.length = bytes_to_int32(len); + rep.sequenceNumber = client->sequence; + rep.context_len = len; + + if (client->swapped) { + int n; + swapl(&rep.length, n); + swaps(&rep.sequenceNumber, n); + swapl(&rep.context_len, n); + } + + WriteToClient(client, sizeof(SELinuxGetContextReply), (char *)&rep); + WriteToClient(client, len, ctx); + freecon(ctx); + return Success; +} + +static int +ProcSELinuxSetCreateContext(ClientPtr client, unsigned offset) +{ + PrivateRec **privPtr = &client->devPrivates; + security_id_t *pSid; + security_context_t ctx = NULL; + char *ptr; + int rc; + + REQUEST(SELinuxSetCreateContextReq); + REQUEST_FIXED_SIZE(SELinuxSetCreateContextReq, stuff->context_len); + + if (stuff->context_len > 0) { + ctx = SELinuxCopyContext((char *)(stuff + 1), stuff->context_len); + if (!ctx) + return BadAlloc; + } + + ptr = dixLookupPrivate(privPtr, subjectKey); + pSid = (security_id_t *)(ptr + offset); + *pSid = NULL; + + rc = Success; + if (stuff->context_len > 0) { + if (security_check_context_raw(ctx) < 0 || + avc_context_to_sid_raw(ctx, pSid) < 0) + rc = BadValue; + } + + free(ctx); + return rc; +} + +static int +ProcSELinuxGetCreateContext(ClientPtr client, unsigned offset) +{ + security_id_t *pSid; + char *ptr; + + REQUEST_SIZE_MATCH(SELinuxGetCreateContextReq); + + if (offset == CTX_DEV) + ptr = dixLookupPrivate(&serverClient->devPrivates, subjectKey); + else + ptr = dixLookupPrivate(&client->devPrivates, subjectKey); + + pSid = (security_id_t *)(ptr + offset); + return SELinuxSendContextReply(client, *pSid); +} + +static int +ProcSELinuxSetDeviceContext(ClientPtr client) +{ + security_context_t ctx; + security_id_t sid; + DeviceIntPtr dev; + SELinuxSubjectRec *subj; + SELinuxObjectRec *obj; + int rc; + + REQUEST(SELinuxSetContextReq); + REQUEST_FIXED_SIZE(SELinuxSetContextReq, stuff->context_len); + + if (stuff->context_len < 1) + return BadLength; + ctx = SELinuxCopyContext((char *)(stuff + 1), stuff->context_len); + if (!ctx) + return BadAlloc; + + rc = dixLookupDevice(&dev, stuff->id, client, DixManageAccess); + if (rc != Success) + goto out; + + if (security_check_context_raw(ctx) < 0 || + avc_context_to_sid_raw(ctx, &sid) < 0) { + rc = BadValue; + goto out; + } + + subj = dixLookupPrivate(&dev->devPrivates, subjectKey); + subj->sid = sid; + obj = dixLookupPrivate(&dev->devPrivates, objectKey); + obj->sid = sid; + + rc = Success; +out: + free(ctx); + return rc; +} + +static int +ProcSELinuxGetDeviceContext(ClientPtr client) +{ + DeviceIntPtr dev; + SELinuxSubjectRec *subj; + int rc; + + REQUEST(SELinuxGetContextReq); + REQUEST_SIZE_MATCH(SELinuxGetContextReq); + + rc = dixLookupDevice(&dev, stuff->id, client, DixGetAttrAccess); + if (rc != Success) + return rc; + + subj = dixLookupPrivate(&dev->devPrivates, subjectKey); + return SELinuxSendContextReply(client, subj->sid); +} + +static int +ProcSELinuxGetDrawableContext(ClientPtr client) +{ + DrawablePtr pDraw; + PrivateRec **privatePtr; + SELinuxObjectRec *obj; + int rc; + + REQUEST(SELinuxGetContextReq); + REQUEST_SIZE_MATCH(SELinuxGetContextReq); + + rc = dixLookupDrawable(&pDraw, stuff->id, client, + M_WINDOW | M_DRAWABLE_PIXMAP, + DixGetAttrAccess); + if (rc != Success) + return rc; + + if (pDraw->type == M_DRAWABLE_PIXMAP) + privatePtr = &((PixmapPtr)pDraw)->devPrivates; + else + privatePtr = &((WindowPtr)pDraw)->devPrivates; + + obj = dixLookupPrivate(privatePtr, objectKey); + return SELinuxSendContextReply(client, obj->sid); +} + +static int +ProcSELinuxGetPropertyContext(ClientPtr client, pointer privKey) +{ + WindowPtr pWin; + PropertyPtr pProp; + SELinuxObjectRec *obj; + int rc; + + REQUEST(SELinuxGetPropertyContextReq); + REQUEST_SIZE_MATCH(SELinuxGetPropertyContextReq); + + rc = dixLookupWindow(&pWin, stuff->window, client, DixGetPropAccess); + if (rc != Success) + return rc; + + rc = dixLookupProperty(&pProp, pWin, stuff->property, client, + DixGetAttrAccess); + if (rc != Success) + return rc; + + obj = dixLookupPrivate(&pProp->devPrivates, privKey); + return SELinuxSendContextReply(client, obj->sid); +} + +static int +ProcSELinuxGetSelectionContext(ClientPtr client, pointer privKey) +{ + Selection *pSel; + SELinuxObjectRec *obj; + int rc; + + REQUEST(SELinuxGetContextReq); + REQUEST_SIZE_MATCH(SELinuxGetContextReq); + + rc = dixLookupSelection(&pSel, stuff->id, client, DixGetAttrAccess); + if (rc != Success) + return rc; + + obj = dixLookupPrivate(&pSel->devPrivates, privKey); + return SELinuxSendContextReply(client, obj->sid); +} + +static int +ProcSELinuxGetClientContext(ClientPtr client) +{ + ClientPtr target; + SELinuxSubjectRec *subj; + int rc; + + REQUEST(SELinuxGetContextReq); + REQUEST_SIZE_MATCH(SELinuxGetContextReq); + + rc = dixLookupClient(&target, stuff->id, client, DixGetAttrAccess); + if (rc != Success) + return rc; + + subj = dixLookupPrivate(&target->devPrivates, subjectKey); + return SELinuxSendContextReply(client, subj->sid); +} + +static int +SELinuxPopulateItem(SELinuxListItemRec *i, PrivateRec **privPtr, CARD32 id, + int *size) +{ + SELinuxObjectRec *obj = dixLookupPrivate(privPtr, objectKey); + SELinuxObjectRec *data = dixLookupPrivate(privPtr, dataKey); + + if (avc_sid_to_context_raw(obj->sid, &i->octx) < 0) + return BadValue; + if (avc_sid_to_context_raw(data->sid, &i->dctx) < 0) + return BadValue; + + i->id = id; + i->octx_len = bytes_to_int32(strlen(i->octx) + 1); + i->dctx_len = bytes_to_int32(strlen(i->dctx) + 1); + + *size += i->octx_len + i->dctx_len + 3; + return Success; +} + +static void +SELinuxFreeItems(SELinuxListItemRec *items, int count) +{ + int k; + for (k = 0; k < count; k++) { + freecon(items[k].octx); + freecon(items[k].dctx); + } + free(items); +} + +static int +SELinuxSendItemsToClient(ClientPtr client, SELinuxListItemRec *items, + int size, int count) +{ + int rc, k, n, pos = 0; + SELinuxListItemsReply rep; + CARD32 *buf; + + buf = calloc(size, sizeof(CARD32)); + if (size && !buf) { + rc = BadAlloc; + goto out; + } + + /* Fill in the buffer */ + for (k = 0; k < count; k++) { + buf[pos] = items[k].id; + if (client->swapped) + swapl(buf + pos, n); + pos++; + + buf[pos] = items[k].octx_len * 4; + if (client->swapped) + swapl(buf + pos, n); + pos++; + + buf[pos] = items[k].dctx_len * 4; + if (client->swapped) + swapl(buf + pos, n); + pos++; + + memcpy((char *)(buf + pos), items[k].octx, strlen(items[k].octx) + 1); + pos += items[k].octx_len; + memcpy((char *)(buf + pos), items[k].dctx, strlen(items[k].dctx) + 1); + pos += items[k].dctx_len; + } + + /* Send reply to client */ + rep.type = X_Reply; + rep.length = size; + rep.sequenceNumber = client->sequence; + rep.count = count; + + if (client->swapped) { + swapl(&rep.length, n); + swaps(&rep.sequenceNumber, n); + swapl(&rep.count, n); + } + + WriteToClient(client, sizeof(SELinuxListItemsReply), (char *)&rep); + WriteToClient(client, size * 4, (char *)buf); + + /* Free stuff and return */ + rc = Success; + free(buf); +out: + SELinuxFreeItems(items, count); + return rc; +} + +static int +ProcSELinuxListProperties(ClientPtr client) +{ + WindowPtr pWin; + PropertyPtr pProp; + SELinuxListItemRec *items; + int rc, count, size, i; + CARD32 id; + + REQUEST(SELinuxGetContextReq); + REQUEST_SIZE_MATCH(SELinuxGetContextReq); + + rc = dixLookupWindow(&pWin, stuff->id, client, DixListPropAccess); + if (rc != Success) + return rc; + + /* Count the number of properties and allocate items */ + count = 0; + for (pProp = wUserProps(pWin); pProp; pProp = pProp->next) + count++; + items = calloc(count, sizeof(SELinuxListItemRec)); + if (count && !items) + return BadAlloc; + + /* Fill in the items and calculate size */ + i = 0; + size = 0; + for (pProp = wUserProps(pWin); pProp; pProp = pProp->next) { + id = pProp->propertyName; + rc = SELinuxPopulateItem(items + i, &pProp->devPrivates, id, &size); + if (rc != Success) { + SELinuxFreeItems(items, count); + return rc; + } + i++; + } + + return SELinuxSendItemsToClient(client, items, size, count); +} + +static int +ProcSELinuxListSelections(ClientPtr client) +{ + Selection *pSel; + SELinuxListItemRec *items; + int rc, count, size, i; + CARD32 id; + + REQUEST_SIZE_MATCH(SELinuxGetCreateContextReq); + + /* Count the number of selections and allocate items */ + count = 0; + for (pSel = CurrentSelections; pSel; pSel = pSel->next) + count++; + items = calloc(count, sizeof(SELinuxListItemRec)); + if (count && !items) + return BadAlloc; + + /* Fill in the items and calculate size */ + i = 0; + size = 0; + for (pSel = CurrentSelections; pSel; pSel = pSel->next) { + id = pSel->selection; + rc = SELinuxPopulateItem(items + i, &pSel->devPrivates, id, &size); + if (rc != Success) { + SELinuxFreeItems(items, count); + return rc; + } + i++; + } + + return SELinuxSendItemsToClient(client, items, size, count); +} + +static int +ProcSELinuxDispatch(ClientPtr client) +{ + REQUEST(xReq); + switch (stuff->data) { + case X_SELinuxQueryVersion: + return ProcSELinuxQueryVersion(client); + case X_SELinuxSetDeviceCreateContext: + return ProcSELinuxSetCreateContext(client, CTX_DEV); + case X_SELinuxGetDeviceCreateContext: + return ProcSELinuxGetCreateContext(client, CTX_DEV); + case X_SELinuxSetDeviceContext: + return ProcSELinuxSetDeviceContext(client); + case X_SELinuxGetDeviceContext: + return ProcSELinuxGetDeviceContext(client); + case X_SELinuxSetDrawableCreateContext: + return ProcSELinuxSetCreateContext(client, CTX_WIN); + case X_SELinuxGetDrawableCreateContext: + return ProcSELinuxGetCreateContext(client, CTX_WIN); + case X_SELinuxGetDrawableContext: + return ProcSELinuxGetDrawableContext(client); + case X_SELinuxSetPropertyCreateContext: + return ProcSELinuxSetCreateContext(client, CTX_PRP); + case X_SELinuxGetPropertyCreateContext: + return ProcSELinuxGetCreateContext(client, CTX_PRP); + case X_SELinuxSetPropertyUseContext: + return ProcSELinuxSetCreateContext(client, USE_PRP); + case X_SELinuxGetPropertyUseContext: + return ProcSELinuxGetCreateContext(client, USE_PRP); + case X_SELinuxGetPropertyContext: + return ProcSELinuxGetPropertyContext(client, objectKey); + case X_SELinuxGetPropertyDataContext: + return ProcSELinuxGetPropertyContext(client, dataKey); + case X_SELinuxListProperties: + return ProcSELinuxListProperties(client); + case X_SELinuxSetSelectionCreateContext: + return ProcSELinuxSetCreateContext(client, CTX_SEL); + case X_SELinuxGetSelectionCreateContext: + return ProcSELinuxGetCreateContext(client, CTX_SEL); + case X_SELinuxSetSelectionUseContext: + return ProcSELinuxSetCreateContext(client, USE_SEL); + case X_SELinuxGetSelectionUseContext: + return ProcSELinuxGetCreateContext(client, USE_SEL); + case X_SELinuxGetSelectionContext: + return ProcSELinuxGetSelectionContext(client, objectKey); + case X_SELinuxGetSelectionDataContext: + return ProcSELinuxGetSelectionContext(client, dataKey); + case X_SELinuxListSelections: + return ProcSELinuxListSelections(client); + case X_SELinuxGetClientContext: + return ProcSELinuxGetClientContext(client); + default: + return BadRequest; + } +} + +static int +SProcSELinuxQueryVersion(ClientPtr client) +{ + REQUEST(SELinuxQueryVersionReq); + int n; + + REQUEST_SIZE_MATCH(SELinuxQueryVersionReq); + swaps(&stuff->client_major, n); + swaps(&stuff->client_minor, n); + return ProcSELinuxQueryVersion(client); +} + +static int +SProcSELinuxSetCreateContext(ClientPtr client, unsigned offset) +{ + REQUEST(SELinuxSetCreateContextReq); + int n; + + REQUEST_AT_LEAST_SIZE(SELinuxSetCreateContextReq); + swapl(&stuff->context_len, n); + return ProcSELinuxSetCreateContext(client, offset); +} + +static int +SProcSELinuxSetDeviceContext(ClientPtr client) +{ + REQUEST(SELinuxSetContextReq); + int n; + + REQUEST_AT_LEAST_SIZE(SELinuxSetContextReq); + swapl(&stuff->id, n); + swapl(&stuff->context_len, n); + return ProcSELinuxSetDeviceContext(client); +} + +static int +SProcSELinuxGetDeviceContext(ClientPtr client) +{ + REQUEST(SELinuxGetContextReq); + int n; + + REQUEST_SIZE_MATCH(SELinuxGetContextReq); + swapl(&stuff->id, n); + return ProcSELinuxGetDeviceContext(client); +} + +static int +SProcSELinuxGetDrawableContext(ClientPtr client) +{ + REQUEST(SELinuxGetContextReq); + int n; + + REQUEST_SIZE_MATCH(SELinuxGetContextReq); + swapl(&stuff->id, n); + return ProcSELinuxGetDrawableContext(client); +} + +static int +SProcSELinuxGetPropertyContext(ClientPtr client, pointer privKey) +{ + REQUEST(SELinuxGetPropertyContextReq); + int n; + + REQUEST_SIZE_MATCH(SELinuxGetPropertyContextReq); + swapl(&stuff->window, n); + swapl(&stuff->property, n); + return ProcSELinuxGetPropertyContext(client, privKey); +} + +static int +SProcSELinuxGetSelectionContext(ClientPtr client, pointer privKey) +{ + REQUEST(SELinuxGetContextReq); + int n; + + REQUEST_SIZE_MATCH(SELinuxGetContextReq); + swapl(&stuff->id, n); + return ProcSELinuxGetSelectionContext(client, privKey); +} + +static int +SProcSELinuxListProperties(ClientPtr client) +{ + REQUEST(SELinuxGetContextReq); + int n; + + REQUEST_SIZE_MATCH(SELinuxGetContextReq); + swapl(&stuff->id, n); + return ProcSELinuxListProperties(client); +} + +static int +SProcSELinuxGetClientContext(ClientPtr client) +{ + REQUEST(SELinuxGetContextReq); + int n; + + REQUEST_SIZE_MATCH(SELinuxGetContextReq); + swapl(&stuff->id, n); + return ProcSELinuxGetClientContext(client); +} + +static int +SProcSELinuxDispatch(ClientPtr client) +{ + REQUEST(xReq); + int n; + + swaps(&stuff->length, n); + + switch (stuff->data) { + case X_SELinuxQueryVersion: + return SProcSELinuxQueryVersion(client); + case X_SELinuxSetDeviceCreateContext: + return SProcSELinuxSetCreateContext(client, CTX_DEV); + case X_SELinuxGetDeviceCreateContext: + return ProcSELinuxGetCreateContext(client, CTX_DEV); + case X_SELinuxSetDeviceContext: + return SProcSELinuxSetDeviceContext(client); + case X_SELinuxGetDeviceContext: + return SProcSELinuxGetDeviceContext(client); + case X_SELinuxSetDrawableCreateContext: + return SProcSELinuxSetCreateContext(client, CTX_WIN); + case X_SELinuxGetDrawableCreateContext: + return ProcSELinuxGetCreateContext(client, CTX_WIN); + case X_SELinuxGetDrawableContext: + return SProcSELinuxGetDrawableContext(client); + case X_SELinuxSetPropertyCreateContext: + return SProcSELinuxSetCreateContext(client, CTX_PRP); + case X_SELinuxGetPropertyCreateContext: + return ProcSELinuxGetCreateContext(client, CTX_PRP); + case X_SELinuxSetPropertyUseContext: + return SProcSELinuxSetCreateContext(client, USE_PRP); + case X_SELinuxGetPropertyUseContext: + return ProcSELinuxGetCreateContext(client, USE_PRP); + case X_SELinuxGetPropertyContext: + return SProcSELinuxGetPropertyContext(client, objectKey); + case X_SELinuxGetPropertyDataContext: + return SProcSELinuxGetPropertyContext(client, dataKey); + case X_SELinuxListProperties: + return SProcSELinuxListProperties(client); + case X_SELinuxSetSelectionCreateContext: + return SProcSELinuxSetCreateContext(client, CTX_SEL); + case X_SELinuxGetSelectionCreateContext: + return ProcSELinuxGetCreateContext(client, CTX_SEL); + case X_SELinuxSetSelectionUseContext: + return SProcSELinuxSetCreateContext(client, USE_SEL); + case X_SELinuxGetSelectionUseContext: + return ProcSELinuxGetCreateContext(client, USE_SEL); + case X_SELinuxGetSelectionContext: + return SProcSELinuxGetSelectionContext(client, objectKey); + case X_SELinuxGetSelectionDataContext: + return SProcSELinuxGetSelectionContext(client, dataKey); + case X_SELinuxListSelections: + return ProcSELinuxListSelections(client); + case X_SELinuxGetClientContext: + return SProcSELinuxGetClientContext(client); + default: + return BadRequest; + } +} + + +/* + * Extension Setup / Teardown + */ + +static void +SELinuxResetProc(ExtensionEntry *extEntry) +{ + SELinuxFlaskReset(); + SELinuxLabelReset(); +} + +void +SELinuxExtensionInit(INITARGS) +{ + ExtensionEntry *extEntry; + + /* Check SELinux mode on system, configuration file, and boolean */ + if (!is_selinux_enabled()) { + LogMessage(X_INFO, "SELinux: Disabled on system\n"); + return; + } + if (selinuxEnforcingState == SELINUX_MODE_DISABLED) { + LogMessage(X_INFO, "SELinux: Disabled in configuration file\n"); + return; + } + if (!security_get_boolean_active("xserver_object_manager")) { + LogMessage(X_INFO, "SELinux: Disabled by boolean\n"); + return; + } + + /* Set up XACE hooks */ + SELinuxLabelInit(); + SELinuxFlaskInit(); + + /* Add extension to server */ + extEntry = AddExtension(SELINUX_EXTENSION_NAME, + SELinuxNumberEvents, SELinuxNumberErrors, + ProcSELinuxDispatch, SProcSELinuxDispatch, + SELinuxResetProc, StandardMinorOpcode); + + AddExtensionAlias("Flask", extEntry); +} diff --git a/xorg-server/Xext/xselinux_hooks.c b/xorg-server/Xext/xselinux_hooks.c index 6c8c8cdbe..6075a34e8 100644 --- a/xorg-server/Xext/xselinux_hooks.c +++ b/xorg-server/Xext/xselinux_hooks.c @@ -1,981 +1,938 @@ -/************************************************************ - -Author: Eamon Walsh - -Permission to use, copy, modify, distribute, and sell this software and its -documentation for any purpose is hereby granted without fee, provided that -this permission notice appear in supporting documentation. 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 -AUTHOR 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. - -********************************************************/ - -/* - * Portions of this code copyright (c) 2005 by Trusted Computer Solutions, Inc. - * All rights reserved. - */ - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include -#include -#include - -#include - -#include -#include "selection.h" -#include "inputstr.h" -#include "scrnintstr.h" -#include "windowstr.h" -#include "propertyst.h" -#include "extnsionst.h" -#include "xacestr.h" -#include "../os/osdep.h" -#define _XSELINUX_NEED_FLASK_MAP -#include "xselinuxint.h" - - -/* structure passed to auditing callback */ -typedef struct { - ClientPtr client; /* client */ - DeviceIntPtr dev; /* device */ - char *command; /* client's executable path */ - unsigned id; /* resource id, if any */ - int restype; /* resource type, if any */ - int event; /* event type, if any */ - Atom property; /* property name, if any */ - Atom selection; /* selection name, if any */ - char *extension; /* extension name, if any */ -} SELinuxAuditRec; - -/* private state keys */ -static int subjectKeyIndex; -DevPrivateKey subjectKey = &subjectKeyIndex; -static int objectKeyIndex; -DevPrivateKey objectKey = &objectKeyIndex; -static int dataKeyIndex; -DevPrivateKey dataKey = &dataKeyIndex; - -/* audit file descriptor */ -static int audit_fd; - -/* atoms for window label properties */ -static Atom atom_ctx; -static Atom atom_client_ctx; - -/* The unlabeled SID */ -static security_id_t unlabeled_sid; - -/* forward declarations */ -static void SELinuxScreen(CallbackListPtr *, pointer, pointer); - -/* "true" pointer value for use as callback data */ -static pointer truep = (pointer)1; - - -/* - * Performs an SELinux permission check. - */ -static int -SELinuxDoCheck(SELinuxSubjectRec *subj, SELinuxObjectRec *obj, - security_class_t class, Mask mode, SELinuxAuditRec *auditdata) -{ - /* serverClient requests OK */ - if (subj->privileged) - return Success; - - auditdata->command = subj->command; - errno = 0; - - if (avc_has_perm(subj->sid, obj->sid, class, mode, &subj->aeref, - auditdata) < 0) { - if (mode == DixUnknownAccess) - return Success; /* DixUnknownAccess requests OK ... for now */ - if (errno == EACCES) - return BadAccess; - ErrorF("SELinux: avc_has_perm: unexpected error %d\n", errno); - return BadValue; - } - - return Success; -} - -/* - * Labels a newly connected client. - */ -static void -SELinuxLabelClient(ClientPtr client) -{ - int fd = XaceGetConnectionNumber(client); - SELinuxSubjectRec *subj; - SELinuxObjectRec *obj; - security_context_t ctx; - - subj = dixLookupPrivate(&client->devPrivates, subjectKey); - obj = dixLookupPrivate(&client->devPrivates, objectKey); - - /* Try to get a context from the socket */ - if (fd < 0 || getpeercon_raw(fd, &ctx) < 0) { - /* Otherwise, fall back to a default context */ - ctx = SELinuxDefaultClientLabel(); - } - - /* For local clients, try and determine the executable name */ - if (XaceIsLocal(client)) { - struct ucred creds; - socklen_t len = sizeof(creds); - char path[PATH_MAX + 1]; - size_t bytes; - - memset(&creds, 0, sizeof(creds)); - if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &creds, &len) < 0) - goto finish; - - snprintf(path, PATH_MAX + 1, "/proc/%d/cmdline", creds.pid); - fd = open(path, O_RDONLY); - if (fd < 0) - goto finish; - - bytes = read(fd, path, PATH_MAX + 1); - close(fd); - if (bytes <= 0) - goto finish; - - subj->command = xalloc(bytes); - if (!subj->command) - goto finish; - - memcpy(subj->command, path, bytes); - subj->command[bytes - 1] = 0; - } - -finish: - /* Get a SID from the context */ - if (avc_context_to_sid_raw(ctx, &subj->sid) < 0) - FatalError("SELinux: client %d: context_to_sid_raw(%s) failed\n", - client->index, ctx); - - obj->sid = subj->sid; - freecon(ctx); -} - -/* - * Labels initial server objects. - */ -static void -SELinuxLabelInitial(void) -{ - int i; - XaceScreenAccessRec srec; - SELinuxSubjectRec *subj; - SELinuxObjectRec *obj; - security_context_t ctx; - pointer unused; - - /* Do the serverClient */ - subj = dixLookupPrivate(&serverClient->devPrivates, subjectKey); - obj = dixLookupPrivate(&serverClient->devPrivates, objectKey); - subj->privileged = 1; - - /* Use the context of the X server process for the serverClient */ - if (getcon_raw(&ctx) < 0) - FatalError("SELinux: couldn't get context of X server process\n"); - - /* Get a SID from the context */ - if (avc_context_to_sid_raw(ctx, &subj->sid) < 0) - FatalError("SELinux: serverClient: context_to_sid(%s) failed\n", ctx); - - obj->sid = subj->sid; - freecon(ctx); - - srec.client = serverClient; - srec.access_mode = DixCreateAccess; - srec.status = Success; - - for (i = 0; i < screenInfo.numScreens; i++) { - /* Do the screen object */ - srec.screen = screenInfo.screens[i]; - SELinuxScreen(NULL, NULL, &srec); - - /* Do the default colormap */ - dixLookupResourceByType(&unused, screenInfo.screens[i]->defColormap, - RT_COLORMAP, serverClient, DixCreateAccess); - } -} - -/* - * Labels new resource objects. - */ -static int -SELinuxLabelResource(XaceResourceAccessRec *rec, SELinuxSubjectRec *subj, - SELinuxObjectRec *obj, security_class_t class) -{ - int offset; - security_id_t tsid; - - /* Check for a create context */ - if (rec->rtype & RC_DRAWABLE && subj->win_create_sid) { - obj->sid = subj->win_create_sid; - return Success; - } - - if (rec->parent) - offset = dixLookupPrivateOffset(rec->ptype); - - if (rec->parent && offset >= 0) { - /* Use the SID of the parent object in the labeling operation */ - PrivateRec **privatePtr = DEVPRIV_AT(rec->parent, offset); - SELinuxObjectRec *pobj = dixLookupPrivate(privatePtr, objectKey); - tsid = pobj->sid; - } else { - /* Use the SID of the subject */ - tsid = subj->sid; - } - - /* Perform a transition to obtain the final SID */ - if (avc_compute_create(subj->sid, tsid, class, &obj->sid) < 0) { - ErrorF("SELinux: a compute_create call failed!\n"); - return BadValue; - } - - return Success; -} - - -/* - * Libselinux Callbacks - */ - -static int -SELinuxAudit(void *auditdata, - security_class_t class, - char *msgbuf, - size_t msgbufsize) -{ - SELinuxAuditRec *audit = auditdata; - ClientPtr client = audit->client; - char idNum[16]; - const char *propertyName, *selectionName; - int major = -1, minor = -1; - - if (client) { - REQUEST(xReq); - if (stuff) { - major = stuff->reqType; - minor = MinorOpcodeOfRequest(client); - } - } - if (audit->id) - snprintf(idNum, 16, "%x", audit->id); - - propertyName = audit->property ? NameForAtom(audit->property) : NULL; - selectionName = audit->selection ? NameForAtom(audit->selection) : NULL; - - return snprintf(msgbuf, msgbufsize, - "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", - (major >= 0) ? "request=" : "", - (major >= 0) ? LookupRequestName(major, minor) : "", - audit->command ? " comm=" : "", - audit->command ? audit->command : "", - audit->dev ? " xdevice=\"" : "", - audit->dev ? audit->dev->name : "", - audit->dev ? "\"" : "", - audit->id ? " resid=" : "", - audit->id ? idNum : "", - audit->restype ? " restype=" : "", - audit->restype ? LookupResourceName(audit->restype) : "", - audit->event ? " event=" : "", - audit->event ? LookupEventName(audit->event & 127) : "", - audit->property ? " property=" : "", - audit->property ? propertyName : "", - audit->selection ? " selection=" : "", - audit->selection ? selectionName : "", - audit->extension ? " extension=" : "", - audit->extension ? audit->extension : ""); -} - -static int -SELinuxLog(int type, const char *fmt, ...) -{ - va_list ap; - char buf[MAX_AUDIT_MESSAGE_LENGTH]; - int rc, aut; - - switch (type) { - case SELINUX_INFO: - aut = AUDIT_USER_MAC_POLICY_LOAD; - break; - case SELINUX_AVC: - aut = AUDIT_USER_AVC; - break; - default: - aut = AUDIT_USER_SELINUX_ERR; - break; - } - - va_start(ap, fmt); - vsnprintf(buf, MAX_AUDIT_MESSAGE_LENGTH, fmt, ap); - rc = audit_log_user_avc_message(audit_fd, aut, buf, NULL, NULL, NULL, 0); - va_end(ap); - LogMessageVerb(X_WARNING, 0, "%s", buf); - return 0; -} - -/* - * XACE Callbacks - */ - -static void -SELinuxDevice(CallbackListPtr *pcbl, pointer unused, pointer calldata) -{ - XaceDeviceAccessRec *rec = calldata; - SELinuxSubjectRec *subj; - SELinuxObjectRec *obj; - SELinuxAuditRec auditdata = { .client = rec->client, .dev = rec->dev }; - security_class_t cls; - int rc; - - subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); - obj = dixLookupPrivate(&rec->dev->devPrivates, objectKey); - - /* If this is a new object that needs labeling, do it now */ - if (rec->access_mode & DixCreateAccess) { - SELinuxSubjectRec *dsubj; - dsubj = dixLookupPrivate(&rec->dev->devPrivates, subjectKey); - - if (subj->dev_create_sid) { - /* Label the device with the create context */ - obj->sid = subj->dev_create_sid; - dsubj->sid = subj->dev_create_sid; - } else { - /* Label the device directly with the process SID */ - obj->sid = subj->sid; - dsubj->sid = subj->sid; - } - } - - cls = IsPointerDevice(rec->dev) ? SECCLASS_X_POINTER : SECCLASS_X_KEYBOARD; - rc = SELinuxDoCheck(subj, obj, cls, rec->access_mode, &auditdata); - if (rc != Success) - rec->status = rc; -} - -static void -SELinuxSend(CallbackListPtr *pcbl, pointer unused, pointer calldata) -{ - XaceSendAccessRec *rec = calldata; - SELinuxSubjectRec *subj; - SELinuxObjectRec *obj, ev_sid; - SELinuxAuditRec auditdata = { .client = rec->client, .dev = rec->dev }; - security_class_t class; - int rc, i, type; - - if (rec->dev) - subj = dixLookupPrivate(&rec->dev->devPrivates, subjectKey); - else - subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); - - obj = dixLookupPrivate(&rec->pWin->devPrivates, objectKey); - - /* Check send permission on window */ - rc = SELinuxDoCheck(subj, obj, SECCLASS_X_DRAWABLE, DixSendAccess, - &auditdata); - if (rc != Success) - goto err; - - /* Check send permission on specific event types */ - for (i = 0; i < rec->count; i++) { - type = rec->events[i].u.u.type; - class = (type & 128) ? SECCLASS_X_FAKEEVENT : SECCLASS_X_EVENT; - - rc = SELinuxEventToSID(type, obj->sid, &ev_sid); - if (rc != Success) - goto err; - - auditdata.event = type; - rc = SELinuxDoCheck(subj, &ev_sid, class, DixSendAccess, &auditdata); - if (rc != Success) - goto err; - } - return; -err: - rec->status = rc; -} - -static void -SELinuxReceive(CallbackListPtr *pcbl, pointer unused, pointer calldata) -{ - XaceReceiveAccessRec *rec = calldata; - SELinuxSubjectRec *subj; - SELinuxObjectRec *obj, ev_sid; - SELinuxAuditRec auditdata = { .client = NULL }; - security_class_t class; - int rc, i, type; - - subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); - obj = dixLookupPrivate(&rec->pWin->devPrivates, objectKey); - - /* Check receive permission on window */ - rc = SELinuxDoCheck(subj, obj, SECCLASS_X_DRAWABLE, DixReceiveAccess, - &auditdata); - if (rc != Success) - goto err; - - /* Check receive permission on specific event types */ - for (i = 0; i < rec->count; i++) { - type = rec->events[i].u.u.type; - class = (type & 128) ? SECCLASS_X_FAKEEVENT : SECCLASS_X_EVENT; - - rc = SELinuxEventToSID(type, obj->sid, &ev_sid); - if (rc != Success) - goto err; - - auditdata.event = type; - rc = SELinuxDoCheck(subj, &ev_sid, class, DixReceiveAccess, &auditdata); - if (rc != Success) - goto err; - } - return; -err: - rec->status = rc; -} - -static void -SELinuxExtension(CallbackListPtr *pcbl, pointer unused, pointer calldata) -{ - XaceExtAccessRec *rec = calldata; - SELinuxSubjectRec *subj, *serv; - SELinuxObjectRec *obj; - SELinuxAuditRec auditdata = { .client = rec->client }; - int rc; - - subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); - obj = dixLookupPrivate(&rec->ext->devPrivates, objectKey); - - /* If this is a new object that needs labeling, do it now */ - /* XXX there should be a separate callback for this */ - if (obj->sid == unlabeled_sid) { - security_id_t sid; - - serv = dixLookupPrivate(&serverClient->devPrivates, subjectKey); - rc = SELinuxExtensionToSID(rec->ext->name, &sid); - if (rc != Success) { - rec->status = rc; - return; - } - - /* Perform a transition to obtain the final SID */ - if (avc_compute_create(serv->sid, sid, SECCLASS_X_EXTENSION, - &obj->sid) < 0) { - ErrorF("SELinux: a SID transition call failed!\n"); - rec->status = BadValue; - return; - } - } - - /* Perform the security check */ - auditdata.extension = rec->ext->name; - rc = SELinuxDoCheck(subj, obj, SECCLASS_X_EXTENSION, rec->access_mode, - &auditdata); - if (rc != Success) - rec->status = rc; -} - -static void -SELinuxSelection(CallbackListPtr *pcbl, pointer unused, pointer calldata) -{ - XaceSelectionAccessRec *rec = calldata; - SELinuxSubjectRec *subj; - SELinuxObjectRec *obj, *data; - Selection *pSel = *rec->ppSel; - Atom name = pSel->selection; - Mask access_mode = rec->access_mode; - SELinuxAuditRec auditdata = { .client = rec->client, .selection = name }; - security_id_t tsid; - int rc; - - subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); - obj = dixLookupPrivate(&pSel->devPrivates, objectKey); - - /* If this is a new object that needs labeling, do it now */ - if (access_mode & DixCreateAccess) { - rc = SELinuxSelectionToSID(name, subj, &obj->sid, &obj->poly); - if (rc != Success) - obj->sid = unlabeled_sid; - access_mode = DixSetAttrAccess; - } - /* If this is a polyinstantiated object, find the right instance */ - else if (obj->poly) { - rc = SELinuxSelectionToSID(name, subj, &tsid, NULL); - if (rc != Success) { - rec->status = rc; - return; - } - while (pSel->selection != name || obj->sid != tsid) { - if ((pSel = pSel->next) == NULL) - break; - obj = dixLookupPrivate(&pSel->devPrivates, objectKey); - } - - if (pSel) - *rec->ppSel = pSel; - else { - rec->status = BadMatch; - return; - } - } - - /* Perform the security check */ - rc = SELinuxDoCheck(subj, obj, SECCLASS_X_SELECTION, access_mode, - &auditdata); - if (rc != Success) - rec->status = rc; - - /* Label the content (advisory only) */ - if (access_mode & DixSetAttrAccess) { - data = dixLookupPrivate(&pSel->devPrivates, dataKey); - if (subj->sel_create_sid) - data->sid = subj->sel_create_sid; - else - data->sid = obj->sid; - } -} - -static void -SELinuxProperty(CallbackListPtr *pcbl, pointer unused, pointer calldata) -{ - XacePropertyAccessRec *rec = calldata; - SELinuxSubjectRec *subj; - SELinuxObjectRec *obj, *data; - PropertyPtr pProp = *rec->ppProp; - Atom name = pProp->propertyName; - SELinuxAuditRec auditdata = { .client = rec->client, .property = name }; - security_id_t tsid; - int rc; - - /* Don't care about the new content check */ - if (rec->access_mode & DixPostAccess) - return; - - subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); - obj = dixLookupPrivate(&pProp->devPrivates, objectKey); - - /* If this is a new object that needs labeling, do it now */ - if (rec->access_mode & DixCreateAccess) { - rc = SELinuxPropertyToSID(name, subj, &obj->sid, &obj->poly); - if (rc != Success) { - rec->status = rc; - return; - } - } - /* If this is a polyinstantiated object, find the right instance */ - else if (obj->poly) { - rc = SELinuxPropertyToSID(name, subj, &tsid, NULL); - if (rc != Success) { - rec->status = rc; - return; - } - while (pProp->propertyName != name || obj->sid != tsid) { - if ((pProp = pProp->next) == NULL) - break; - obj = dixLookupPrivate(&pProp->devPrivates, objectKey); - } - - if (pProp) - *rec->ppProp = pProp; - else { - rec->status = BadMatch; - return; - } - } - - /* Perform the security check */ - rc = SELinuxDoCheck(subj, obj, SECCLASS_X_PROPERTY, rec->access_mode, - &auditdata); - if (rc != Success) - rec->status = rc; - - /* Label the content (advisory only) */ - if (rec->access_mode & DixWriteAccess) { - data = dixLookupPrivate(&pProp->devPrivates, dataKey); - if (subj->prp_create_sid) - data->sid = subj->prp_create_sid; - else - data->sid = obj->sid; - } -} - -static void -SELinuxResource(CallbackListPtr *pcbl, pointer unused, pointer calldata) -{ - XaceResourceAccessRec *rec = calldata; - SELinuxSubjectRec *subj; - SELinuxObjectRec *obj; - SELinuxAuditRec auditdata = { .client = rec->client }; - Mask access_mode = rec->access_mode; - PrivateRec **privatePtr; - security_class_t class; - int rc, offset; - - subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); - - /* Determine if the resource object has a devPrivates field */ - offset = dixLookupPrivateOffset(rec->rtype); - if (offset < 0) { - /* No: use the SID of the owning client */ - class = SECCLASS_X_RESOURCE; - privatePtr = &clients[CLIENT_ID(rec->id)]->devPrivates; - obj = dixLookupPrivate(privatePtr, objectKey); - } else { - /* Yes: use the SID from the resource object itself */ - class = SELinuxTypeToClass(rec->rtype); - privatePtr = DEVPRIV_AT(rec->res, offset); - obj = dixLookupPrivate(privatePtr, objectKey); - } - - /* If this is a new object that needs labeling, do it now */ - if (access_mode & DixCreateAccess && offset >= 0) { - rc = SELinuxLabelResource(rec, subj, obj, class); - if (rc != Success) { - rec->status = rc; - return; - } - } - - /* Collapse generic resource permissions down to read/write */ - if (class == SECCLASS_X_RESOURCE) { - access_mode = !!(rec->access_mode & SELinuxReadMask); /* rd */ - access_mode |= !!(rec->access_mode & ~SELinuxReadMask) << 1; /* wr */ - } - - /* Perform the security check */ - auditdata.restype = rec->rtype; - auditdata.id = rec->id; - rc = SELinuxDoCheck(subj, obj, class, access_mode, &auditdata); - if (rc != Success) - rec->status = rc; - - /* Perform the background none check on windows */ - if (access_mode & DixCreateAccess && rec->rtype == RT_WINDOW) { - rc = SELinuxDoCheck(subj, obj, class, DixBlendAccess, &auditdata); - if (rc != Success) - ((WindowPtr)rec->res)->forcedBG = TRUE; - } -} - -static void -SELinuxScreen(CallbackListPtr *pcbl, pointer is_saver, pointer calldata) -{ - XaceScreenAccessRec *rec = calldata; - SELinuxSubjectRec *subj; - SELinuxObjectRec *obj; - SELinuxAuditRec auditdata = { .client = rec->client }; - Mask access_mode = rec->access_mode; - int rc; - - subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); - obj = dixLookupPrivate(&rec->screen->devPrivates, objectKey); - - /* If this is a new object that needs labeling, do it now */ - if (access_mode & DixCreateAccess) { - /* Perform a transition to obtain the final SID */ - if (avc_compute_create(subj->sid, subj->sid, SECCLASS_X_SCREEN, - &obj->sid) < 0) { - ErrorF("SELinux: a compute_create call failed!\n"); - rec->status = BadValue; - return; - } - } - - if (is_saver) - access_mode <<= 2; - - rc = SELinuxDoCheck(subj, obj, SECCLASS_X_SCREEN, access_mode, &auditdata); - if (rc != Success) - rec->status = rc; -} - -static void -SELinuxClient(CallbackListPtr *pcbl, pointer unused, pointer calldata) -{ - XaceClientAccessRec *rec = calldata; - SELinuxSubjectRec *subj; - SELinuxObjectRec *obj; - SELinuxAuditRec auditdata = { .client = rec->client }; - int rc; - - subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); - obj = dixLookupPrivate(&rec->target->devPrivates, objectKey); - - rc = SELinuxDoCheck(subj, obj, SECCLASS_X_CLIENT, rec->access_mode, - &auditdata); - if (rc != Success) - rec->status = rc; -} - -static void -SELinuxServer(CallbackListPtr *pcbl, pointer unused, pointer calldata) -{ - XaceServerAccessRec *rec = calldata; - SELinuxSubjectRec *subj; - SELinuxObjectRec *obj; - SELinuxAuditRec auditdata = { .client = rec->client }; - int rc; - - subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); - obj = dixLookupPrivate(&serverClient->devPrivates, objectKey); - - rc = SELinuxDoCheck(subj, obj, SECCLASS_X_SERVER, rec->access_mode, - &auditdata); - if (rc != Success) - rec->status = rc; -} - - -/* - * DIX Callbacks - */ - -static void -SELinuxClientState(CallbackListPtr *pcbl, pointer unused, pointer calldata) -{ - NewClientInfoRec *pci = calldata; - - switch (pci->client->clientState) { - case ClientStateInitial: - SELinuxLabelClient(pci->client); - break; - - default: - break; - } -} - -static void -SELinuxResourceState(CallbackListPtr *pcbl, pointer unused, pointer calldata) -{ - ResourceStateInfoRec *rec = calldata; - SELinuxSubjectRec *subj; - SELinuxObjectRec *obj; - WindowPtr pWin; - - if (rec->type != RT_WINDOW) - return; - if (rec->state != ResourceStateAdding) - return; - - pWin = (WindowPtr)rec->value; - subj = dixLookupPrivate(&wClient(pWin)->devPrivates, subjectKey); - - if (subj->sid) { - security_context_t ctx; - int rc = avc_sid_to_context_raw(subj->sid, &ctx); - if (rc < 0) - FatalError("SELinux: Failed to get security context!\n"); - rc = dixChangeWindowProperty(serverClient, - pWin, atom_client_ctx, XA_STRING, 8, - PropModeReplace, strlen(ctx), ctx, FALSE); - if (rc != Success) - FatalError("SELinux: Failed to set label property on window!\n"); - freecon(ctx); - } else - FatalError("SELinux: Unexpected unlabeled client found\n"); - - obj = dixLookupPrivate(&pWin->devPrivates, objectKey); - - if (obj->sid) { - security_context_t ctx; - int rc = avc_sid_to_context_raw(obj->sid, &ctx); - if (rc < 0) - FatalError("SELinux: Failed to get security context!\n"); - rc = dixChangeWindowProperty(serverClient, - pWin, atom_ctx, XA_STRING, 8, - PropModeReplace, strlen(ctx), ctx, FALSE); - if (rc != Success) - FatalError("SELinux: Failed to set label property on window!\n"); - freecon(ctx); - } else - FatalError("SELinux: Unexpected unlabeled window found\n"); -} - - -/* - * DevPrivates Callbacks - */ - -static void -SELinuxSubjectInit(CallbackListPtr *pcbl, pointer unused, pointer calldata) -{ - PrivateCallbackRec *rec = calldata; - SELinuxSubjectRec *subj = *rec->value; - - subj->sid = unlabeled_sid; - - avc_entry_ref_init(&subj->aeref); -} - -static void -SELinuxSubjectFree(CallbackListPtr *pcbl, pointer unused, pointer calldata) -{ - PrivateCallbackRec *rec = calldata; - SELinuxSubjectRec *subj = *rec->value; - - xfree(subj->command); -} - -static void -SELinuxObjectInit(CallbackListPtr *pcbl, pointer unused, pointer calldata) -{ - PrivateCallbackRec *rec = calldata; - SELinuxObjectRec *obj = *rec->value; - - obj->sid = unlabeled_sid; -} - -static int netlink_fd; - -static void -SELinuxBlockHandler(void *data, struct timeval **tv, void *read_mask) -{ -} - -static void -SELinuxWakeupHandler(void *data, int err, void *read_mask) -{ - if (FD_ISSET(netlink_fd, (fd_set *)read_mask)) - avc_netlink_check_nb(); -} - -void -SELinuxFlaskReset(void) -{ - /* Unregister callbacks */ - DeleteCallback(&ClientStateCallback, SELinuxClientState, NULL); - DeleteCallback(&ResourceStateCallback, SELinuxResourceState, NULL); - - XaceDeleteCallback(XACE_EXT_DISPATCH, SELinuxExtension, NULL); - XaceDeleteCallback(XACE_RESOURCE_ACCESS, SELinuxResource, NULL); - XaceDeleteCallback(XACE_DEVICE_ACCESS, SELinuxDevice, NULL); - XaceDeleteCallback(XACE_PROPERTY_ACCESS, SELinuxProperty, NULL); - XaceDeleteCallback(XACE_SEND_ACCESS, SELinuxSend, NULL); - XaceDeleteCallback(XACE_RECEIVE_ACCESS, SELinuxReceive, NULL); - XaceDeleteCallback(XACE_CLIENT_ACCESS, SELinuxClient, NULL); - XaceDeleteCallback(XACE_EXT_ACCESS, SELinuxExtension, NULL); - XaceDeleteCallback(XACE_SERVER_ACCESS, SELinuxServer, NULL); - XaceDeleteCallback(XACE_SELECTION_ACCESS, SELinuxSelection, NULL); - XaceDeleteCallback(XACE_SCREEN_ACCESS, SELinuxScreen, NULL); - XaceDeleteCallback(XACE_SCREENSAVER_ACCESS, SELinuxScreen, truep); - - /* Tear down SELinux stuff */ - audit_close(audit_fd); - avc_netlink_release_fd(); - RemoveBlockAndWakeupHandlers(SELinuxBlockHandler, SELinuxWakeupHandler, - NULL); - RemoveGeneralSocket(netlink_fd); - - avc_destroy(); -} - -void -SELinuxFlaskInit(void) -{ - struct selinux_opt avc_option = { AVC_OPT_SETENFORCE, (char *)0 }; - security_context_t ctx; - int ret = TRUE; - - switch(selinuxEnforcingState) { - case SELINUX_MODE_ENFORCING: - LogMessage(X_INFO, "SELinux: Configured in enforcing mode\n"); - avc_option.value = (char *)1; - break; - case SELINUX_MODE_PERMISSIVE: - LogMessage(X_INFO, "SELinux: Configured in permissive mode\n"); - avc_option.value = (char *)0; - break; - default: - avc_option.type = AVC_OPT_UNUSED; - break; - } - - /* Set up SELinux stuff */ - selinux_set_callback(SELINUX_CB_LOG, (union selinux_callback)SELinuxLog); - selinux_set_callback(SELINUX_CB_AUDIT, (union selinux_callback)SELinuxAudit); - - if (selinux_set_mapping(map) < 0) { - if (errno == EINVAL) { - ErrorF("SELinux: Invalid object class mapping, disabling SELinux support.\n"); - return; - } - FatalError("SELinux: Failed to set up security class mapping\n"); - } - - if (avc_open(&avc_option, 1) < 0) - FatalError("SELinux: Couldn't initialize SELinux userspace AVC\n"); - - if (security_get_initial_context_raw("unlabeled", &ctx) < 0) - FatalError("SELinux: Failed to look up unlabeled context\n"); - if (avc_context_to_sid_raw(ctx, &unlabeled_sid) < 0) - FatalError("SELinux: a context_to_SID call failed!\n"); - freecon(ctx); - - /* Prepare for auditing */ - audit_fd = audit_open(); - if (audit_fd < 0) - FatalError("SELinux: Failed to open the system audit log\n"); - - /* Allocate private storage */ - if (!dixRequestPrivate(subjectKey, sizeof(SELinuxSubjectRec)) || - !dixRequestPrivate(objectKey, sizeof(SELinuxObjectRec)) || - !dixRequestPrivate(dataKey, sizeof(SELinuxObjectRec))) - FatalError("SELinux: Failed to allocate private storage.\n"); - - /* Create atoms for doing window labeling */ - atom_ctx = MakeAtom("_SELINUX_CONTEXT", 16, TRUE); - if (atom_ctx == BAD_RESOURCE) - FatalError("SELinux: Failed to create atom\n"); - atom_client_ctx = MakeAtom("_SELINUX_CLIENT_CONTEXT", 23, TRUE); - if (atom_client_ctx == BAD_RESOURCE) - FatalError("SELinux: Failed to create atom\n"); - - netlink_fd = avc_netlink_acquire_fd(); - AddGeneralSocket(netlink_fd); - RegisterBlockAndWakeupHandlers(SELinuxBlockHandler, SELinuxWakeupHandler, - NULL); - - /* Register callbacks */ - ret &= dixRegisterPrivateInitFunc(subjectKey, SELinuxSubjectInit, NULL); - ret &= dixRegisterPrivateDeleteFunc(subjectKey, SELinuxSubjectFree, NULL); - ret &= dixRegisterPrivateInitFunc(objectKey, SELinuxObjectInit, NULL); - ret &= dixRegisterPrivateInitFunc(dataKey, SELinuxObjectInit, NULL); - - ret &= AddCallback(&ClientStateCallback, SELinuxClientState, NULL); - ret &= AddCallback(&ResourceStateCallback, SELinuxResourceState, NULL); - - ret &= XaceRegisterCallback(XACE_EXT_DISPATCH, SELinuxExtension, NULL); - ret &= XaceRegisterCallback(XACE_RESOURCE_ACCESS, SELinuxResource, NULL); - ret &= XaceRegisterCallback(XACE_DEVICE_ACCESS, SELinuxDevice, NULL); - ret &= XaceRegisterCallback(XACE_PROPERTY_ACCESS, SELinuxProperty, NULL); - ret &= XaceRegisterCallback(XACE_SEND_ACCESS, SELinuxSend, NULL); - ret &= XaceRegisterCallback(XACE_RECEIVE_ACCESS, SELinuxReceive, NULL); - ret &= XaceRegisterCallback(XACE_CLIENT_ACCESS, SELinuxClient, NULL); - ret &= XaceRegisterCallback(XACE_EXT_ACCESS, SELinuxExtension, NULL); - ret &= XaceRegisterCallback(XACE_SERVER_ACCESS, SELinuxServer, NULL); - ret &= XaceRegisterCallback(XACE_SELECTION_ACCESS, SELinuxSelection, NULL); - ret &= XaceRegisterCallback(XACE_SCREEN_ACCESS, SELinuxScreen, NULL); - ret &= XaceRegisterCallback(XACE_SCREENSAVER_ACCESS, SELinuxScreen, truep); - if (!ret) - FatalError("SELinux: Failed to register one or more callbacks\n"); - - /* Label objects that were created before we could register ourself */ - SELinuxLabelInitial(); -} +/************************************************************ + +Author: Eamon Walsh + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +this permission notice appear in supporting documentation. 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 +AUTHOR 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. + +********************************************************/ + +/* + * Portions of this code copyright (c) 2005 by Trusted Computer Solutions, Inc. + * All rights reserved. + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include +#include + +#include + +#include +#include "selection.h" +#include "inputstr.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "propertyst.h" +#include "extnsionst.h" +#include "xacestr.h" +#include "../os/osdep.h" +#define _XSELINUX_NEED_FLASK_MAP +#include "xselinuxint.h" + + +/* structure passed to auditing callback */ +typedef struct { + ClientPtr client; /* client */ + DeviceIntPtr dev; /* device */ + char *command; /* client's executable path */ + unsigned id; /* resource id, if any */ + int restype; /* resource type, if any */ + int event; /* event type, if any */ + Atom property; /* property name, if any */ + Atom selection; /* selection name, if any */ + char *extension; /* extension name, if any */ +} SELinuxAuditRec; + +/* private state keys */ +static int subjectKeyIndex; +DevPrivateKey subjectKey = &subjectKeyIndex; +static int objectKeyIndex; +DevPrivateKey objectKey = &objectKeyIndex; +static int dataKeyIndex; +DevPrivateKey dataKey = &dataKeyIndex; + +/* audit file descriptor */ +static int audit_fd; + +/* atoms for window label properties */ +static Atom atom_ctx; +static Atom atom_client_ctx; + +/* The unlabeled SID */ +static security_id_t unlabeled_sid; + +/* forward declarations */ +static void SELinuxScreen(CallbackListPtr *, pointer, pointer); + +/* "true" pointer value for use as callback data */ +static pointer truep = (pointer)1; + + +/* + * Performs an SELinux permission check. + */ +static int +SELinuxDoCheck(SELinuxSubjectRec *subj, SELinuxObjectRec *obj, + security_class_t class, Mask mode, SELinuxAuditRec *auditdata) +{ + /* serverClient requests OK */ + if (subj->privileged) + return Success; + + auditdata->command = subj->command; + errno = 0; + + if (avc_has_perm(subj->sid, obj->sid, class, mode, &subj->aeref, + auditdata) < 0) { + if (mode == DixUnknownAccess) + return Success; /* DixUnknownAccess requests OK ... for now */ + if (errno == EACCES) + return BadAccess; + ErrorF("SELinux: avc_has_perm: unexpected error %d\n", errno); + return BadValue; + } + + return Success; +} + +/* + * Labels a newly connected client. + */ +static void +SELinuxLabelClient(ClientPtr client) +{ + int fd = XaceGetConnectionNumber(client); + SELinuxSubjectRec *subj; + SELinuxObjectRec *obj; + security_context_t ctx; + + subj = dixLookupPrivate(&client->devPrivates, subjectKey); + obj = dixLookupPrivate(&client->devPrivates, objectKey); + + /* Try to get a context from the socket */ + if (fd < 0 || getpeercon_raw(fd, &ctx) < 0) { + /* Otherwise, fall back to a default context */ + ctx = SELinuxDefaultClientLabel(); + } + + /* For local clients, try and determine the executable name */ + if (XaceIsLocal(client)) { + struct ucred creds; + socklen_t len = sizeof(creds); + char path[PATH_MAX + 1]; + size_t bytes; + + memset(&creds, 0, sizeof(creds)); + if (getsockopt(fd, SOL_SOCKET, SO_PEERCRED, &creds, &len) < 0) + goto finish; + + snprintf(path, PATH_MAX + 1, "/proc/%d/cmdline", creds.pid); + fd = open(path, O_RDONLY); + if (fd < 0) + goto finish; + + bytes = read(fd, path, PATH_MAX + 1); + close(fd); + if (bytes <= 0) + goto finish; + + strncpy(subj->command, path, COMMAND_LEN - 1); + } + +finish: + /* Get a SID from the context */ + if (avc_context_to_sid_raw(ctx, &subj->sid) < 0) + FatalError("SELinux: client %d: context_to_sid_raw(%s) failed\n", + client->index, ctx); + + obj->sid = subj->sid; + freecon(ctx); +} + +/* + * Labels initial server objects. + */ +static void +SELinuxLabelInitial(void) +{ + int i; + XaceScreenAccessRec srec; + SELinuxSubjectRec *subj; + SELinuxObjectRec *obj; + security_context_t ctx; + pointer unused; + + /* Do the serverClient */ + subj = dixLookupPrivate(&serverClient->devPrivates, subjectKey); + obj = dixLookupPrivate(&serverClient->devPrivates, objectKey); + subj->privileged = 1; + + /* Use the context of the X server process for the serverClient */ + if (getcon_raw(&ctx) < 0) + FatalError("SELinux: couldn't get context of X server process\n"); + + /* Get a SID from the context */ + if (avc_context_to_sid_raw(ctx, &subj->sid) < 0) + FatalError("SELinux: serverClient: context_to_sid(%s) failed\n", ctx); + + obj->sid = subj->sid; + freecon(ctx); + + srec.client = serverClient; + srec.access_mode = DixCreateAccess; + srec.status = Success; + + for (i = 0; i < screenInfo.numScreens; i++) { + /* Do the screen object */ + srec.screen = screenInfo.screens[i]; + SELinuxScreen(NULL, NULL, &srec); + + /* Do the default colormap */ + dixLookupResourceByType(&unused, screenInfo.screens[i]->defColormap, + RT_COLORMAP, serverClient, DixCreateAccess); + } +} + +/* + * Labels new resource objects. + */ +static int +SELinuxLabelResource(XaceResourceAccessRec *rec, SELinuxSubjectRec *subj, + SELinuxObjectRec *obj, security_class_t class) +{ + int offset; + security_id_t tsid; + + /* Check for a create context */ + if (rec->rtype & RC_DRAWABLE && subj->win_create_sid) { + obj->sid = subj->win_create_sid; + return Success; + } + + if (rec->parent) + offset = dixLookupPrivateOffset(rec->ptype); + + if (rec->parent && offset >= 0) { + /* Use the SID of the parent object in the labeling operation */ + PrivateRec **privatePtr = DEVPRIV_AT(rec->parent, offset); + SELinuxObjectRec *pobj = dixLookupPrivate(privatePtr, objectKey); + tsid = pobj->sid; + } else { + /* Use the SID of the subject */ + tsid = subj->sid; + } + + /* Perform a transition to obtain the final SID */ + if (avc_compute_create(subj->sid, tsid, class, &obj->sid) < 0) { + ErrorF("SELinux: a compute_create call failed!\n"); + return BadValue; + } + + return Success; +} + + +/* + * Libselinux Callbacks + */ + +static int +SELinuxAudit(void *auditdata, + security_class_t class, + char *msgbuf, + size_t msgbufsize) +{ + SELinuxAuditRec *audit = auditdata; + ClientPtr client = audit->client; + char idNum[16]; + const char *propertyName, *selectionName; + int major = -1, minor = -1; + + if (client) { + REQUEST(xReq); + if (stuff) { + major = stuff->reqType; + minor = MinorOpcodeOfRequest(client); + } + } + if (audit->id) + snprintf(idNum, 16, "%x", audit->id); + + propertyName = audit->property ? NameForAtom(audit->property) : NULL; + selectionName = audit->selection ? NameForAtom(audit->selection) : NULL; + + return snprintf(msgbuf, msgbufsize, + "%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s%s", + (major >= 0) ? "request=" : "", + (major >= 0) ? LookupRequestName(major, minor) : "", + audit->command ? " comm=" : "", + audit->command ? audit->command : "", + audit->dev ? " xdevice=\"" : "", + audit->dev ? audit->dev->name : "", + audit->dev ? "\"" : "", + audit->id ? " resid=" : "", + audit->id ? idNum : "", + audit->restype ? " restype=" : "", + audit->restype ? LookupResourceName(audit->restype) : "", + audit->event ? " event=" : "", + audit->event ? LookupEventName(audit->event & 127) : "", + audit->property ? " property=" : "", + audit->property ? propertyName : "", + audit->selection ? " selection=" : "", + audit->selection ? selectionName : "", + audit->extension ? " extension=" : "", + audit->extension ? audit->extension : ""); +} + +static int +SELinuxLog(int type, const char *fmt, ...) +{ + va_list ap; + char buf[MAX_AUDIT_MESSAGE_LENGTH]; + int rc, aut; + + switch (type) { + case SELINUX_INFO: + aut = AUDIT_USER_MAC_POLICY_LOAD; + break; + case SELINUX_AVC: + aut = AUDIT_USER_AVC; + break; + default: + aut = AUDIT_USER_SELINUX_ERR; + break; + } + + va_start(ap, fmt); + vsnprintf(buf, MAX_AUDIT_MESSAGE_LENGTH, fmt, ap); + rc = audit_log_user_avc_message(audit_fd, aut, buf, NULL, NULL, NULL, 0); + va_end(ap); + LogMessageVerb(X_WARNING, 0, "%s", buf); + return 0; +} + +/* + * XACE Callbacks + */ + +static void +SELinuxDevice(CallbackListPtr *pcbl, pointer unused, pointer calldata) +{ + XaceDeviceAccessRec *rec = calldata; + SELinuxSubjectRec *subj; + SELinuxObjectRec *obj; + SELinuxAuditRec auditdata = { .client = rec->client, .dev = rec->dev }; + security_class_t cls; + int rc; + + subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); + obj = dixLookupPrivate(&rec->dev->devPrivates, objectKey); + + /* If this is a new object that needs labeling, do it now */ + if (rec->access_mode & DixCreateAccess) { + SELinuxSubjectRec *dsubj; + dsubj = dixLookupPrivate(&rec->dev->devPrivates, subjectKey); + + if (subj->dev_create_sid) { + /* Label the device with the create context */ + obj->sid = subj->dev_create_sid; + dsubj->sid = subj->dev_create_sid; + } else { + /* Label the device directly with the process SID */ + obj->sid = subj->sid; + dsubj->sid = subj->sid; + } + } + + cls = IsPointerDevice(rec->dev) ? SECCLASS_X_POINTER : SECCLASS_X_KEYBOARD; + rc = SELinuxDoCheck(subj, obj, cls, rec->access_mode, &auditdata); + if (rc != Success) + rec->status = rc; +} + +static void +SELinuxSend(CallbackListPtr *pcbl, pointer unused, pointer calldata) +{ + XaceSendAccessRec *rec = calldata; + SELinuxSubjectRec *subj; + SELinuxObjectRec *obj, ev_sid; + SELinuxAuditRec auditdata = { .client = rec->client, .dev = rec->dev }; + security_class_t class; + int rc, i, type; + + if (rec->dev) + subj = dixLookupPrivate(&rec->dev->devPrivates, subjectKey); + else + subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); + + obj = dixLookupPrivate(&rec->pWin->devPrivates, objectKey); + + /* Check send permission on window */ + rc = SELinuxDoCheck(subj, obj, SECCLASS_X_DRAWABLE, DixSendAccess, + &auditdata); + if (rc != Success) + goto err; + + /* Check send permission on specific event types */ + for (i = 0; i < rec->count; i++) { + type = rec->events[i].u.u.type; + class = (type & 128) ? SECCLASS_X_FAKEEVENT : SECCLASS_X_EVENT; + + rc = SELinuxEventToSID(type, obj->sid, &ev_sid); + if (rc != Success) + goto err; + + auditdata.event = type; + rc = SELinuxDoCheck(subj, &ev_sid, class, DixSendAccess, &auditdata); + if (rc != Success) + goto err; + } + return; +err: + rec->status = rc; +} + +static void +SELinuxReceive(CallbackListPtr *pcbl, pointer unused, pointer calldata) +{ + XaceReceiveAccessRec *rec = calldata; + SELinuxSubjectRec *subj; + SELinuxObjectRec *obj, ev_sid; + SELinuxAuditRec auditdata = { .client = NULL }; + security_class_t class; + int rc, i, type; + + subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); + obj = dixLookupPrivate(&rec->pWin->devPrivates, objectKey); + + /* Check receive permission on window */ + rc = SELinuxDoCheck(subj, obj, SECCLASS_X_DRAWABLE, DixReceiveAccess, + &auditdata); + if (rc != Success) + goto err; + + /* Check receive permission on specific event types */ + for (i = 0; i < rec->count; i++) { + type = rec->events[i].u.u.type; + class = (type & 128) ? SECCLASS_X_FAKEEVENT : SECCLASS_X_EVENT; + + rc = SELinuxEventToSID(type, obj->sid, &ev_sid); + if (rc != Success) + goto err; + + auditdata.event = type; + rc = SELinuxDoCheck(subj, &ev_sid, class, DixReceiveAccess, &auditdata); + if (rc != Success) + goto err; + } + return; +err: + rec->status = rc; +} + +static void +SELinuxExtension(CallbackListPtr *pcbl, pointer unused, pointer calldata) +{ + XaceExtAccessRec *rec = calldata; + SELinuxSubjectRec *subj, *serv; + SELinuxObjectRec *obj; + SELinuxAuditRec auditdata = { .client = rec->client }; + int rc; + + subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); + obj = dixLookupPrivate(&rec->ext->devPrivates, objectKey); + + /* If this is a new object that needs labeling, do it now */ + /* XXX there should be a separate callback for this */ + if (obj->sid == NULL) { + security_id_t sid; + + serv = dixLookupPrivate(&serverClient->devPrivates, subjectKey); + rc = SELinuxExtensionToSID(rec->ext->name, &sid); + if (rc != Success) { + rec->status = rc; + return; + } + + /* Perform a transition to obtain the final SID */ + if (avc_compute_create(serv->sid, sid, SECCLASS_X_EXTENSION, + &obj->sid) < 0) { + ErrorF("SELinux: a SID transition call failed!\n"); + rec->status = BadValue; + return; + } + } + + /* Perform the security check */ + auditdata.extension = rec->ext->name; + rc = SELinuxDoCheck(subj, obj, SECCLASS_X_EXTENSION, rec->access_mode, + &auditdata); + if (rc != Success) + rec->status = rc; +} + +static void +SELinuxSelection(CallbackListPtr *pcbl, pointer unused, pointer calldata) +{ + XaceSelectionAccessRec *rec = calldata; + SELinuxSubjectRec *subj; + SELinuxObjectRec *obj, *data; + Selection *pSel = *rec->ppSel; + Atom name = pSel->selection; + Mask access_mode = rec->access_mode; + SELinuxAuditRec auditdata = { .client = rec->client, .selection = name }; + security_id_t tsid; + int rc; + + subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); + obj = dixLookupPrivate(&pSel->devPrivates, objectKey); + + /* If this is a new object that needs labeling, do it now */ + if (access_mode & DixCreateAccess) { + rc = SELinuxSelectionToSID(name, subj, &obj->sid, &obj->poly); + if (rc != Success) + obj->sid = unlabeled_sid; + access_mode = DixSetAttrAccess; + } + /* If this is a polyinstantiated object, find the right instance */ + else if (obj->poly) { + rc = SELinuxSelectionToSID(name, subj, &tsid, NULL); + if (rc != Success) { + rec->status = rc; + return; + } + while (pSel->selection != name || obj->sid != tsid) { + if ((pSel = pSel->next) == NULL) + break; + obj = dixLookupPrivate(&pSel->devPrivates, objectKey); + } + + if (pSel) + *rec->ppSel = pSel; + else { + rec->status = BadMatch; + return; + } + } + + /* Perform the security check */ + rc = SELinuxDoCheck(subj, obj, SECCLASS_X_SELECTION, access_mode, + &auditdata); + if (rc != Success) + rec->status = rc; + + /* Label the content (advisory only) */ + if (access_mode & DixSetAttrAccess) { + data = dixLookupPrivate(&pSel->devPrivates, dataKey); + if (subj->sel_create_sid) + data->sid = subj->sel_create_sid; + else + data->sid = obj->sid; + } +} + +static void +SELinuxProperty(CallbackListPtr *pcbl, pointer unused, pointer calldata) +{ + XacePropertyAccessRec *rec = calldata; + SELinuxSubjectRec *subj; + SELinuxObjectRec *obj, *data; + PropertyPtr pProp = *rec->ppProp; + Atom name = pProp->propertyName; + SELinuxAuditRec auditdata = { .client = rec->client, .property = name }; + security_id_t tsid; + int rc; + + /* Don't care about the new content check */ + if (rec->access_mode & DixPostAccess) + return; + + subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); + obj = dixLookupPrivate(&pProp->devPrivates, objectKey); + + /* If this is a new object that needs labeling, do it now */ + if (rec->access_mode & DixCreateAccess) { + rc = SELinuxPropertyToSID(name, subj, &obj->sid, &obj->poly); + if (rc != Success) { + rec->status = rc; + return; + } + } + /* If this is a polyinstantiated object, find the right instance */ + else if (obj->poly) { + rc = SELinuxPropertyToSID(name, subj, &tsid, NULL); + if (rc != Success) { + rec->status = rc; + return; + } + while (pProp->propertyName != name || obj->sid != tsid) { + if ((pProp = pProp->next) == NULL) + break; + obj = dixLookupPrivate(&pProp->devPrivates, objectKey); + } + + if (pProp) + *rec->ppProp = pProp; + else { + rec->status = BadMatch; + return; + } + } + + /* Perform the security check */ + rc = SELinuxDoCheck(subj, obj, SECCLASS_X_PROPERTY, rec->access_mode, + &auditdata); + if (rc != Success) + rec->status = rc; + + /* Label the content (advisory only) */ + if (rec->access_mode & DixWriteAccess) { + data = dixLookupPrivate(&pProp->devPrivates, dataKey); + if (subj->prp_create_sid) + data->sid = subj->prp_create_sid; + else + data->sid = obj->sid; + } +} + +static void +SELinuxResource(CallbackListPtr *pcbl, pointer unused, pointer calldata) +{ + XaceResourceAccessRec *rec = calldata; + SELinuxSubjectRec *subj; + SELinuxObjectRec *obj; + SELinuxAuditRec auditdata = { .client = rec->client }; + Mask access_mode = rec->access_mode; + PrivateRec **privatePtr; + security_class_t class; + int rc, offset; + + subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); + + /* Determine if the resource object has a devPrivates field */ + offset = dixLookupPrivateOffset(rec->rtype); + if (offset < 0) { + /* No: use the SID of the owning client */ + class = SECCLASS_X_RESOURCE; + privatePtr = &clients[CLIENT_ID(rec->id)]->devPrivates; + obj = dixLookupPrivate(privatePtr, objectKey); + } else { + /* Yes: use the SID from the resource object itself */ + class = SELinuxTypeToClass(rec->rtype); + privatePtr = DEVPRIV_AT(rec->res, offset); + obj = dixLookupPrivate(privatePtr, objectKey); + } + + /* If this is a new object that needs labeling, do it now */ + if (access_mode & DixCreateAccess && offset >= 0) { + rc = SELinuxLabelResource(rec, subj, obj, class); + if (rc != Success) { + rec->status = rc; + return; + } + } + + /* Collapse generic resource permissions down to read/write */ + if (class == SECCLASS_X_RESOURCE) { + access_mode = !!(rec->access_mode & SELinuxReadMask); /* rd */ + access_mode |= !!(rec->access_mode & ~SELinuxReadMask) << 1; /* wr */ + } + + /* Perform the security check */ + auditdata.restype = rec->rtype; + auditdata.id = rec->id; + rc = SELinuxDoCheck(subj, obj, class, access_mode, &auditdata); + if (rc != Success) + rec->status = rc; + + /* Perform the background none check on windows */ + if (access_mode & DixCreateAccess && rec->rtype == RT_WINDOW) { + rc = SELinuxDoCheck(subj, obj, class, DixBlendAccess, &auditdata); + if (rc != Success) + ((WindowPtr)rec->res)->forcedBG = TRUE; + } +} + +static void +SELinuxScreen(CallbackListPtr *pcbl, pointer is_saver, pointer calldata) +{ + XaceScreenAccessRec *rec = calldata; + SELinuxSubjectRec *subj; + SELinuxObjectRec *obj; + SELinuxAuditRec auditdata = { .client = rec->client }; + Mask access_mode = rec->access_mode; + int rc; + + subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); + obj = dixLookupPrivate(&rec->screen->devPrivates, objectKey); + + /* If this is a new object that needs labeling, do it now */ + if (access_mode & DixCreateAccess) { + /* Perform a transition to obtain the final SID */ + if (avc_compute_create(subj->sid, subj->sid, SECCLASS_X_SCREEN, + &obj->sid) < 0) { + ErrorF("SELinux: a compute_create call failed!\n"); + rec->status = BadValue; + return; + } + } + + if (is_saver) + access_mode <<= 2; + + rc = SELinuxDoCheck(subj, obj, SECCLASS_X_SCREEN, access_mode, &auditdata); + if (rc != Success) + rec->status = rc; +} + +static void +SELinuxClient(CallbackListPtr *pcbl, pointer unused, pointer calldata) +{ + XaceClientAccessRec *rec = calldata; + SELinuxSubjectRec *subj; + SELinuxObjectRec *obj; + SELinuxAuditRec auditdata = { .client = rec->client }; + int rc; + + subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); + obj = dixLookupPrivate(&rec->target->devPrivates, objectKey); + + rc = SELinuxDoCheck(subj, obj, SECCLASS_X_CLIENT, rec->access_mode, + &auditdata); + if (rc != Success) + rec->status = rc; +} + +static void +SELinuxServer(CallbackListPtr *pcbl, pointer unused, pointer calldata) +{ + XaceServerAccessRec *rec = calldata; + SELinuxSubjectRec *subj; + SELinuxObjectRec *obj; + SELinuxAuditRec auditdata = { .client = rec->client }; + int rc; + + subj = dixLookupPrivate(&rec->client->devPrivates, subjectKey); + obj = dixLookupPrivate(&serverClient->devPrivates, objectKey); + + rc = SELinuxDoCheck(subj, obj, SECCLASS_X_SERVER, rec->access_mode, + &auditdata); + if (rc != Success) + rec->status = rc; +} + + +/* + * DIX Callbacks + */ + +static void +SELinuxClientState(CallbackListPtr *pcbl, pointer unused, pointer calldata) +{ + NewClientInfoRec *pci = calldata; + + switch (pci->client->clientState) { + case ClientStateInitial: + SELinuxLabelClient(pci->client); + break; + + default: + break; + } +} + +static void +SELinuxResourceState(CallbackListPtr *pcbl, pointer unused, pointer calldata) +{ + ResourceStateInfoRec *rec = calldata; + SELinuxSubjectRec *subj; + SELinuxObjectRec *obj; + WindowPtr pWin; + + if (rec->type != RT_WINDOW) + return; + if (rec->state != ResourceStateAdding) + return; + + pWin = (WindowPtr)rec->value; + subj = dixLookupPrivate(&wClient(pWin)->devPrivates, subjectKey); + + if (subj->sid) { + security_context_t ctx; + int rc = avc_sid_to_context_raw(subj->sid, &ctx); + if (rc < 0) + FatalError("SELinux: Failed to get security context!\n"); + rc = dixChangeWindowProperty(serverClient, + pWin, atom_client_ctx, XA_STRING, 8, + PropModeReplace, strlen(ctx), ctx, FALSE); + if (rc != Success) + FatalError("SELinux: Failed to set label property on window!\n"); + freecon(ctx); + } else + FatalError("SELinux: Unexpected unlabeled client found\n"); + + obj = dixLookupPrivate(&pWin->devPrivates, objectKey); + + if (obj->sid) { + security_context_t ctx; + int rc = avc_sid_to_context_raw(obj->sid, &ctx); + if (rc < 0) + FatalError("SELinux: Failed to get security context!\n"); + rc = dixChangeWindowProperty(serverClient, + pWin, atom_ctx, XA_STRING, 8, + PropModeReplace, strlen(ctx), ctx, FALSE); + if (rc != Success) + FatalError("SELinux: Failed to set label property on window!\n"); + freecon(ctx); + } else + FatalError("SELinux: Unexpected unlabeled window found\n"); +} + + +static int netlink_fd; + +static void +SELinuxBlockHandler(void *data, struct timeval **tv, void *read_mask) +{ +} + +static void +SELinuxWakeupHandler(void *data, int err, void *read_mask) +{ + if (FD_ISSET(netlink_fd, (fd_set *)read_mask)) + avc_netlink_check_nb(); +} + +void +SELinuxFlaskReset(void) +{ + /* Unregister callbacks */ + DeleteCallback(&ClientStateCallback, SELinuxClientState, NULL); + DeleteCallback(&ResourceStateCallback, SELinuxResourceState, NULL); + + XaceDeleteCallback(XACE_EXT_DISPATCH, SELinuxExtension, NULL); + XaceDeleteCallback(XACE_RESOURCE_ACCESS, SELinuxResource, NULL); + XaceDeleteCallback(XACE_DEVICE_ACCESS, SELinuxDevice, NULL); + XaceDeleteCallback(XACE_PROPERTY_ACCESS, SELinuxProperty, NULL); + XaceDeleteCallback(XACE_SEND_ACCESS, SELinuxSend, NULL); + XaceDeleteCallback(XACE_RECEIVE_ACCESS, SELinuxReceive, NULL); + XaceDeleteCallback(XACE_CLIENT_ACCESS, SELinuxClient, NULL); + XaceDeleteCallback(XACE_EXT_ACCESS, SELinuxExtension, NULL); + XaceDeleteCallback(XACE_SERVER_ACCESS, SELinuxServer, NULL); + XaceDeleteCallback(XACE_SELECTION_ACCESS, SELinuxSelection, NULL); + XaceDeleteCallback(XACE_SCREEN_ACCESS, SELinuxScreen, NULL); + XaceDeleteCallback(XACE_SCREENSAVER_ACCESS, SELinuxScreen, truep); + + /* Tear down SELinux stuff */ + audit_close(audit_fd); + avc_netlink_release_fd(); + RemoveBlockAndWakeupHandlers(SELinuxBlockHandler, SELinuxWakeupHandler, + NULL); + RemoveGeneralSocket(netlink_fd); + + avc_destroy(); +} + +void +SELinuxFlaskInit(void) +{ + struct selinux_opt avc_option = { AVC_OPT_SETENFORCE, (char *)0 }; + security_context_t ctx; + int ret = TRUE; + + switch(selinuxEnforcingState) { + case SELINUX_MODE_ENFORCING: + LogMessage(X_INFO, "SELinux: Configured in enforcing mode\n"); + avc_option.value = (char *)1; + break; + case SELINUX_MODE_PERMISSIVE: + LogMessage(X_INFO, "SELinux: Configured in permissive mode\n"); + avc_option.value = (char *)0; + break; + default: + avc_option.type = AVC_OPT_UNUSED; + break; + } + + /* Set up SELinux stuff */ + selinux_set_callback(SELINUX_CB_LOG, (union selinux_callback)SELinuxLog); + selinux_set_callback(SELINUX_CB_AUDIT, (union selinux_callback)SELinuxAudit); + + if (selinux_set_mapping(map) < 0) { + if (errno == EINVAL) { + ErrorF("SELinux: Invalid object class mapping, disabling SELinux support.\n"); + return; + } + FatalError("SELinux: Failed to set up security class mapping\n"); + } + + if (avc_open(&avc_option, 1) < 0) + FatalError("SELinux: Couldn't initialize SELinux userspace AVC\n"); + + if (security_get_initial_context_raw("unlabeled", &ctx) < 0) + FatalError("SELinux: Failed to look up unlabeled context\n"); + if (avc_context_to_sid_raw(ctx, &unlabeled_sid) < 0) + FatalError("SELinux: a context_to_SID call failed!\n"); + freecon(ctx); + + /* Prepare for auditing */ + audit_fd = audit_open(); + if (audit_fd < 0) + FatalError("SELinux: Failed to open the system audit log\n"); + + /* Allocate private storage */ + if (!dixRequestPrivate(subjectKey, sizeof(SELinuxSubjectRec)) || + !dixRequestPrivate(objectKey, sizeof(SELinuxObjectRec)) || + !dixRequestPrivate(dataKey, sizeof(SELinuxObjectRec))) + FatalError("SELinux: Failed to allocate private storage.\n"); + + /* Create atoms for doing window labeling */ + atom_ctx = MakeAtom("_SELINUX_CONTEXT", 16, TRUE); + if (atom_ctx == BAD_RESOURCE) + FatalError("SELinux: Failed to create atom\n"); + atom_client_ctx = MakeAtom("_SELINUX_CLIENT_CONTEXT", 23, TRUE); + if (atom_client_ctx == BAD_RESOURCE) + FatalError("SELinux: Failed to create atom\n"); + + netlink_fd = avc_netlink_acquire_fd(); + AddGeneralSocket(netlink_fd); + RegisterBlockAndWakeupHandlers(SELinuxBlockHandler, SELinuxWakeupHandler, + NULL); + + /* Register callbacks */ + ret &= AddCallback(&ClientStateCallback, SELinuxClientState, NULL); + ret &= AddCallback(&ResourceStateCallback, SELinuxResourceState, NULL); + + ret &= XaceRegisterCallback(XACE_EXT_DISPATCH, SELinuxExtension, NULL); + ret &= XaceRegisterCallback(XACE_RESOURCE_ACCESS, SELinuxResource, NULL); + ret &= XaceRegisterCallback(XACE_DEVICE_ACCESS, SELinuxDevice, NULL); + ret &= XaceRegisterCallback(XACE_PROPERTY_ACCESS, SELinuxProperty, NULL); + ret &= XaceRegisterCallback(XACE_SEND_ACCESS, SELinuxSend, NULL); + ret &= XaceRegisterCallback(XACE_RECEIVE_ACCESS, SELinuxReceive, NULL); + ret &= XaceRegisterCallback(XACE_CLIENT_ACCESS, SELinuxClient, NULL); + ret &= XaceRegisterCallback(XACE_EXT_ACCESS, SELinuxExtension, NULL); + ret &= XaceRegisterCallback(XACE_SERVER_ACCESS, SELinuxServer, NULL); + ret &= XaceRegisterCallback(XACE_SELECTION_ACCESS, SELinuxSelection, NULL); + ret &= XaceRegisterCallback(XACE_SCREEN_ACCESS, SELinuxScreen, NULL); + ret &= XaceRegisterCallback(XACE_SCREENSAVER_ACCESS, SELinuxScreen, truep); + if (!ret) + FatalError("SELinux: Failed to register one or more callbacks\n"); + + /* Label objects that were created before we could register ourself */ + SELinuxLabelInitial(); +} diff --git a/xorg-server/Xext/xselinux_label.c b/xorg-server/Xext/xselinux_label.c index 9b5023a53..76e537abe 100644 --- a/xorg-server/Xext/xselinux_label.c +++ b/xorg-server/Xext/xselinux_label.c @@ -1,374 +1,374 @@ -/************************************************************ - -Author: Eamon Walsh - -Permission to use, copy, modify, distribute, and sell this software and its -documentation for any purpose is hereby granted without fee, provided that -this permission notice appear in supporting documentation. 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 -AUTHOR 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 -#endif - -#include - -#include "registry.h" -#include "xselinuxint.h" - -/* selection and property atom cache */ -typedef struct { - SELinuxObjectRec prp; - SELinuxObjectRec sel; -} SELinuxAtomRec; - -/* dynamic array */ -typedef struct { - unsigned size; - void **array; -} SELinuxArrayRec; - -/* labeling handle */ -static struct selabel_handle *label_hnd; - -/* Array of object classes indexed by resource type */ -SELinuxArrayRec arr_types; -/* Array of event SIDs indexed by event type */ -SELinuxArrayRec arr_events; -/* Array of property and selection SID structures */ -SELinuxArrayRec arr_atoms; - -/* - * Dynamic array helpers - */ -static void * -SELinuxArrayGet(SELinuxArrayRec *rec, unsigned key) -{ - return (rec->size > key) ? rec->array[key] : 0; -} - -static int -SELinuxArraySet(SELinuxArrayRec *rec, unsigned key, void *val) -{ - if (key >= rec->size) { - /* Need to increase size of array */ - rec->array = xrealloc(rec->array, (key + 1) * sizeof(val)); - if (!rec->array) - return FALSE; - memset(rec->array + rec->size, 0, (key - rec->size + 1) * sizeof(val)); - rec->size = key + 1; - } - - rec->array[key] = val; - return TRUE; -} - -static void -SELinuxArrayFree(SELinuxArrayRec *rec, int free_elements) -{ - if (free_elements) { - unsigned i = rec->size; - while (i) - xfree(rec->array[--i]); - } - - xfree(rec->array); - rec->size = 0; - rec->array = NULL; -} - -/* - * Looks up a name in the selection or property mappings - */ -static int -SELinuxAtomToSIDLookup(Atom atom, SELinuxObjectRec *obj, int map, int polymap) -{ - const char *name = NameForAtom(atom); - security_context_t ctx; - int rc = Success; - - obj->poly = 1; - - /* Look in the mappings of names to contexts */ - if (selabel_lookup_raw(label_hnd, &ctx, name, map) == 0) { - obj->poly = 0; - } else if (errno != ENOENT) { - ErrorF("SELinux: a property label lookup failed!\n"); - return BadValue; - } else if (selabel_lookup_raw(label_hnd, &ctx, name, polymap) < 0) { - ErrorF("SELinux: a property label lookup failed!\n"); - return BadValue; - } - - /* Get a SID for context */ - if (avc_context_to_sid_raw(ctx, &obj->sid) < 0) { - ErrorF("SELinux: a context_to_SID_raw call failed!\n"); - rc = BadAlloc; - } - - freecon(ctx); - return rc; -} - -/* - * Looks up the SID corresponding to the given property or selection atom - */ -int -SELinuxAtomToSID(Atom atom, int prop, SELinuxObjectRec **obj_rtn) -{ - SELinuxAtomRec *rec; - SELinuxObjectRec *obj; - int rc, map, polymap; - - rec = SELinuxArrayGet(&arr_atoms, atom); - if (!rec) { - rec = xcalloc(1, sizeof(SELinuxAtomRec)); - if (!rec || !SELinuxArraySet(&arr_atoms, atom, rec)) - return BadAlloc; - } - - if (prop) { - obj = &rec->prp; - map = SELABEL_X_PROP; - polymap = SELABEL_X_POLYPROP; - } else { - obj = &rec->sel; - map = SELABEL_X_SELN; - polymap = SELABEL_X_POLYSELN; - } - - if (!obj->sid) { - rc = SELinuxAtomToSIDLookup(atom, obj, map, polymap); - if (rc != Success) - goto out; - } - - *obj_rtn = obj; - rc = Success; -out: - return rc; -} - -/* - * Looks up a SID for a selection/subject pair - */ -int -SELinuxSelectionToSID(Atom selection, SELinuxSubjectRec *subj, - security_id_t *sid_rtn, int *poly_rtn) -{ - int rc; - SELinuxObjectRec *obj; - security_id_t tsid; - - /* Get the default context and polyinstantiation bit */ - rc = SELinuxAtomToSID(selection, 0, &obj); - if (rc != Success) - return rc; - - /* Check for an override context next */ - if (subj->sel_use_sid) { - tsid = subj->sel_use_sid; - goto out; - } - - tsid = obj->sid; - - /* Polyinstantiate if necessary to obtain the final SID */ - if (obj->poly && avc_compute_member(subj->sid, obj->sid, - SECCLASS_X_SELECTION, &tsid) < 0) { - ErrorF("SELinux: a compute_member call failed!\n"); - return BadValue; - } -out: - *sid_rtn = tsid; - if (poly_rtn) - *poly_rtn = obj->poly; - return Success; -} - -/* - * Looks up a SID for a property/subject pair - */ -int -SELinuxPropertyToSID(Atom property, SELinuxSubjectRec *subj, - security_id_t *sid_rtn, int *poly_rtn) -{ - int rc; - SELinuxObjectRec *obj; - security_id_t tsid, tsid2; - - /* Get the default context and polyinstantiation bit */ - rc = SELinuxAtomToSID(property, 1, &obj); - if (rc != Success) - return rc; - - /* Check for an override context next */ - if (subj->prp_use_sid) { - tsid = subj->prp_use_sid; - goto out; - } - - /* Perform a transition */ - if (avc_compute_create(subj->sid, obj->sid, - SECCLASS_X_PROPERTY, &tsid) < 0) { - ErrorF("SELinux: a compute_create call failed!\n"); - return BadValue; - } - - /* Polyinstantiate if necessary to obtain the final SID */ - if (obj->poly) { - tsid2 = tsid; - if (avc_compute_member(subj->sid, tsid2, - SECCLASS_X_PROPERTY, &tsid) < 0) { - ErrorF("SELinux: a compute_member call failed!\n"); - return BadValue; - } - } -out: - *sid_rtn = tsid; - if (poly_rtn) - *poly_rtn = obj->poly; - return Success; -} - -/* - * Looks up the SID corresponding to the given event type - */ -int -SELinuxEventToSID(unsigned type, security_id_t sid_of_window, - SELinuxObjectRec *sid_return) -{ - const char *name = LookupEventName(type); - security_id_t sid; - security_context_t ctx; - type &= 127; - - sid = SELinuxArrayGet(&arr_events, type); - if (!sid) { - /* Look in the mappings of event names to contexts */ - if (selabel_lookup_raw(label_hnd, &ctx, name, SELABEL_X_EVENT) < 0) { - ErrorF("SELinux: an event label lookup failed!\n"); - return BadValue; - } - /* Get a SID for context */ - if (avc_context_to_sid_raw(ctx, &sid) < 0) { - ErrorF("SELinux: a context_to_SID_raw call failed!\n"); - freecon(ctx); - return BadAlloc; - } - freecon(ctx); - /* Cache the SID value */ - if (!SELinuxArraySet(&arr_events, type, sid)) - return BadAlloc; - } - - /* Perform a transition to obtain the final SID */ - if (avc_compute_create(sid_of_window, sid, SECCLASS_X_EVENT, - &sid_return->sid) < 0) { - ErrorF("SELinux: a compute_create call failed!\n"); - return BadValue; - } - - return Success; -} - -int -SELinuxExtensionToSID(const char *name, security_id_t *sid_rtn) -{ - security_context_t ctx; - - /* Look in the mappings of extension names to contexts */ - if (selabel_lookup_raw(label_hnd, &ctx, name, SELABEL_X_EXT) < 0) { - ErrorF("SELinux: a property label lookup failed!\n"); - return BadValue; - } - /* Get a SID for context */ - if (avc_context_to_sid_raw(ctx, sid_rtn) < 0) { - ErrorF("SELinux: a context_to_SID_raw call failed!\n"); - freecon(ctx); - return BadAlloc; - } - freecon(ctx); - return Success; -} - -/* - * Returns the object class corresponding to the given resource type. - */ -security_class_t -SELinuxTypeToClass(RESTYPE type) -{ - void *tmp; - - tmp = SELinuxArrayGet(&arr_types, type & TypeMask); - if (!tmp) { - unsigned long class = SECCLASS_X_RESOURCE; - - if (type & RC_DRAWABLE) - class = SECCLASS_X_DRAWABLE; - else if (type == RT_GC) - class = SECCLASS_X_GC; - else if (type == RT_FONT) - class = SECCLASS_X_FONT; - else if (type == RT_CURSOR) - class = SECCLASS_X_CURSOR; - else if (type == RT_COLORMAP) - class = SECCLASS_X_COLORMAP; - else { - /* Need to do a string lookup */ - const char *str = LookupResourceName(type); - if (!strcmp(str, "PICTURE")) - class = SECCLASS_X_DRAWABLE; - else if (!strcmp(str, "GLYPHSET")) - class = SECCLASS_X_FONT; - } - - tmp = (void *)class; - SELinuxArraySet(&arr_types, type & TypeMask, tmp); - } - - return (security_class_t)(unsigned long)tmp; -} - -security_context_t -SELinuxDefaultClientLabel(void) -{ - security_context_t ctx; - - if (selabel_lookup_raw(label_hnd, &ctx, "remote", SELABEL_X_CLIENT) < 0) - FatalError("SELinux: failed to look up remote-client context\n"); - - return ctx; -} - -void -SELinuxLabelInit(void) -{ - struct selinux_opt selabel_option = { SELABEL_OPT_VALIDATE, (char *)1 }; - - label_hnd = selabel_open(SELABEL_CTX_X, &selabel_option, 1); - if (!label_hnd) - FatalError("SELinux: Failed to open x_contexts mapping in policy\n"); -} - -void -SELinuxLabelReset(void) -{ - selabel_close(label_hnd); - label_hnd = NULL; - - /* Free local state */ - SELinuxArrayFree(&arr_types, 0); - SELinuxArrayFree(&arr_events, 0); - SELinuxArrayFree(&arr_atoms, 1); -} +/************************************************************ + +Author: Eamon Walsh + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +this permission notice appear in supporting documentation. 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 +AUTHOR 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 +#endif + +#include + +#include "registry.h" +#include "xselinuxint.h" + +/* selection and property atom cache */ +typedef struct { + SELinuxObjectRec prp; + SELinuxObjectRec sel; +} SELinuxAtomRec; + +/* dynamic array */ +typedef struct { + unsigned size; + void **array; +} SELinuxArrayRec; + +/* labeling handle */ +static struct selabel_handle *label_hnd; + +/* Array of object classes indexed by resource type */ +SELinuxArrayRec arr_types; +/* Array of event SIDs indexed by event type */ +SELinuxArrayRec arr_events; +/* Array of property and selection SID structures */ +SELinuxArrayRec arr_atoms; + +/* + * Dynamic array helpers + */ +static void * +SELinuxArrayGet(SELinuxArrayRec *rec, unsigned key) +{ + return (rec->size > key) ? rec->array[key] : 0; +} + +static int +SELinuxArraySet(SELinuxArrayRec *rec, unsigned key, void *val) +{ + if (key >= rec->size) { + /* Need to increase size of array */ + rec->array = realloc(rec->array, (key + 1) * sizeof(val)); + if (!rec->array) + return FALSE; + memset(rec->array + rec->size, 0, (key - rec->size + 1) * sizeof(val)); + rec->size = key + 1; + } + + rec->array[key] = val; + return TRUE; +} + +static void +SELinuxArrayFree(SELinuxArrayRec *rec, int free_elements) +{ + if (free_elements) { + unsigned i = rec->size; + while (i) + free(rec->array[--i]); + } + + free(rec->array); + rec->size = 0; + rec->array = NULL; +} + +/* + * Looks up a name in the selection or property mappings + */ +static int +SELinuxAtomToSIDLookup(Atom atom, SELinuxObjectRec *obj, int map, int polymap) +{ + const char *name = NameForAtom(atom); + security_context_t ctx; + int rc = Success; + + obj->poly = 1; + + /* Look in the mappings of names to contexts */ + if (selabel_lookup_raw(label_hnd, &ctx, name, map) == 0) { + obj->poly = 0; + } else if (errno != ENOENT) { + ErrorF("SELinux: a property label lookup failed!\n"); + return BadValue; + } else if (selabel_lookup_raw(label_hnd, &ctx, name, polymap) < 0) { + ErrorF("SELinux: a property label lookup failed!\n"); + return BadValue; + } + + /* Get a SID for context */ + if (avc_context_to_sid_raw(ctx, &obj->sid) < 0) { + ErrorF("SELinux: a context_to_SID_raw call failed!\n"); + rc = BadAlloc; + } + + freecon(ctx); + return rc; +} + +/* + * Looks up the SID corresponding to the given property or selection atom + */ +int +SELinuxAtomToSID(Atom atom, int prop, SELinuxObjectRec **obj_rtn) +{ + SELinuxAtomRec *rec; + SELinuxObjectRec *obj; + int rc, map, polymap; + + rec = SELinuxArrayGet(&arr_atoms, atom); + if (!rec) { + rec = calloc(1, sizeof(SELinuxAtomRec)); + if (!rec || !SELinuxArraySet(&arr_atoms, atom, rec)) + return BadAlloc; + } + + if (prop) { + obj = &rec->prp; + map = SELABEL_X_PROP; + polymap = SELABEL_X_POLYPROP; + } else { + obj = &rec->sel; + map = SELABEL_X_SELN; + polymap = SELABEL_X_POLYSELN; + } + + if (!obj->sid) { + rc = SELinuxAtomToSIDLookup(atom, obj, map, polymap); + if (rc != Success) + goto out; + } + + *obj_rtn = obj; + rc = Success; +out: + return rc; +} + +/* + * Looks up a SID for a selection/subject pair + */ +int +SELinuxSelectionToSID(Atom selection, SELinuxSubjectRec *subj, + security_id_t *sid_rtn, int *poly_rtn) +{ + int rc; + SELinuxObjectRec *obj; + security_id_t tsid; + + /* Get the default context and polyinstantiation bit */ + rc = SELinuxAtomToSID(selection, 0, &obj); + if (rc != Success) + return rc; + + /* Check for an override context next */ + if (subj->sel_use_sid) { + tsid = subj->sel_use_sid; + goto out; + } + + tsid = obj->sid; + + /* Polyinstantiate if necessary to obtain the final SID */ + if (obj->poly && avc_compute_member(subj->sid, obj->sid, + SECCLASS_X_SELECTION, &tsid) < 0) { + ErrorF("SELinux: a compute_member call failed!\n"); + return BadValue; + } +out: + *sid_rtn = tsid; + if (poly_rtn) + *poly_rtn = obj->poly; + return Success; +} + +/* + * Looks up a SID for a property/subject pair + */ +int +SELinuxPropertyToSID(Atom property, SELinuxSubjectRec *subj, + security_id_t *sid_rtn, int *poly_rtn) +{ + int rc; + SELinuxObjectRec *obj; + security_id_t tsid, tsid2; + + /* Get the default context and polyinstantiation bit */ + rc = SELinuxAtomToSID(property, 1, &obj); + if (rc != Success) + return rc; + + /* Check for an override context next */ + if (subj->prp_use_sid) { + tsid = subj->prp_use_sid; + goto out; + } + + /* Perform a transition */ + if (avc_compute_create(subj->sid, obj->sid, + SECCLASS_X_PROPERTY, &tsid) < 0) { + ErrorF("SELinux: a compute_create call failed!\n"); + return BadValue; + } + + /* Polyinstantiate if necessary to obtain the final SID */ + if (obj->poly) { + tsid2 = tsid; + if (avc_compute_member(subj->sid, tsid2, + SECCLASS_X_PROPERTY, &tsid) < 0) { + ErrorF("SELinux: a compute_member call failed!\n"); + return BadValue; + } + } +out: + *sid_rtn = tsid; + if (poly_rtn) + *poly_rtn = obj->poly; + return Success; +} + +/* + * Looks up the SID corresponding to the given event type + */ +int +SELinuxEventToSID(unsigned type, security_id_t sid_of_window, + SELinuxObjectRec *sid_return) +{ + const char *name = LookupEventName(type); + security_id_t sid; + security_context_t ctx; + type &= 127; + + sid = SELinuxArrayGet(&arr_events, type); + if (!sid) { + /* Look in the mappings of event names to contexts */ + if (selabel_lookup_raw(label_hnd, &ctx, name, SELABEL_X_EVENT) < 0) { + ErrorF("SELinux: an event label lookup failed!\n"); + return BadValue; + } + /* Get a SID for context */ + if (avc_context_to_sid_raw(ctx, &sid) < 0) { + ErrorF("SELinux: a context_to_SID_raw call failed!\n"); + freecon(ctx); + return BadAlloc; + } + freecon(ctx); + /* Cache the SID value */ + if (!SELinuxArraySet(&arr_events, type, sid)) + return BadAlloc; + } + + /* Perform a transition to obtain the final SID */ + if (avc_compute_create(sid_of_window, sid, SECCLASS_X_EVENT, + &sid_return->sid) < 0) { + ErrorF("SELinux: a compute_create call failed!\n"); + return BadValue; + } + + return Success; +} + +int +SELinuxExtensionToSID(const char *name, security_id_t *sid_rtn) +{ + security_context_t ctx; + + /* Look in the mappings of extension names to contexts */ + if (selabel_lookup_raw(label_hnd, &ctx, name, SELABEL_X_EXT) < 0) { + ErrorF("SELinux: a property label lookup failed!\n"); + return BadValue; + } + /* Get a SID for context */ + if (avc_context_to_sid_raw(ctx, sid_rtn) < 0) { + ErrorF("SELinux: a context_to_SID_raw call failed!\n"); + freecon(ctx); + return BadAlloc; + } + freecon(ctx); + return Success; +} + +/* + * Returns the object class corresponding to the given resource type. + */ +security_class_t +SELinuxTypeToClass(RESTYPE type) +{ + void *tmp; + + tmp = SELinuxArrayGet(&arr_types, type & TypeMask); + if (!tmp) { + unsigned long class = SECCLASS_X_RESOURCE; + + if (type & RC_DRAWABLE) + class = SECCLASS_X_DRAWABLE; + else if (type == RT_GC) + class = SECCLASS_X_GC; + else if (type == RT_FONT) + class = SECCLASS_X_FONT; + else if (type == RT_CURSOR) + class = SECCLASS_X_CURSOR; + else if (type == RT_COLORMAP) + class = SECCLASS_X_COLORMAP; + else { + /* Need to do a string lookup */ + const char *str = LookupResourceName(type); + if (!strcmp(str, "PICTURE")) + class = SECCLASS_X_DRAWABLE; + else if (!strcmp(str, "GLYPHSET")) + class = SECCLASS_X_FONT; + } + + tmp = (void *)class; + SELinuxArraySet(&arr_types, type & TypeMask, tmp); + } + + return (security_class_t)(unsigned long)tmp; +} + +security_context_t +SELinuxDefaultClientLabel(void) +{ + security_context_t ctx; + + if (selabel_lookup_raw(label_hnd, &ctx, "remote", SELABEL_X_CLIENT) < 0) + FatalError("SELinux: failed to look up remote-client context\n"); + + return ctx; +} + +void +SELinuxLabelInit(void) +{ + struct selinux_opt selabel_option = { SELABEL_OPT_VALIDATE, (char *)1 }; + + label_hnd = selabel_open(SELABEL_CTX_X, &selabel_option, 1); + if (!label_hnd) + FatalError("SELinux: Failed to open x_contexts mapping in policy\n"); +} + +void +SELinuxLabelReset(void) +{ + selabel_close(label_hnd); + label_hnd = NULL; + + /* Free local state */ + SELinuxArrayFree(&arr_types, 0); + SELinuxArrayFree(&arr_events, 0); + SELinuxArrayFree(&arr_atoms, 1); +} diff --git a/xorg-server/Xext/xselinuxint.h b/xorg-server/Xext/xselinuxint.h index 854a57dd7..f084b94b2 100644 --- a/xorg-server/Xext/xselinuxint.h +++ b/xorg-server/Xext/xselinuxint.h @@ -1,556 +1,558 @@ -/************************************************************ - -Author: Eamon Walsh - -Permission to use, copy, modify, distribute, and sell this software and its -documentation for any purpose is hereby granted without fee, provided that -this permission notice appear in supporting documentation. 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 -AUTHOR 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. - -********************************************************/ - -#ifndef _XSELINUXINT_H -#define _XSELINUXINT_H - -#include -#include - -#include "globals.h" -#include "dixaccess.h" -#include "dixstruct.h" -#include "privates.h" -#include "resource.h" -#include "registry.h" -#include "inputstr.h" -#include "xselinux.h" - -/* - * Types - */ - -/* subject state (clients and devices only) */ -typedef struct { - security_id_t sid; - security_id_t dev_create_sid; - security_id_t win_create_sid; - security_id_t sel_create_sid; - security_id_t prp_create_sid; - security_id_t sel_use_sid; - security_id_t prp_use_sid; - struct avc_entry_ref aeref; - char *command; - int privileged; -} SELinuxSubjectRec; - -/* object state */ -typedef struct { - security_id_t sid; - int poly; -} SELinuxObjectRec; - -/* - * Globals - */ - -extern DevPrivateKey subjectKey; -extern DevPrivateKey objectKey; -extern DevPrivateKey dataKey; - -/* - * Label functions - */ - -int -SELinuxAtomToSID(Atom atom, int prop, SELinuxObjectRec **obj_rtn); - -int -SELinuxSelectionToSID(Atom selection, SELinuxSubjectRec *subj, - security_id_t *sid_rtn, int *poly_rtn); - -int -SELinuxPropertyToSID(Atom property, SELinuxSubjectRec *subj, - security_id_t *sid_rtn, int *poly_rtn); - -int -SELinuxEventToSID(unsigned type, security_id_t sid_of_window, - SELinuxObjectRec *sid_return); - -int -SELinuxExtensionToSID(const char *name, security_id_t *sid_rtn); - -security_class_t -SELinuxTypeToClass(RESTYPE type); - -security_context_t -SELinuxDefaultClientLabel(void); - -void -SELinuxLabelInit(void); - -void -SELinuxLabelReset(void); - -/* - * Security module functions - */ - -void -SELinuxFlaskInit(void); - -void -SELinuxFlaskReset(void); - - -/* - * Private Flask definitions - */ - -/* Security class constants */ -#define SECCLASS_X_DRAWABLE 1 -#define SECCLASS_X_SCREEN 2 -#define SECCLASS_X_GC 3 -#define SECCLASS_X_FONT 4 -#define SECCLASS_X_COLORMAP 5 -#define SECCLASS_X_PROPERTY 6 -#define SECCLASS_X_SELECTION 7 -#define SECCLASS_X_CURSOR 8 -#define SECCLASS_X_CLIENT 9 -#define SECCLASS_X_POINTER 10 -#define SECCLASS_X_KEYBOARD 11 -#define SECCLASS_X_SERVER 12 -#define SECCLASS_X_EXTENSION 13 -#define SECCLASS_X_EVENT 14 -#define SECCLASS_X_FAKEEVENT 15 -#define SECCLASS_X_RESOURCE 16 - -#ifdef _XSELINUX_NEED_FLASK_MAP -/* Mapping from DixAccess bits to Flask permissions */ -static struct security_class_mapping map[] = { - { "x_drawable", - { "read", /* DixReadAccess */ - "write", /* DixWriteAccess */ - "destroy", /* DixDestroyAccess */ - "create", /* DixCreateAccess */ - "getattr", /* DixGetAttrAccess */ - "setattr", /* DixSetAttrAccess */ - "list_property", /* DixListPropAccess */ - "get_property", /* DixGetPropAccess */ - "set_property", /* DixSetPropAccess */ - "", /* DixGetFocusAccess */ - "", /* DixSetFocusAccess */ - "list_child", /* DixListAccess */ - "add_child", /* DixAddAccess */ - "remove_child", /* DixRemoveAccess */ - "hide", /* DixHideAccess */ - "show", /* DixShowAccess */ - "blend", /* DixBlendAccess */ - "override", /* DixGrabAccess */ - "", /* DixFreezeAccess */ - "", /* DixForceAccess */ - "", /* DixInstallAccess */ - "", /* DixUninstallAccess */ - "send", /* DixSendAccess */ - "receive", /* DixReceiveAccess */ - "", /* DixUseAccess */ - "manage", /* DixManageAccess */ - NULL }}, - { "x_screen", - { "", /* DixReadAccess */ - "", /* DixWriteAccess */ - "", /* DixDestroyAccess */ - "", /* DixCreateAccess */ - "getattr", /* DixGetAttrAccess */ - "setattr", /* DixSetAttrAccess */ - "saver_getattr", /* DixListPropAccess */ - "saver_setattr", /* DixGetPropAccess */ - "", /* DixSetPropAccess */ - "", /* DixGetFocusAccess */ - "", /* DixSetFocusAccess */ - "", /* DixListAccess */ - "", /* DixAddAccess */ - "", /* DixRemoveAccess */ - "hide_cursor", /* DixHideAccess */ - "show_cursor", /* DixShowAccess */ - "saver_hide", /* DixBlendAccess */ - "saver_show", /* DixGrabAccess */ - NULL }}, - { "x_gc", - { "", /* DixReadAccess */ - "", /* DixWriteAccess */ - "destroy", /* DixDestroyAccess */ - "create", /* DixCreateAccess */ - "getattr", /* DixGetAttrAccess */ - "setattr", /* DixSetAttrAccess */ - "", /* DixListPropAccess */ - "", /* DixGetPropAccess */ - "", /* DixSetPropAccess */ - "", /* DixGetFocusAccess */ - "", /* DixSetFocusAccess */ - "", /* DixListAccess */ - "", /* DixAddAccess */ - "", /* DixRemoveAccess */ - "", /* DixHideAccess */ - "", /* DixShowAccess */ - "", /* DixBlendAccess */ - "", /* DixGrabAccess */ - "", /* DixFreezeAccess */ - "", /* DixForceAccess */ - "", /* DixInstallAccess */ - "", /* DixUninstallAccess */ - "", /* DixSendAccess */ - "", /* DixReceiveAccess */ - "use", /* DixUseAccess */ - NULL }}, - { "x_font", - { "", /* DixReadAccess */ - "", /* DixWriteAccess */ - "destroy", /* DixDestroyAccess */ - "create", /* DixCreateAccess */ - "getattr", /* DixGetAttrAccess */ - "", /* DixSetAttrAccess */ - "", /* DixListPropAccess */ - "", /* DixGetPropAccess */ - "", /* DixSetPropAccess */ - "", /* DixGetFocusAccess */ - "", /* DixSetFocusAccess */ - "", /* DixListAccess */ - "add_glyph", /* DixAddAccess */ - "remove_glyph", /* DixRemoveAccess */ - "", /* DixHideAccess */ - "", /* DixShowAccess */ - "", /* DixBlendAccess */ - "", /* DixGrabAccess */ - "", /* DixFreezeAccess */ - "", /* DixForceAccess */ - "", /* DixInstallAccess */ - "", /* DixUninstallAccess */ - "", /* DixSendAccess */ - "", /* DixReceiveAccess */ - "use", /* DixUseAccess */ - NULL }}, - { "x_colormap", - { "read", /* DixReadAccess */ - "write", /* DixWriteAccess */ - "destroy", /* DixDestroyAccess */ - "create", /* DixCreateAccess */ - "getattr", /* DixGetAttrAccess */ - "", /* DixSetAttrAccess */ - "", /* DixListPropAccess */ - "", /* DixGetPropAccess */ - "", /* DixSetPropAccess */ - "", /* DixGetFocusAccess */ - "", /* DixSetFocusAccess */ - "", /* DixListAccess */ - "add_color", /* DixAddAccess */ - "remove_color", /* DixRemoveAccess */ - "", /* DixHideAccess */ - "", /* DixShowAccess */ - "", /* DixBlendAccess */ - "", /* DixGrabAccess */ - "", /* DixFreezeAccess */ - "", /* DixForceAccess */ - "install", /* DixInstallAccess */ - "uninstall", /* DixUninstallAccess */ - "", /* DixSendAccess */ - "", /* DixReceiveAccess */ - "use", /* DixUseAccess */ - NULL }}, - { "x_property", - { "read", /* DixReadAccess */ - "write", /* DixWriteAccess */ - "destroy", /* DixDestroyAccess */ - "create", /* DixCreateAccess */ - "getattr", /* DixGetAttrAccess */ - "setattr", /* DixSetAttrAccess */ - "", /* DixListPropAccess */ - "", /* DixGetPropAccess */ - "", /* DixSetPropAccess */ - "", /* DixGetFocusAccess */ - "", /* DixSetFocusAccess */ - "", /* DixListAccess */ - "", /* DixAddAccess */ - "", /* DixRemoveAccess */ - "", /* DixHideAccess */ - "", /* DixShowAccess */ - "write", /* DixBlendAccess */ - NULL }}, - { "x_selection", - { "read", /* DixReadAccess */ - "", /* DixWriteAccess */ - "", /* DixDestroyAccess */ - "setattr", /* DixCreateAccess */ - "getattr", /* DixGetAttrAccess */ - "setattr", /* DixSetAttrAccess */ - NULL }}, - { "x_cursor", - { "read", /* DixReadAccess */ - "write", /* DixWriteAccess */ - "destroy", /* DixDestroyAccess */ - "create", /* DixCreateAccess */ - "getattr", /* DixGetAttrAccess */ - "setattr", /* DixSetAttrAccess */ - "", /* DixListPropAccess */ - "", /* DixGetPropAccess */ - "", /* DixSetPropAccess */ - "", /* DixGetFocusAccess */ - "", /* DixSetFocusAccess */ - "", /* DixListAccess */ - "", /* DixAddAccess */ - "", /* DixRemoveAccess */ - "", /* DixHideAccess */ - "", /* DixShowAccess */ - "", /* DixBlendAccess */ - "", /* DixGrabAccess */ - "", /* DixFreezeAccess */ - "", /* DixForceAccess */ - "", /* DixInstallAccess */ - "", /* DixUninstallAccess */ - "", /* DixSendAccess */ - "", /* DixReceiveAccess */ - "use", /* DixUseAccess */ - NULL }}, - { "x_client", - { "", /* DixReadAccess */ - "", /* DixWriteAccess */ - "destroy", /* DixDestroyAccess */ - "", /* DixCreateAccess */ - "getattr", /* DixGetAttrAccess */ - "setattr", /* DixSetAttrAccess */ - "", /* DixListPropAccess */ - "", /* DixGetPropAccess */ - "", /* DixSetPropAccess */ - "", /* DixGetFocusAccess */ - "", /* DixSetFocusAccess */ - "", /* DixListAccess */ - "", /* DixAddAccess */ - "", /* DixRemoveAccess */ - "", /* DixHideAccess */ - "", /* DixShowAccess */ - "", /* DixBlendAccess */ - "", /* DixGrabAccess */ - "", /* DixFreezeAccess */ - "", /* DixForceAccess */ - "", /* DixInstallAccess */ - "", /* DixUninstallAccess */ - "", /* DixSendAccess */ - "", /* DixReceiveAccess */ - "", /* DixUseAccess */ - "manage", /* DixManageAccess */ - NULL }}, - { "x_pointer", - { "read", /* DixReadAccess */ - "write", /* DixWriteAccess */ - "destroy", /* DixDestroyAccess */ - "create", /* DixCreateAccess */ - "getattr", /* DixGetAttrAccess */ - "setattr", /* DixSetAttrAccess */ - "list_property", /* DixListPropAccess */ - "get_property", /* DixGetPropAccess */ - "set_property", /* DixSetPropAccess */ - "getfocus", /* DixGetFocusAccess */ - "setfocus", /* DixSetFocusAccess */ - "", /* DixListAccess */ - "add", /* DixAddAccess */ - "remove", /* DixRemoveAccess */ - "", /* DixHideAccess */ - "", /* DixShowAccess */ - "", /* DixBlendAccess */ - "grab", /* DixGrabAccess */ - "freeze", /* DixFreezeAccess */ - "force_cursor", /* DixForceAccess */ - "", /* DixInstallAccess */ - "", /* DixUninstallAccess */ - "", /* DixSendAccess */ - "", /* DixReceiveAccess */ - "use", /* DixUseAccess */ - "manage", /* DixManageAccess */ - "", /* DixDebugAccess */ - "bell", /* DixBellAccess */ - NULL }}, - { "x_keyboard", - { "read", /* DixReadAccess */ - "write", /* DixWriteAccess */ - "destroy", /* DixDestroyAccess */ - "create", /* DixCreateAccess */ - "getattr", /* DixGetAttrAccess */ - "setattr", /* DixSetAttrAccess */ - "list_property", /* DixListPropAccess */ - "get_property", /* DixGetPropAccess */ - "set_property", /* DixSetPropAccess */ - "getfocus", /* DixGetFocusAccess */ - "setfocus", /* DixSetFocusAccess */ - "", /* DixListAccess */ - "add", /* DixAddAccess */ - "remove", /* DixRemoveAccess */ - "", /* DixHideAccess */ - "", /* DixShowAccess */ - "", /* DixBlendAccess */ - "grab", /* DixGrabAccess */ - "freeze", /* DixFreezeAccess */ - "force_cursor", /* DixForceAccess */ - "", /* DixInstallAccess */ - "", /* DixUninstallAccess */ - "", /* DixSendAccess */ - "", /* DixReceiveAccess */ - "use", /* DixUseAccess */ - "manage", /* DixManageAccess */ - "", /* DixDebugAccess */ - "bell", /* DixBellAccess */ - NULL }}, - { "x_server", - { "record", /* DixReadAccess */ - "", /* DixWriteAccess */ - "", /* DixDestroyAccess */ - "", /* DixCreateAccess */ - "getattr", /* DixGetAttrAccess */ - "setattr", /* DixSetAttrAccess */ - "", /* DixListPropAccess */ - "", /* DixGetPropAccess */ - "", /* DixSetPropAccess */ - "", /* DixGetFocusAccess */ - "", /* DixSetFocusAccess */ - "", /* DixListAccess */ - "", /* DixAddAccess */ - "", /* DixRemoveAccess */ - "", /* DixHideAccess */ - "", /* DixShowAccess */ - "", /* DixBlendAccess */ - "grab", /* DixGrabAccess */ - "", /* DixFreezeAccess */ - "", /* DixForceAccess */ - "", /* DixInstallAccess */ - "", /* DixUninstallAccess */ - "", /* DixSendAccess */ - "", /* DixReceiveAccess */ - "", /* DixUseAccess */ - "manage", /* DixManageAccess */ - "debug", /* DixDebugAccess */ - NULL }}, - { "x_extension", - { "", /* DixReadAccess */ - "", /* DixWriteAccess */ - "", /* DixDestroyAccess */ - "", /* DixCreateAccess */ - "query", /* DixGetAttrAccess */ - "", /* DixSetAttrAccess */ - "", /* DixListPropAccess */ - "", /* DixGetPropAccess */ - "", /* DixSetPropAccess */ - "", /* DixGetFocusAccess */ - "", /* DixSetFocusAccess */ - "", /* DixListAccess */ - "", /* DixAddAccess */ - "", /* DixRemoveAccess */ - "", /* DixHideAccess */ - "", /* DixShowAccess */ - "", /* DixBlendAccess */ - "", /* DixGrabAccess */ - "", /* DixFreezeAccess */ - "", /* DixForceAccess */ - "", /* DixInstallAccess */ - "", /* DixUninstallAccess */ - "", /* DixSendAccess */ - "", /* DixReceiveAccess */ - "use", /* DixUseAccess */ - NULL }}, - { "x_event", - { "", /* DixReadAccess */ - "", /* DixWriteAccess */ - "", /* DixDestroyAccess */ - "", /* DixCreateAccess */ - "", /* DixGetAttrAccess */ - "", /* DixSetAttrAccess */ - "", /* DixListPropAccess */ - "", /* DixGetPropAccess */ - "", /* DixSetPropAccess */ - "", /* DixGetFocusAccess */ - "", /* DixSetFocusAccess */ - "", /* DixListAccess */ - "", /* DixAddAccess */ - "", /* DixRemoveAccess */ - "", /* DixHideAccess */ - "", /* DixShowAccess */ - "", /* DixBlendAccess */ - "", /* DixGrabAccess */ - "", /* DixFreezeAccess */ - "", /* DixForceAccess */ - "", /* DixInstallAccess */ - "", /* DixUninstallAccess */ - "send", /* DixSendAccess */ - "receive", /* DixReceiveAccess */ - NULL }}, - { "x_synthetic_event", - { "", /* DixReadAccess */ - "", /* DixWriteAccess */ - "", /* DixDestroyAccess */ - "", /* DixCreateAccess */ - "", /* DixGetAttrAccess */ - "", /* DixSetAttrAccess */ - "", /* DixListPropAccess */ - "", /* DixGetPropAccess */ - "", /* DixSetPropAccess */ - "", /* DixGetFocusAccess */ - "", /* DixSetFocusAccess */ - "", /* DixListAccess */ - "", /* DixAddAccess */ - "", /* DixRemoveAccess */ - "", /* DixHideAccess */ - "", /* DixShowAccess */ - "", /* DixBlendAccess */ - "", /* DixGrabAccess */ - "", /* DixFreezeAccess */ - "", /* DixForceAccess */ - "", /* DixInstallAccess */ - "", /* DixUninstallAccess */ - "send", /* DixSendAccess */ - "receive", /* DixReceiveAccess */ - NULL }}, - { "x_resource", - { "read", /* DixReadAccess */ - "write", /* DixWriteAccess */ - "write", /* DixDestroyAccess */ - "write", /* DixCreateAccess */ - "read", /* DixGetAttrAccess */ - "write", /* DixSetAttrAccess */ - "read", /* DixListPropAccess */ - "read", /* DixGetPropAccess */ - "write", /* DixSetPropAccess */ - "read", /* DixGetFocusAccess */ - "write", /* DixSetFocusAccess */ - "read", /* DixListAccess */ - "write", /* DixAddAccess */ - "write", /* DixRemoveAccess */ - "write", /* DixHideAccess */ - "read", /* DixShowAccess */ - "read", /* DixBlendAccess */ - "write", /* DixGrabAccess */ - "write", /* DixFreezeAccess */ - "write", /* DixForceAccess */ - "write", /* DixInstallAccess */ - "write", /* DixUninstallAccess */ - "write", /* DixSendAccess */ - "read", /* DixReceiveAccess */ - "read", /* DixUseAccess */ - "write", /* DixManageAccess */ - "read", /* DixDebugAccess */ - "write", /* DixBellAccess */ - NULL }}, - { NULL } -}; - -/* x_resource "read" bits from the list above */ -#define SELinuxReadMask (DixReadAccess|DixGetAttrAccess|DixListPropAccess| \ - DixGetPropAccess|DixGetFocusAccess|DixListAccess| \ - DixShowAccess|DixBlendAccess|DixReceiveAccess| \ - DixUseAccess|DixDebugAccess) - -#endif /* _XSELINUX_NEED_FLASK_MAP */ -#endif /* _XSELINUXINT_H */ +/************************************************************ + +Author: Eamon Walsh + +Permission to use, copy, modify, distribute, and sell this software and its +documentation for any purpose is hereby granted without fee, provided that +this permission notice appear in supporting documentation. 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 +AUTHOR 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. + +********************************************************/ + +#ifndef _XSELINUXINT_H +#define _XSELINUXINT_H + +#include +#include + +#include "globals.h" +#include "dixaccess.h" +#include "dixstruct.h" +#include "privates.h" +#include "resource.h" +#include "registry.h" +#include "inputstr.h" +#include "xselinux.h" + +/* + * Types + */ + +#define COMMAND_LEN 64 + +/* subject state (clients and devices only) */ +typedef struct { + security_id_t sid; + security_id_t dev_create_sid; + security_id_t win_create_sid; + security_id_t sel_create_sid; + security_id_t prp_create_sid; + security_id_t sel_use_sid; + security_id_t prp_use_sid; + struct avc_entry_ref aeref; + char command[COMMAND_LEN]; + int privileged; +} SELinuxSubjectRec; + +/* object state */ +typedef struct { + security_id_t sid; + int poly; +} SELinuxObjectRec; + +/* + * Globals + */ + +extern DevPrivateKey subjectKey; +extern DevPrivateKey objectKey; +extern DevPrivateKey dataKey; + +/* + * Label functions + */ + +int +SELinuxAtomToSID(Atom atom, int prop, SELinuxObjectRec **obj_rtn); + +int +SELinuxSelectionToSID(Atom selection, SELinuxSubjectRec *subj, + security_id_t *sid_rtn, int *poly_rtn); + +int +SELinuxPropertyToSID(Atom property, SELinuxSubjectRec *subj, + security_id_t *sid_rtn, int *poly_rtn); + +int +SELinuxEventToSID(unsigned type, security_id_t sid_of_window, + SELinuxObjectRec *sid_return); + +int +SELinuxExtensionToSID(const char *name, security_id_t *sid_rtn); + +security_class_t +SELinuxTypeToClass(RESTYPE type); + +security_context_t +SELinuxDefaultClientLabel(void); + +void +SELinuxLabelInit(void); + +void +SELinuxLabelReset(void); + +/* + * Security module functions + */ + +void +SELinuxFlaskInit(void); + +void +SELinuxFlaskReset(void); + + +/* + * Private Flask definitions + */ + +/* Security class constants */ +#define SECCLASS_X_DRAWABLE 1 +#define SECCLASS_X_SCREEN 2 +#define SECCLASS_X_GC 3 +#define SECCLASS_X_FONT 4 +#define SECCLASS_X_COLORMAP 5 +#define SECCLASS_X_PROPERTY 6 +#define SECCLASS_X_SELECTION 7 +#define SECCLASS_X_CURSOR 8 +#define SECCLASS_X_CLIENT 9 +#define SECCLASS_X_POINTER 10 +#define SECCLASS_X_KEYBOARD 11 +#define SECCLASS_X_SERVER 12 +#define SECCLASS_X_EXTENSION 13 +#define SECCLASS_X_EVENT 14 +#define SECCLASS_X_FAKEEVENT 15 +#define SECCLASS_X_RESOURCE 16 + +#ifdef _XSELINUX_NEED_FLASK_MAP +/* Mapping from DixAccess bits to Flask permissions */ +static struct security_class_mapping map[] = { + { "x_drawable", + { "read", /* DixReadAccess */ + "write", /* DixWriteAccess */ + "destroy", /* DixDestroyAccess */ + "create", /* DixCreateAccess */ + "getattr", /* DixGetAttrAccess */ + "setattr", /* DixSetAttrAccess */ + "list_property", /* DixListPropAccess */ + "get_property", /* DixGetPropAccess */ + "set_property", /* DixSetPropAccess */ + "", /* DixGetFocusAccess */ + "", /* DixSetFocusAccess */ + "list_child", /* DixListAccess */ + "add_child", /* DixAddAccess */ + "remove_child", /* DixRemoveAccess */ + "hide", /* DixHideAccess */ + "show", /* DixShowAccess */ + "blend", /* DixBlendAccess */ + "override", /* DixGrabAccess */ + "", /* DixFreezeAccess */ + "", /* DixForceAccess */ + "", /* DixInstallAccess */ + "", /* DixUninstallAccess */ + "send", /* DixSendAccess */ + "receive", /* DixReceiveAccess */ + "", /* DixUseAccess */ + "manage", /* DixManageAccess */ + NULL }}, + { "x_screen", + { "", /* DixReadAccess */ + "", /* DixWriteAccess */ + "", /* DixDestroyAccess */ + "", /* DixCreateAccess */ + "getattr", /* DixGetAttrAccess */ + "setattr", /* DixSetAttrAccess */ + "saver_getattr", /* DixListPropAccess */ + "saver_setattr", /* DixGetPropAccess */ + "", /* DixSetPropAccess */ + "", /* DixGetFocusAccess */ + "", /* DixSetFocusAccess */ + "", /* DixListAccess */ + "", /* DixAddAccess */ + "", /* DixRemoveAccess */ + "hide_cursor", /* DixHideAccess */ + "show_cursor", /* DixShowAccess */ + "saver_hide", /* DixBlendAccess */ + "saver_show", /* DixGrabAccess */ + NULL }}, + { "x_gc", + { "", /* DixReadAccess */ + "", /* DixWriteAccess */ + "destroy", /* DixDestroyAccess */ + "create", /* DixCreateAccess */ + "getattr", /* DixGetAttrAccess */ + "setattr", /* DixSetAttrAccess */ + "", /* DixListPropAccess */ + "", /* DixGetPropAccess */ + "", /* DixSetPropAccess */ + "", /* DixGetFocusAccess */ + "", /* DixSetFocusAccess */ + "", /* DixListAccess */ + "", /* DixAddAccess */ + "", /* DixRemoveAccess */ + "", /* DixHideAccess */ + "", /* DixShowAccess */ + "", /* DixBlendAccess */ + "", /* DixGrabAccess */ + "", /* DixFreezeAccess */ + "", /* DixForceAccess */ + "", /* DixInstallAccess */ + "", /* DixUninstallAccess */ + "", /* DixSendAccess */ + "", /* DixReceiveAccess */ + "use", /* DixUseAccess */ + NULL }}, + { "x_font", + { "", /* DixReadAccess */ + "", /* DixWriteAccess */ + "destroy", /* DixDestroyAccess */ + "create", /* DixCreateAccess */ + "getattr", /* DixGetAttrAccess */ + "", /* DixSetAttrAccess */ + "", /* DixListPropAccess */ + "", /* DixGetPropAccess */ + "", /* DixSetPropAccess */ + "", /* DixGetFocusAccess */ + "", /* DixSetFocusAccess */ + "", /* DixListAccess */ + "add_glyph", /* DixAddAccess */ + "remove_glyph", /* DixRemoveAccess */ + "", /* DixHideAccess */ + "", /* DixShowAccess */ + "", /* DixBlendAccess */ + "", /* DixGrabAccess */ + "", /* DixFreezeAccess */ + "", /* DixForceAccess */ + "", /* DixInstallAccess */ + "", /* DixUninstallAccess */ + "", /* DixSendAccess */ + "", /* DixReceiveAccess */ + "use", /* DixUseAccess */ + NULL }}, + { "x_colormap", + { "read", /* DixReadAccess */ + "write", /* DixWriteAccess */ + "destroy", /* DixDestroyAccess */ + "create", /* DixCreateAccess */ + "getattr", /* DixGetAttrAccess */ + "", /* DixSetAttrAccess */ + "", /* DixListPropAccess */ + "", /* DixGetPropAccess */ + "", /* DixSetPropAccess */ + "", /* DixGetFocusAccess */ + "", /* DixSetFocusAccess */ + "", /* DixListAccess */ + "add_color", /* DixAddAccess */ + "remove_color", /* DixRemoveAccess */ + "", /* DixHideAccess */ + "", /* DixShowAccess */ + "", /* DixBlendAccess */ + "", /* DixGrabAccess */ + "", /* DixFreezeAccess */ + "", /* DixForceAccess */ + "install", /* DixInstallAccess */ + "uninstall", /* DixUninstallAccess */ + "", /* DixSendAccess */ + "", /* DixReceiveAccess */ + "use", /* DixUseAccess */ + NULL }}, + { "x_property", + { "read", /* DixReadAccess */ + "write", /* DixWriteAccess */ + "destroy", /* DixDestroyAccess */ + "create", /* DixCreateAccess */ + "getattr", /* DixGetAttrAccess */ + "setattr", /* DixSetAttrAccess */ + "", /* DixListPropAccess */ + "", /* DixGetPropAccess */ + "", /* DixSetPropAccess */ + "", /* DixGetFocusAccess */ + "", /* DixSetFocusAccess */ + "", /* DixListAccess */ + "", /* DixAddAccess */ + "", /* DixRemoveAccess */ + "", /* DixHideAccess */ + "", /* DixShowAccess */ + "write", /* DixBlendAccess */ + NULL }}, + { "x_selection", + { "read", /* DixReadAccess */ + "", /* DixWriteAccess */ + "", /* DixDestroyAccess */ + "setattr", /* DixCreateAccess */ + "getattr", /* DixGetAttrAccess */ + "setattr", /* DixSetAttrAccess */ + NULL }}, + { "x_cursor", + { "read", /* DixReadAccess */ + "write", /* DixWriteAccess */ + "destroy", /* DixDestroyAccess */ + "create", /* DixCreateAccess */ + "getattr", /* DixGetAttrAccess */ + "setattr", /* DixSetAttrAccess */ + "", /* DixListPropAccess */ + "", /* DixGetPropAccess */ + "", /* DixSetPropAccess */ + "", /* DixGetFocusAccess */ + "", /* DixSetFocusAccess */ + "", /* DixListAccess */ + "", /* DixAddAccess */ + "", /* DixRemoveAccess */ + "", /* DixHideAccess */ + "", /* DixShowAccess */ + "", /* DixBlendAccess */ + "", /* DixGrabAccess */ + "", /* DixFreezeAccess */ + "", /* DixForceAccess */ + "", /* DixInstallAccess */ + "", /* DixUninstallAccess */ + "", /* DixSendAccess */ + "", /* DixReceiveAccess */ + "use", /* DixUseAccess */ + NULL }}, + { "x_client", + { "", /* DixReadAccess */ + "", /* DixWriteAccess */ + "destroy", /* DixDestroyAccess */ + "", /* DixCreateAccess */ + "getattr", /* DixGetAttrAccess */ + "setattr", /* DixSetAttrAccess */ + "", /* DixListPropAccess */ + "", /* DixGetPropAccess */ + "", /* DixSetPropAccess */ + "", /* DixGetFocusAccess */ + "", /* DixSetFocusAccess */ + "", /* DixListAccess */ + "", /* DixAddAccess */ + "", /* DixRemoveAccess */ + "", /* DixHideAccess */ + "", /* DixShowAccess */ + "", /* DixBlendAccess */ + "", /* DixGrabAccess */ + "", /* DixFreezeAccess */ + "", /* DixForceAccess */ + "", /* DixInstallAccess */ + "", /* DixUninstallAccess */ + "", /* DixSendAccess */ + "", /* DixReceiveAccess */ + "", /* DixUseAccess */ + "manage", /* DixManageAccess */ + NULL }}, + { "x_pointer", + { "read", /* DixReadAccess */ + "write", /* DixWriteAccess */ + "destroy", /* DixDestroyAccess */ + "create", /* DixCreateAccess */ + "getattr", /* DixGetAttrAccess */ + "setattr", /* DixSetAttrAccess */ + "list_property", /* DixListPropAccess */ + "get_property", /* DixGetPropAccess */ + "set_property", /* DixSetPropAccess */ + "getfocus", /* DixGetFocusAccess */ + "setfocus", /* DixSetFocusAccess */ + "", /* DixListAccess */ + "add", /* DixAddAccess */ + "remove", /* DixRemoveAccess */ + "", /* DixHideAccess */ + "", /* DixShowAccess */ + "", /* DixBlendAccess */ + "grab", /* DixGrabAccess */ + "freeze", /* DixFreezeAccess */ + "force_cursor", /* DixForceAccess */ + "", /* DixInstallAccess */ + "", /* DixUninstallAccess */ + "", /* DixSendAccess */ + "", /* DixReceiveAccess */ + "use", /* DixUseAccess */ + "manage", /* DixManageAccess */ + "", /* DixDebugAccess */ + "bell", /* DixBellAccess */ + NULL }}, + { "x_keyboard", + { "read", /* DixReadAccess */ + "write", /* DixWriteAccess */ + "destroy", /* DixDestroyAccess */ + "create", /* DixCreateAccess */ + "getattr", /* DixGetAttrAccess */ + "setattr", /* DixSetAttrAccess */ + "list_property", /* DixListPropAccess */ + "get_property", /* DixGetPropAccess */ + "set_property", /* DixSetPropAccess */ + "getfocus", /* DixGetFocusAccess */ + "setfocus", /* DixSetFocusAccess */ + "", /* DixListAccess */ + "add", /* DixAddAccess */ + "remove", /* DixRemoveAccess */ + "", /* DixHideAccess */ + "", /* DixShowAccess */ + "", /* DixBlendAccess */ + "grab", /* DixGrabAccess */ + "freeze", /* DixFreezeAccess */ + "force_cursor", /* DixForceAccess */ + "", /* DixInstallAccess */ + "", /* DixUninstallAccess */ + "", /* DixSendAccess */ + "", /* DixReceiveAccess */ + "use", /* DixUseAccess */ + "manage", /* DixManageAccess */ + "", /* DixDebugAccess */ + "bell", /* DixBellAccess */ + NULL }}, + { "x_server", + { "record", /* DixReadAccess */ + "", /* DixWriteAccess */ + "", /* DixDestroyAccess */ + "", /* DixCreateAccess */ + "getattr", /* DixGetAttrAccess */ + "setattr", /* DixSetAttrAccess */ + "", /* DixListPropAccess */ + "", /* DixGetPropAccess */ + "", /* DixSetPropAccess */ + "", /* DixGetFocusAccess */ + "", /* DixSetFocusAccess */ + "", /* DixListAccess */ + "", /* DixAddAccess */ + "", /* DixRemoveAccess */ + "", /* DixHideAccess */ + "", /* DixShowAccess */ + "", /* DixBlendAccess */ + "grab", /* DixGrabAccess */ + "", /* DixFreezeAccess */ + "", /* DixForceAccess */ + "", /* DixInstallAccess */ + "", /* DixUninstallAccess */ + "", /* DixSendAccess */ + "", /* DixReceiveAccess */ + "", /* DixUseAccess */ + "manage", /* DixManageAccess */ + "debug", /* DixDebugAccess */ + NULL }}, + { "x_extension", + { "", /* DixReadAccess */ + "", /* DixWriteAccess */ + "", /* DixDestroyAccess */ + "", /* DixCreateAccess */ + "query", /* DixGetAttrAccess */ + "", /* DixSetAttrAccess */ + "", /* DixListPropAccess */ + "", /* DixGetPropAccess */ + "", /* DixSetPropAccess */ + "", /* DixGetFocusAccess */ + "", /* DixSetFocusAccess */ + "", /* DixListAccess */ + "", /* DixAddAccess */ + "", /* DixRemoveAccess */ + "", /* DixHideAccess */ + "", /* DixShowAccess */ + "", /* DixBlendAccess */ + "", /* DixGrabAccess */ + "", /* DixFreezeAccess */ + "", /* DixForceAccess */ + "", /* DixInstallAccess */ + "", /* DixUninstallAccess */ + "", /* DixSendAccess */ + "", /* DixReceiveAccess */ + "use", /* DixUseAccess */ + NULL }}, + { "x_event", + { "", /* DixReadAccess */ + "", /* DixWriteAccess */ + "", /* DixDestroyAccess */ + "", /* DixCreateAccess */ + "", /* DixGetAttrAccess */ + "", /* DixSetAttrAccess */ + "", /* DixListPropAccess */ + "", /* DixGetPropAccess */ + "", /* DixSetPropAccess */ + "", /* DixGetFocusAccess */ + "", /* DixSetFocusAccess */ + "", /* DixListAccess */ + "", /* DixAddAccess */ + "", /* DixRemoveAccess */ + "", /* DixHideAccess */ + "", /* DixShowAccess */ + "", /* DixBlendAccess */ + "", /* DixGrabAccess */ + "", /* DixFreezeAccess */ + "", /* DixForceAccess */ + "", /* DixInstallAccess */ + "", /* DixUninstallAccess */ + "send", /* DixSendAccess */ + "receive", /* DixReceiveAccess */ + NULL }}, + { "x_synthetic_event", + { "", /* DixReadAccess */ + "", /* DixWriteAccess */ + "", /* DixDestroyAccess */ + "", /* DixCreateAccess */ + "", /* DixGetAttrAccess */ + "", /* DixSetAttrAccess */ + "", /* DixListPropAccess */ + "", /* DixGetPropAccess */ + "", /* DixSetPropAccess */ + "", /* DixGetFocusAccess */ + "", /* DixSetFocusAccess */ + "", /* DixListAccess */ + "", /* DixAddAccess */ + "", /* DixRemoveAccess */ + "", /* DixHideAccess */ + "", /* DixShowAccess */ + "", /* DixBlendAccess */ + "", /* DixGrabAccess */ + "", /* DixFreezeAccess */ + "", /* DixForceAccess */ + "", /* DixInstallAccess */ + "", /* DixUninstallAccess */ + "send", /* DixSendAccess */ + "receive", /* DixReceiveAccess */ + NULL }}, + { "x_resource", + { "read", /* DixReadAccess */ + "write", /* DixWriteAccess */ + "write", /* DixDestroyAccess */ + "write", /* DixCreateAccess */ + "read", /* DixGetAttrAccess */ + "write", /* DixSetAttrAccess */ + "read", /* DixListPropAccess */ + "read", /* DixGetPropAccess */ + "write", /* DixSetPropAccess */ + "read", /* DixGetFocusAccess */ + "write", /* DixSetFocusAccess */ + "read", /* DixListAccess */ + "write", /* DixAddAccess */ + "write", /* DixRemoveAccess */ + "write", /* DixHideAccess */ + "read", /* DixShowAccess */ + "read", /* DixBlendAccess */ + "write", /* DixGrabAccess */ + "write", /* DixFreezeAccess */ + "write", /* DixForceAccess */ + "write", /* DixInstallAccess */ + "write", /* DixUninstallAccess */ + "write", /* DixSendAccess */ + "read", /* DixReceiveAccess */ + "read", /* DixUseAccess */ + "write", /* DixManageAccess */ + "read", /* DixDebugAccess */ + "write", /* DixBellAccess */ + NULL }}, + { NULL } +}; + +/* x_resource "read" bits from the list above */ +#define SELinuxReadMask (DixReadAccess|DixGetAttrAccess|DixListPropAccess| \ + DixGetPropAccess|DixGetFocusAccess|DixListAccess| \ + DixShowAccess|DixBlendAccess|DixReceiveAccess| \ + DixUseAccess|DixDebugAccess) + +#endif /* _XSELINUX_NEED_FLASK_MAP */ +#endif /* _XSELINUXINT_H */ diff --git a/xorg-server/Xext/xtest.c b/xorg-server/Xext/xtest.c index 99b6711f2..05395a7c1 100644 --- a/xorg-server/Xext/xtest.c +++ b/xorg-server/Xext/xtest.c @@ -1,713 +1,713 @@ -/* - - Copyright 1992, 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. - - */ - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include -#include -#include -#include "misc.h" -#include "os.h" -#include "dixstruct.h" -#include "extnsionst.h" -#include "windowstr.h" -#include "inputstr.h" -#include "scrnintstr.h" -#include "dixevents.h" -#include "sleepuntil.h" -#include "mi.h" -#include "xkbsrv.h" -#include "xkbstr.h" -#include -#include -#include -#include "exglobals.h" -#include "mipointer.h" -#include "xserver-properties.h" -#include "exevents.h" - -#include "modinit.h" - -extern int DeviceValuator; - -/* XTest events are sent during request processing and may be interruped by - * a SIGIO. We need a separate event list to avoid events overwriting each - * other's memory */ -static EventListPtr xtest_evlist; - -/* Used to store if a device is an XTest Virtual device */ -static int XTestDevicePrivateKeyIndex; -DevPrivateKey XTestDevicePrivateKey = &XTestDevicePrivateKeyIndex; - -/** - * xtestpointer - * is the virtual pointer for XTest. It is the first slave - * device of the VCP. - * xtestkeyboard - * is the virtual keyboard for XTest. It is the first slave - * device of the VCK - * - * Neither of these devices can be deleted. - */ -DeviceIntPtr xtestpointer, xtestkeyboard; - -#ifdef PANORAMIX -#include "panoramiX.h" -#include "panoramiXsrv.h" -#endif - -static int XTestSwapFakeInput( - ClientPtr /* client */, - xReq * /* req */ - ); - -static DISPATCH_PROC(ProcXTestCompareCursor); -static DISPATCH_PROC(ProcXTestDispatch); -static DISPATCH_PROC(ProcXTestFakeInput); -static DISPATCH_PROC(ProcXTestGetVersion); -static DISPATCH_PROC(ProcXTestGrabControl); -static DISPATCH_PROC(SProcXTestCompareCursor); -static DISPATCH_PROC(SProcXTestDispatch); -static DISPATCH_PROC(SProcXTestFakeInput); -static DISPATCH_PROC(SProcXTestGetVersion); -static DISPATCH_PROC(SProcXTestGrabControl); - -void -XTestExtensionInit(INITARGS) -{ - AddExtension(XTestExtensionName, 0, 0, - ProcXTestDispatch, SProcXTestDispatch, - NULL, StandardMinorOpcode); - - xtest_evlist = InitEventList(GetMaximumEventsNum()); -} - -static int -ProcXTestGetVersion(ClientPtr client) -{ - xXTestGetVersionReply rep; - int n; - - REQUEST_SIZE_MATCH(xXTestGetVersionReq); - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.majorVersion = XTestMajorVersion; - rep.minorVersion = XTestMinorVersion; - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - swaps(&rep.minorVersion, n); - } - WriteToClient(client, sizeof(xXTestGetVersionReply), (char *)&rep); - return(client->noClientException); -} - -static int -ProcXTestCompareCursor(ClientPtr client) -{ - REQUEST(xXTestCompareCursorReq); - xXTestCompareCursorReply rep; - WindowPtr pWin; - CursorPtr pCursor; - int n, rc; - DeviceIntPtr ptr = PickPointer(client); - - REQUEST_SIZE_MATCH(xXTestCompareCursorReq); - rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); - if (rc != Success) - return rc; - if (stuff->cursor == None) - pCursor = NullCursor; - else if (stuff->cursor == XTestCurrentCursor) - pCursor = GetSpriteCursor(ptr); - else { - rc = dixLookupResourceByType((pointer *)&pCursor, stuff->cursor, RT_CURSOR, - client, DixReadAccess); - if (rc != Success) - { - client->errorValue = stuff->cursor; - return (rc == BadValue) ? BadCursor : rc; - } - } - rep.type = X_Reply; - rep.length = 0; - rep.sequenceNumber = client->sequence; - rep.same = (wCursor(pWin) == pCursor); - if (client->swapped) { - swaps(&rep.sequenceNumber, n); - } - WriteToClient(client, sizeof(xXTestCompareCursorReply), (char *)&rep); - return(client->noClientException); -} - -static int -ProcXTestFakeInput(ClientPtr client) -{ - REQUEST(xXTestFakeInputReq); - int nev, n, type, rc; - xEvent *ev; - DeviceIntPtr dev = NULL; - WindowPtr root; - Bool extension = FALSE; - deviceValuator *dv = NULL; - int valuators[MAX_VALUATORS] = {0}; - int numValuators = 0; - int firstValuator = 0; - int nevents = 0; - int i; - int base = 0; - int flags = 0; - int need_ptr_update = 1; - - nev = (stuff->length << 2) - sizeof(xReq); - if ((nev % sizeof(xEvent)) || !nev) - return BadLength; - nev /= sizeof(xEvent); - UpdateCurrentTime(); - ev = (xEvent *)&((xReq *)stuff)[1]; - type = ev->u.u.type & 0177; - - if (type >= EXTENSION_EVENT_BASE) - { - extension = TRUE; - - /* check device */ - rc = dixLookupDevice(&dev, stuff->deviceid & 0177, client, - DixWriteAccess); - if (rc != Success) - { - client->errorValue = stuff->deviceid & 0177; - return rc; - } - - /* check type */ - type -= DeviceValuator; - switch (type) { - case XI_DeviceKeyPress: - case XI_DeviceKeyRelease: - if (!dev->key) - { - client->errorValue = ev->u.u.type; - return BadValue; - } - break; - case XI_DeviceButtonPress: - case XI_DeviceButtonRelease: - if (!dev->button) - { - client->errorValue = ev->u.u.type; - return BadValue; - } - break; - case XI_DeviceMotionNotify: - if (!dev->valuator) - { - client->errorValue = ev->u.u.type; - return BadValue; - } - break; - case XI_ProximityIn: - case XI_ProximityOut: - if (!dev->proximity) - { - client->errorValue = ev->u.u.type; - return BadValue; - } - break; - default: - client->errorValue = ev->u.u.type; - return BadValue; - } - - /* check validity */ - if (nev == 1 && type == XI_DeviceMotionNotify) - return BadLength; /* DevMotion must be followed by DevValuator */ - - if (type == XI_DeviceMotionNotify) - { - firstValuator = ((deviceValuator *)(ev+1))->first_valuator; - if (firstValuator > dev->valuator->numAxes) - { - client->errorValue = ev->u.u.type; - return BadValue; - } - - if (ev->u.u.detail == xFalse) - flags |= POINTER_ABSOLUTE; - } else - { - firstValuator = 0; - flags |= POINTER_ABSOLUTE; - } - - if (nev > 1 && !dev->valuator) - { - client->errorValue = dv->first_valuator; - return BadValue; - } - - - /* check validity of valuator events */ - base = firstValuator; - for (n = 1; n < nev; n++) - { - dv = (deviceValuator *)(ev + n); - if (dv->type != DeviceValuator) - { - client->errorValue = dv->type; - return BadValue; - } - if (dv->first_valuator != base) - { - client->errorValue = dv->first_valuator; - return BadValue; - } - switch(dv->num_valuators) - { - case 6: valuators[base + 5] = dv->valuator5; - case 5: valuators[base + 4] = dv->valuator4; - case 4: valuators[base + 3] = dv->valuator3; - case 3: valuators[base + 2] = dv->valuator2; - case 2: valuators[base + 1] = dv->valuator1; - case 1: valuators[base] = dv->valuator0; - break; - default: - client->errorValue = dv->num_valuators; - return BadValue; - } - - base += dv->num_valuators; - numValuators += dv->num_valuators; - - if (firstValuator + numValuators > dev->valuator->numAxes) - { - client->errorValue = dv->num_valuators; - return BadValue; - } - } - type = type - XI_DeviceKeyPress + KeyPress; - - } else - { - if (nev != 1) - return BadLength; - switch (type) - { - case KeyPress: - case KeyRelease: - dev = PickKeyboard(client); - break; - case ButtonPress: - case ButtonRelease: - dev = PickPointer(client); - break; - case MotionNotify: - dev = PickPointer(client); - valuators[0] = ev->u.keyButtonPointer.rootX; - valuators[1] = ev->u.keyButtonPointer.rootY; - numValuators = 2; - firstValuator = 0; - if (ev->u.u.detail == xFalse) - flags = POINTER_ABSOLUTE | POINTER_SCREEN; - break; - default: - client->errorValue = ev->u.u.type; - return BadValue; - } - - dev = GetXTestDevice(dev); - } - - /* If the event has a time set, wait for it to pass */ - if (ev->u.keyButtonPointer.time) - { - TimeStamp activateTime; - CARD32 ms; - - activateTime = currentTime; - ms = activateTime.milliseconds + ev->u.keyButtonPointer.time; - if (ms < activateTime.milliseconds) - activateTime.months++; - activateTime.milliseconds = ms; - ev->u.keyButtonPointer.time = 0; - - /* see mbuf.c:QueueDisplayRequest (from the deprecated Multibuffer - * extension) for code similar to this */ - - if (!ClientSleepUntil(client, &activateTime, NULL, NULL)) - { - return BadAlloc; - } - /* swap the request back so we can simply re-execute it */ - if (client->swapped) - { - (void) XTestSwapFakeInput(client, (xReq *)stuff); - swaps(&stuff->length, n); - } - ResetCurrentRequest (client); - client->sequence--; - return Success; - } - - switch (type) - { - case KeyPress: - case KeyRelease: - if (!dev->key) - return BadDevice; - - if (ev->u.u.detail < dev->key->xkbInfo->desc->min_key_code || - ev->u.u.detail > dev->key->xkbInfo->desc->max_key_code) - { - client->errorValue = ev->u.u.detail; - return BadValue; - } - - need_ptr_update = 0; - break; - case MotionNotify: - if (!dev->valuator) - return BadDevice; - - /* broken lib, XI events have root uninitialized */ - if (extension || ev->u.keyButtonPointer.root == None) - root = GetCurrentRootWindow(dev); - else - { - rc = dixLookupWindow(&root, ev->u.keyButtonPointer.root, - client, DixGetAttrAccess); - if (rc != Success) - return rc; - if (root->parent) - { - client->errorValue = ev->u.keyButtonPointer.root; - return BadValue; - } - } - if (ev->u.u.detail != xTrue && ev->u.u.detail != xFalse) - { - client->errorValue = ev->u.u.detail; - return BadValue; - } - - /* FIXME: Xinerama! */ - - break; - case ButtonPress: - case ButtonRelease: - if (!dev->button) - return BadDevice; - - if (!ev->u.u.detail || ev->u.u.detail > dev->button->numButtons) - { - client->errorValue = ev->u.u.detail; - return BadValue; - } - break; - } - if (screenIsSaved == SCREEN_SAVER_ON) - dixSaveScreens(serverClient, SCREEN_SAVER_OFF, ScreenSaverReset); - - switch(type) { - case MotionNotify: - nevents = GetPointerEvents(xtest_evlist, dev, type, 0, flags, - firstValuator, numValuators, valuators); - break; - case ButtonPress: - case ButtonRelease: - nevents = GetPointerEvents(xtest_evlist, dev, type, ev->u.u.detail, - flags, firstValuator, - numValuators, valuators); - break; - case KeyPress: - case KeyRelease: - nevents = GetKeyboardEvents(xtest_evlist, dev, type, ev->u.u.detail); - break; - } - - for (i = 0; i < nevents; i++) - mieqProcessDeviceEvent(dev, (InternalEvent*)(xtest_evlist+i)->event, NULL); - - if (need_ptr_update) - miPointerUpdateSprite(dev); - return client->noClientException; -} - -static int -ProcXTestGrabControl(ClientPtr client) -{ - REQUEST(xXTestGrabControlReq); - - REQUEST_SIZE_MATCH(xXTestGrabControlReq); - if ((stuff->impervious != xTrue) && (stuff->impervious != xFalse)) - { - client->errorValue = stuff->impervious; - return(BadValue); - } - if (stuff->impervious) - MakeClientGrabImpervious(client); - else - MakeClientGrabPervious(client); - return(client->noClientException); -} - -static int -ProcXTestDispatch (ClientPtr client) -{ - REQUEST(xReq); - switch (stuff->data) - { - case X_XTestGetVersion: - return ProcXTestGetVersion(client); - case X_XTestCompareCursor: - return ProcXTestCompareCursor(client); - case X_XTestFakeInput: - return ProcXTestFakeInput(client); - case X_XTestGrabControl: - return ProcXTestGrabControl(client); - default: - return BadRequest; - } -} - -static int -SProcXTestGetVersion(ClientPtr client) -{ - int n; - REQUEST(xXTestGetVersionReq); - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH(xXTestGetVersionReq); - swaps(&stuff->minorVersion, n); - return ProcXTestGetVersion(client); -} - -static int -SProcXTestCompareCursor(ClientPtr client) -{ - int n; - REQUEST(xXTestCompareCursorReq); - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH(xXTestCompareCursorReq); - swapl(&stuff->window, n); - swapl(&stuff->cursor, n); - return ProcXTestCompareCursor(client); -} - -static int -XTestSwapFakeInput(ClientPtr client, xReq *req) -{ - int nev; - xEvent *ev; - xEvent sev; - EventSwapPtr proc; - - nev = ((req->length << 2) - sizeof(xReq)) / sizeof(xEvent); - for (ev = (xEvent *)&req[1]; --nev >= 0; ev++) - { - /* Swap event */ - proc = EventSwapVector[ev->u.u.type & 0177]; - /* no swapping proc; invalid event type? */ - if (!proc || proc == NotImplemented) { - client->errorValue = ev->u.u.type; - return BadValue; - } - (*proc)(ev, &sev); - *ev = sev; - } - return Success; -} - -static int -SProcXTestFakeInput(ClientPtr client) -{ - int n; - REQUEST(xReq); - - swaps(&stuff->length, n); - n = XTestSwapFakeInput(client, stuff); - if (n != Success) - return n; - return ProcXTestFakeInput(client); -} - -static int -SProcXTestGrabControl(ClientPtr client) -{ - int n; - REQUEST(xXTestGrabControlReq); - - swaps(&stuff->length, n); - REQUEST_SIZE_MATCH(xXTestGrabControlReq); - return ProcXTestGrabControl(client); -} - -static int -SProcXTestDispatch (ClientPtr client) -{ - REQUEST(xReq); - switch (stuff->data) - { - case X_XTestGetVersion: - return SProcXTestGetVersion(client); - case X_XTestCompareCursor: - return SProcXTestCompareCursor(client); - case X_XTestFakeInput: - return SProcXTestFakeInput(client); - case X_XTestGrabControl: - return SProcXTestGrabControl(client); - default: - return BadRequest; - } -} - -/** - * Allocate an virtual slave device for xtest events, this - * is a slave device to inputInfo master devices - */ -void InitXTestDevices(void) -{ - if(AllocXTestDevice(serverClient, "Virtual core", - &xtestpointer, &xtestkeyboard, - inputInfo.pointer, inputInfo.keyboard) != Success) - FatalError("Failed to allocate XTest devices"); - - if (ActivateDevice(xtestpointer, TRUE) != Success || - ActivateDevice(xtestkeyboard, TRUE) != Success) - FatalError("Failed to activate XTest core devices."); - if (!EnableDevice(xtestpointer, TRUE) || - !EnableDevice(xtestkeyboard, TRUE)) - FatalError("Failed to enable XTest core devices."); - - AttachDevice(NULL, xtestpointer, inputInfo.pointer); - AttachDevice(NULL, xtestkeyboard, inputInfo.keyboard); -} - -/** - * Don't allow changing the XTest property. - */ -static int -DeviceSetXTestProperty(DeviceIntPtr dev, Atom property, - XIPropertyValuePtr prop, BOOL checkonly) -{ - if (property == XIGetKnownProperty(XI_PROP_XTEST_DEVICE)) - return BadAccess; - - return Success; -} - -/** - * Allocate a device pair that is initialised as a slave - * device with properties that identify the devices as belonging - * to XTest subsystem. - * This only creates the pair, Activate/Enable Device - * still need to be called. - */ -int AllocXTestDevice (ClientPtr client, char* name, - DeviceIntPtr* ptr, DeviceIntPtr* keybd, - DeviceIntPtr master_ptr, DeviceIntPtr master_keybd) -{ - int retval; - int len = strlen(name); - char *xtestname = xcalloc(len + 7, 1 ); - char dummy = 1; - - strncpy( xtestname, name, len); - strncat( xtestname, " XTEST", 6 ); - - retval = AllocDevicePair( client, xtestname, ptr, keybd, CorePointerProc, CoreKeyboardProc, FALSE); - if ( retval == Success ){ - dixSetPrivate(&((*ptr)->devPrivates), XTestDevicePrivateKey, (void *)(intptr_t)master_ptr->id); - dixSetPrivate(&((*keybd)->devPrivates), XTestDevicePrivateKey, (void *)(intptr_t)master_keybd->id); - - XIChangeDeviceProperty(*ptr, XIGetKnownProperty(XI_PROP_XTEST_DEVICE), - XA_INTEGER, 8, PropModeReplace, 1, &dummy, - FALSE); - XISetDevicePropertyDeletable(*ptr, XIGetKnownProperty(XI_PROP_XTEST_DEVICE), FALSE); - XIRegisterPropertyHandler(*ptr, DeviceSetXTestProperty, NULL, NULL); - XIChangeDeviceProperty(*keybd, XIGetKnownProperty(XI_PROP_XTEST_DEVICE), - XA_INTEGER, 8, PropModeReplace, 1, &dummy, - FALSE); - XISetDevicePropertyDeletable(*keybd, XIGetKnownProperty(XI_PROP_XTEST_DEVICE), FALSE); - XIRegisterPropertyHandler(*keybd, DeviceSetXTestProperty, NULL, NULL); - } - - xfree( xtestname ); - - return retval; -} - -/** - * If master is NULL, return TRUE if the given device is an xtest device or - * FALSE otherwise. - * If master is not NULL, return TRUE if the given device is this master's - * xtest device. - */ -BOOL -IsXTestDevice(DeviceIntPtr dev, DeviceIntPtr master) -{ - int is_XTest = FALSE; - int mid; - void *tmp; /* shut up, gcc! */ - - if (IsMaster(dev)) - return is_XTest; - - tmp = dixLookupPrivate(&dev->devPrivates, XTestDevicePrivateKey); - mid = (intptr_t)tmp; - - /* deviceid 0 is reserved for XIAllDevices, non-zero mid means XTest - * device */ - if ((!master && mid) || - (master && mid == master->id)) - is_XTest = TRUE; - - return is_XTest; -} - -/** - * @return The X Test virtual device for the given master. - */ -DeviceIntPtr -GetXTestDevice(DeviceIntPtr master) -{ - DeviceIntPtr it; - - for (it = inputInfo.devices; it; it = it->next) - { - if (IsXTestDevice(it, master)) - return it; - } - - /* This only happens if master is a slave device. don't do that */ - return NULL; -} - +/* + + Copyright 1992, 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. + + */ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include +#include +#include +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "extnsionst.h" +#include "windowstr.h" +#include "inputstr.h" +#include "scrnintstr.h" +#include "dixevents.h" +#include "sleepuntil.h" +#include "mi.h" +#include "xkbsrv.h" +#include "xkbstr.h" +#include +#include +#include +#include "exglobals.h" +#include "mipointer.h" +#include "xserver-properties.h" +#include "exevents.h" + +#include "modinit.h" + +extern int DeviceValuator; + +/* XTest events are sent during request processing and may be interruped by + * a SIGIO. We need a separate event list to avoid events overwriting each + * other's memory */ +static EventListPtr xtest_evlist; + +/* Used to store if a device is an XTest Virtual device */ +static int XTestDevicePrivateKeyIndex; +DevPrivateKey XTestDevicePrivateKey = &XTestDevicePrivateKeyIndex; + +/** + * xtestpointer + * is the virtual pointer for XTest. It is the first slave + * device of the VCP. + * xtestkeyboard + * is the virtual keyboard for XTest. It is the first slave + * device of the VCK + * + * Neither of these devices can be deleted. + */ +DeviceIntPtr xtestpointer, xtestkeyboard; + +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" +#endif + +static int XTestSwapFakeInput( + ClientPtr /* client */, + xReq * /* req */ + ); + +static DISPATCH_PROC(ProcXTestCompareCursor); +static DISPATCH_PROC(ProcXTestDispatch); +static DISPATCH_PROC(ProcXTestFakeInput); +static DISPATCH_PROC(ProcXTestGetVersion); +static DISPATCH_PROC(ProcXTestGrabControl); +static DISPATCH_PROC(SProcXTestCompareCursor); +static DISPATCH_PROC(SProcXTestDispatch); +static DISPATCH_PROC(SProcXTestFakeInput); +static DISPATCH_PROC(SProcXTestGetVersion); +static DISPATCH_PROC(SProcXTestGrabControl); + +void +XTestExtensionInit(INITARGS) +{ + AddExtension(XTestExtensionName, 0, 0, + ProcXTestDispatch, SProcXTestDispatch, + NULL, StandardMinorOpcode); + + xtest_evlist = InitEventList(GetMaximumEventsNum()); +} + +static int +ProcXTestGetVersion(ClientPtr client) +{ + xXTestGetVersionReply rep; + int n; + + REQUEST_SIZE_MATCH(xXTestGetVersionReq); + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.majorVersion = XTestMajorVersion; + rep.minorVersion = XTestMinorVersion; + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + swaps(&rep.minorVersion, n); + } + WriteToClient(client, sizeof(xXTestGetVersionReply), (char *)&rep); + return Success; +} + +static int +ProcXTestCompareCursor(ClientPtr client) +{ + REQUEST(xXTestCompareCursorReq); + xXTestCompareCursorReply rep; + WindowPtr pWin; + CursorPtr pCursor; + int n, rc; + DeviceIntPtr ptr = PickPointer(client); + + REQUEST_SIZE_MATCH(xXTestCompareCursorReq); + rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); + if (rc != Success) + return rc; + if (stuff->cursor == None) + pCursor = NullCursor; + else if (stuff->cursor == XTestCurrentCursor) + pCursor = GetSpriteCursor(ptr); + else { + rc = dixLookupResourceByType((pointer *)&pCursor, stuff->cursor, RT_CURSOR, + client, DixReadAccess); + if (rc != Success) + { + client->errorValue = stuff->cursor; + return (rc == BadValue) ? BadCursor : rc; + } + } + rep.type = X_Reply; + rep.length = 0; + rep.sequenceNumber = client->sequence; + rep.same = (wCursor(pWin) == pCursor); + if (client->swapped) { + swaps(&rep.sequenceNumber, n); + } + WriteToClient(client, sizeof(xXTestCompareCursorReply), (char *)&rep); + return Success; +} + +static int +ProcXTestFakeInput(ClientPtr client) +{ + REQUEST(xXTestFakeInputReq); + int nev, n, type, rc; + xEvent *ev; + DeviceIntPtr dev = NULL; + WindowPtr root; + Bool extension = FALSE; + deviceValuator *dv = NULL; + int valuators[MAX_VALUATORS] = {0}; + int numValuators = 0; + int firstValuator = 0; + int nevents = 0; + int i; + int base = 0; + int flags = 0; + int need_ptr_update = 1; + + nev = (stuff->length << 2) - sizeof(xReq); + if ((nev % sizeof(xEvent)) || !nev) + return BadLength; + nev /= sizeof(xEvent); + UpdateCurrentTime(); + ev = (xEvent *)&((xReq *)stuff)[1]; + type = ev->u.u.type & 0177; + + if (type >= EXTENSION_EVENT_BASE) + { + extension = TRUE; + + /* check device */ + rc = dixLookupDevice(&dev, stuff->deviceid & 0177, client, + DixWriteAccess); + if (rc != Success) + { + client->errorValue = stuff->deviceid & 0177; + return rc; + } + + /* check type */ + type -= DeviceValuator; + switch (type) { + case XI_DeviceKeyPress: + case XI_DeviceKeyRelease: + if (!dev->key) + { + client->errorValue = ev->u.u.type; + return BadValue; + } + break; + case XI_DeviceButtonPress: + case XI_DeviceButtonRelease: + if (!dev->button) + { + client->errorValue = ev->u.u.type; + return BadValue; + } + break; + case XI_DeviceMotionNotify: + if (!dev->valuator) + { + client->errorValue = ev->u.u.type; + return BadValue; + } + break; + case XI_ProximityIn: + case XI_ProximityOut: + if (!dev->proximity) + { + client->errorValue = ev->u.u.type; + return BadValue; + } + break; + default: + client->errorValue = ev->u.u.type; + return BadValue; + } + + /* check validity */ + if (nev == 1 && type == XI_DeviceMotionNotify) + return BadLength; /* DevMotion must be followed by DevValuator */ + + if (type == XI_DeviceMotionNotify) + { + firstValuator = ((deviceValuator *)(ev+1))->first_valuator; + if (firstValuator > dev->valuator->numAxes) + { + client->errorValue = ev->u.u.type; + return BadValue; + } + + if (ev->u.u.detail == xFalse) + flags |= POINTER_ABSOLUTE; + } else + { + firstValuator = 0; + flags |= POINTER_ABSOLUTE; + } + + if (nev > 1 && !dev->valuator) + { + client->errorValue = dv->first_valuator; + return BadValue; + } + + + /* check validity of valuator events */ + base = firstValuator; + for (n = 1; n < nev; n++) + { + dv = (deviceValuator *)(ev + n); + if (dv->type != DeviceValuator) + { + client->errorValue = dv->type; + return BadValue; + } + if (dv->first_valuator != base) + { + client->errorValue = dv->first_valuator; + return BadValue; + } + switch(dv->num_valuators) + { + case 6: valuators[base + 5] = dv->valuator5; + case 5: valuators[base + 4] = dv->valuator4; + case 4: valuators[base + 3] = dv->valuator3; + case 3: valuators[base + 2] = dv->valuator2; + case 2: valuators[base + 1] = dv->valuator1; + case 1: valuators[base] = dv->valuator0; + break; + default: + client->errorValue = dv->num_valuators; + return BadValue; + } + + base += dv->num_valuators; + numValuators += dv->num_valuators; + + if (firstValuator + numValuators > dev->valuator->numAxes) + { + client->errorValue = dv->num_valuators; + return BadValue; + } + } + type = type - XI_DeviceKeyPress + KeyPress; + + } else + { + if (nev != 1) + return BadLength; + switch (type) + { + case KeyPress: + case KeyRelease: + dev = PickKeyboard(client); + break; + case ButtonPress: + case ButtonRelease: + dev = PickPointer(client); + break; + case MotionNotify: + dev = PickPointer(client); + valuators[0] = ev->u.keyButtonPointer.rootX; + valuators[1] = ev->u.keyButtonPointer.rootY; + numValuators = 2; + firstValuator = 0; + if (ev->u.u.detail == xFalse) + flags = POINTER_ABSOLUTE | POINTER_SCREEN; + break; + default: + client->errorValue = ev->u.u.type; + return BadValue; + } + + dev = GetXTestDevice(dev); + } + + /* If the event has a time set, wait for it to pass */ + if (ev->u.keyButtonPointer.time) + { + TimeStamp activateTime; + CARD32 ms; + + activateTime = currentTime; + ms = activateTime.milliseconds + ev->u.keyButtonPointer.time; + if (ms < activateTime.milliseconds) + activateTime.months++; + activateTime.milliseconds = ms; + ev->u.keyButtonPointer.time = 0; + + /* see mbuf.c:QueueDisplayRequest (from the deprecated Multibuffer + * extension) for code similar to this */ + + if (!ClientSleepUntil(client, &activateTime, NULL, NULL)) + { + return BadAlloc; + } + /* swap the request back so we can simply re-execute it */ + if (client->swapped) + { + (void) XTestSwapFakeInput(client, (xReq *)stuff); + swaps(&stuff->length, n); + } + ResetCurrentRequest (client); + client->sequence--; + return Success; + } + + switch (type) + { + case KeyPress: + case KeyRelease: + if (!dev->key) + return BadDevice; + + if (ev->u.u.detail < dev->key->xkbInfo->desc->min_key_code || + ev->u.u.detail > dev->key->xkbInfo->desc->max_key_code) + { + client->errorValue = ev->u.u.detail; + return BadValue; + } + + need_ptr_update = 0; + break; + case MotionNotify: + if (!dev->valuator) + return BadDevice; + + /* broken lib, XI events have root uninitialized */ + if (extension || ev->u.keyButtonPointer.root == None) + root = GetCurrentRootWindow(dev); + else + { + rc = dixLookupWindow(&root, ev->u.keyButtonPointer.root, + client, DixGetAttrAccess); + if (rc != Success) + return rc; + if (root->parent) + { + client->errorValue = ev->u.keyButtonPointer.root; + return BadValue; + } + } + if (ev->u.u.detail != xTrue && ev->u.u.detail != xFalse) + { + client->errorValue = ev->u.u.detail; + return BadValue; + } + + /* FIXME: Xinerama! */ + + break; + case ButtonPress: + case ButtonRelease: + if (!dev->button) + return BadDevice; + + if (!ev->u.u.detail || ev->u.u.detail > dev->button->numButtons) + { + client->errorValue = ev->u.u.detail; + return BadValue; + } + break; + } + if (screenIsSaved == SCREEN_SAVER_ON) + dixSaveScreens(serverClient, SCREEN_SAVER_OFF, ScreenSaverReset); + + switch(type) { + case MotionNotify: + nevents = GetPointerEvents(xtest_evlist, dev, type, 0, flags, + firstValuator, numValuators, valuators); + break; + case ButtonPress: + case ButtonRelease: + nevents = GetPointerEvents(xtest_evlist, dev, type, ev->u.u.detail, + flags, firstValuator, + numValuators, valuators); + break; + case KeyPress: + case KeyRelease: + nevents = GetKeyboardEvents(xtest_evlist, dev, type, ev->u.u.detail); + break; + } + + for (i = 0; i < nevents; i++) + mieqProcessDeviceEvent(dev, (InternalEvent*)(xtest_evlist+i)->event, NULL); + + if (need_ptr_update) + miPointerUpdateSprite(dev); + return Success; +} + +static int +ProcXTestGrabControl(ClientPtr client) +{ + REQUEST(xXTestGrabControlReq); + + REQUEST_SIZE_MATCH(xXTestGrabControlReq); + if ((stuff->impervious != xTrue) && (stuff->impervious != xFalse)) + { + client->errorValue = stuff->impervious; + return(BadValue); + } + if (stuff->impervious) + MakeClientGrabImpervious(client); + else + MakeClientGrabPervious(client); + return Success; +} + +static int +ProcXTestDispatch (ClientPtr client) +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_XTestGetVersion: + return ProcXTestGetVersion(client); + case X_XTestCompareCursor: + return ProcXTestCompareCursor(client); + case X_XTestFakeInput: + return ProcXTestFakeInput(client); + case X_XTestGrabControl: + return ProcXTestGrabControl(client); + default: + return BadRequest; + } +} + +static int +SProcXTestGetVersion(ClientPtr client) +{ + int n; + REQUEST(xXTestGetVersionReq); + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXTestGetVersionReq); + swaps(&stuff->minorVersion, n); + return ProcXTestGetVersion(client); +} + +static int +SProcXTestCompareCursor(ClientPtr client) +{ + int n; + REQUEST(xXTestCompareCursorReq); + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXTestCompareCursorReq); + swapl(&stuff->window, n); + swapl(&stuff->cursor, n); + return ProcXTestCompareCursor(client); +} + +static int +XTestSwapFakeInput(ClientPtr client, xReq *req) +{ + int nev; + xEvent *ev; + xEvent sev; + EventSwapPtr proc; + + nev = ((req->length << 2) - sizeof(xReq)) / sizeof(xEvent); + for (ev = (xEvent *)&req[1]; --nev >= 0; ev++) + { + /* Swap event */ + proc = EventSwapVector[ev->u.u.type & 0177]; + /* no swapping proc; invalid event type? */ + if (!proc || proc == NotImplemented) { + client->errorValue = ev->u.u.type; + return BadValue; + } + (*proc)(ev, &sev); + *ev = sev; + } + return Success; +} + +static int +SProcXTestFakeInput(ClientPtr client) +{ + int n; + REQUEST(xReq); + + swaps(&stuff->length, n); + n = XTestSwapFakeInput(client, stuff); + if (n != Success) + return n; + return ProcXTestFakeInput(client); +} + +static int +SProcXTestGrabControl(ClientPtr client) +{ + int n; + REQUEST(xXTestGrabControlReq); + + swaps(&stuff->length, n); + REQUEST_SIZE_MATCH(xXTestGrabControlReq); + return ProcXTestGrabControl(client); +} + +static int +SProcXTestDispatch (ClientPtr client) +{ + REQUEST(xReq); + switch (stuff->data) + { + case X_XTestGetVersion: + return SProcXTestGetVersion(client); + case X_XTestCompareCursor: + return SProcXTestCompareCursor(client); + case X_XTestFakeInput: + return SProcXTestFakeInput(client); + case X_XTestGrabControl: + return SProcXTestGrabControl(client); + default: + return BadRequest; + } +} + +/** + * Allocate an virtual slave device for xtest events, this + * is a slave device to inputInfo master devices + */ +void InitXTestDevices(void) +{ + if(AllocXTestDevice(serverClient, "Virtual core", + &xtestpointer, &xtestkeyboard, + inputInfo.pointer, inputInfo.keyboard) != Success) + FatalError("Failed to allocate XTest devices"); + + if (ActivateDevice(xtestpointer, TRUE) != Success || + ActivateDevice(xtestkeyboard, TRUE) != Success) + FatalError("Failed to activate XTest core devices."); + if (!EnableDevice(xtestpointer, TRUE) || + !EnableDevice(xtestkeyboard, TRUE)) + FatalError("Failed to enable XTest core devices."); + + AttachDevice(NULL, xtestpointer, inputInfo.pointer); + AttachDevice(NULL, xtestkeyboard, inputInfo.keyboard); +} + +/** + * Don't allow changing the XTest property. + */ +static int +DeviceSetXTestProperty(DeviceIntPtr dev, Atom property, + XIPropertyValuePtr prop, BOOL checkonly) +{ + if (property == XIGetKnownProperty(XI_PROP_XTEST_DEVICE)) + return BadAccess; + + return Success; +} + +/** + * Allocate a device pair that is initialised as a slave + * device with properties that identify the devices as belonging + * to XTest subsystem. + * This only creates the pair, Activate/Enable Device + * still need to be called. + */ +int AllocXTestDevice (ClientPtr client, char* name, + DeviceIntPtr* ptr, DeviceIntPtr* keybd, + DeviceIntPtr master_ptr, DeviceIntPtr master_keybd) +{ + int retval; + int len = strlen(name); + char *xtestname = calloc(len + 7, 1 ); + char dummy = 1; + + strncpy( xtestname, name, len); + strncat( xtestname, " XTEST", 6 ); + + retval = AllocDevicePair( client, xtestname, ptr, keybd, CorePointerProc, CoreKeyboardProc, FALSE); + if ( retval == Success ){ + dixSetPrivate(&((*ptr)->devPrivates), XTestDevicePrivateKey, (void *)(intptr_t)master_ptr->id); + dixSetPrivate(&((*keybd)->devPrivates), XTestDevicePrivateKey, (void *)(intptr_t)master_keybd->id); + + XIChangeDeviceProperty(*ptr, XIGetKnownProperty(XI_PROP_XTEST_DEVICE), + XA_INTEGER, 8, PropModeReplace, 1, &dummy, + FALSE); + XISetDevicePropertyDeletable(*ptr, XIGetKnownProperty(XI_PROP_XTEST_DEVICE), FALSE); + XIRegisterPropertyHandler(*ptr, DeviceSetXTestProperty, NULL, NULL); + XIChangeDeviceProperty(*keybd, XIGetKnownProperty(XI_PROP_XTEST_DEVICE), + XA_INTEGER, 8, PropModeReplace, 1, &dummy, + FALSE); + XISetDevicePropertyDeletable(*keybd, XIGetKnownProperty(XI_PROP_XTEST_DEVICE), FALSE); + XIRegisterPropertyHandler(*keybd, DeviceSetXTestProperty, NULL, NULL); + } + + free( xtestname ); + + return retval; +} + +/** + * If master is NULL, return TRUE if the given device is an xtest device or + * FALSE otherwise. + * If master is not NULL, return TRUE if the given device is this master's + * xtest device. + */ +BOOL +IsXTestDevice(DeviceIntPtr dev, DeviceIntPtr master) +{ + int is_XTest = FALSE; + int mid; + void *tmp; /* shut up, gcc! */ + + if (IsMaster(dev)) + return is_XTest; + + tmp = dixLookupPrivate(&dev->devPrivates, XTestDevicePrivateKey); + mid = (intptr_t)tmp; + + /* deviceid 0 is reserved for XIAllDevices, non-zero mid means XTest + * device */ + if ((!master && mid) || + (master && mid == master->id)) + is_XTest = TRUE; + + return is_XTest; +} + +/** + * @return The X Test virtual device for the given master. + */ +DeviceIntPtr +GetXTestDevice(DeviceIntPtr master) +{ + DeviceIntPtr it; + + for (it = inputInfo.devices; it; it = it->next) + { + if (IsXTestDevice(it, master)) + return it; + } + + /* This only happens if master is a slave device. don't do that */ + return NULL; +} + diff --git a/xorg-server/Xext/xvdisp.c b/xorg-server/Xext/xvdisp.c index 4345672ab..34ea61ad3 100644 --- a/xorg-server/Xext/xvdisp.c +++ b/xorg-server/Xext/xvdisp.c @@ -1,1962 +1,1962 @@ -/*********************************************************** -Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts, -and the Massachusetts Institute of Technology, Cambridge, 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 names of Digital or MIT 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. -******************************************************************/ - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include - -#include -#include -#include "misc.h" -#include "scrnintstr.h" -#include "windowstr.h" -#include "pixmapstr.h" -#include "gcstruct.h" -#include "dixstruct.h" -#include "resource.h" -#include "opaque.h" - -#include -#include -#include "xvdix.h" -#ifdef MITSHM -#include -#endif - -#include "xvdisp.h" - -#ifdef PANORAMIX -#include "panoramiX.h" -#include "panoramiXsrv.h" - -unsigned long XvXRTPort; -#endif - -static int -SWriteQueryExtensionReply( - ClientPtr client, - xvQueryExtensionReply *rep -){ - char n; - - swaps(&rep->sequenceNumber, n); - swapl(&rep->length, n); - swaps(&rep->version, n); - swaps(&rep->revision, n); - - (void)WriteToClient(client, sz_xvQueryExtensionReply, (char *)rep); - - return Success; -} - -static int -SWriteQueryAdaptorsReply( - ClientPtr client, - xvQueryAdaptorsReply *rep -){ - char n; - - swaps(&rep->sequenceNumber, n); - swapl(&rep->length, n); - swaps(&rep->num_adaptors, n); - - (void)WriteToClient(client, sz_xvQueryAdaptorsReply, (char *)rep); - - return Success; -} - -static int -SWriteQueryEncodingsReply( - ClientPtr client, - xvQueryEncodingsReply *rep -){ - char n; - - swaps(&rep->sequenceNumber, n); - swapl(&rep->length, n); - swaps(&rep->num_encodings, n); - - (void)WriteToClient(client, sz_xvQueryEncodingsReply, (char *)rep); - - return Success; -} - -static int -SWriteAdaptorInfo( - ClientPtr client, - xvAdaptorInfo *pAdaptor -){ - char n; - - swapl(&pAdaptor->base_id, n); - swaps(&pAdaptor->name_size, n); - swaps(&pAdaptor->num_ports, n); - swaps(&pAdaptor->num_formats, n); - - (void)WriteToClient(client, sz_xvAdaptorInfo, (char *)pAdaptor); - - return Success; -} - -static int -SWriteEncodingInfo( - ClientPtr client, - xvEncodingInfo *pEncoding -){ - char n; - - swapl(&pEncoding->encoding, n); - swaps(&pEncoding->name_size, n); - swaps(&pEncoding->width, n); - swaps(&pEncoding->height, n); - swapl(&pEncoding->rate.numerator, n); - swapl(&pEncoding->rate.denominator, n); - (void)WriteToClient(client, sz_xvEncodingInfo, (char *)pEncoding); - - return Success; -} - -static int -SWriteFormat( - ClientPtr client, - xvFormat *pFormat -){ - char n; - - swapl(&pFormat->visual, n); - (void)WriteToClient(client, sz_xvFormat, (char *)pFormat); - - return Success; -} - -static int -SWriteAttributeInfo( - ClientPtr client, - xvAttributeInfo *pAtt -){ - char n; - - swapl(&pAtt->flags, n); - swapl(&pAtt->size, n); - swapl(&pAtt->min, n); - swapl(&pAtt->max, n); - (void)WriteToClient(client, sz_xvAttributeInfo, (char *)pAtt); - - return Success; -} - -static int -SWriteImageFormatInfo( - ClientPtr client, - xvImageFormatInfo *pImage -){ - char n; - - swapl(&pImage->id, n); - swapl(&pImage->red_mask, n); - swapl(&pImage->green_mask, n); - swapl(&pImage->blue_mask, n); - swapl(&pImage->y_sample_bits, n); - swapl(&pImage->u_sample_bits, n); - swapl(&pImage->v_sample_bits, n); - swapl(&pImage->horz_y_period, n); - swapl(&pImage->horz_u_period, n); - swapl(&pImage->horz_v_period, n); - swapl(&pImage->vert_y_period, n); - swapl(&pImage->vert_u_period, n); - swapl(&pImage->vert_v_period, n); - - (void)WriteToClient(client, sz_xvImageFormatInfo, (char *)pImage); - - return Success; -} - -static int -SWriteGrabPortReply( - ClientPtr client, - xvGrabPortReply *rep -){ - char n; - - swaps(&rep->sequenceNumber, n); - swapl(&rep->length, n); - - (void)WriteToClient(client, sz_xvGrabPortReply, (char *)rep); - - return Success; -} - -static int -SWriteGetPortAttributeReply( - ClientPtr client, - xvGetPortAttributeReply *rep -){ - char n; - - swaps(&rep->sequenceNumber, n); - swapl(&rep->length, n); - swapl(&rep->value, n); - - (void)WriteToClient(client, sz_xvGetPortAttributeReply, (char *)rep); - - return Success; -} - -static int -SWriteQueryBestSizeReply( - ClientPtr client, - xvQueryBestSizeReply *rep -){ - char n; - - swaps(&rep->sequenceNumber, n); - swapl(&rep->length, n); - swaps(&rep->actual_width, n); - swaps(&rep->actual_height, n); - - (void)WriteToClient(client, sz_xvQueryBestSizeReply, (char *)rep); - - return Success; -} - -static int -SWriteQueryPortAttributesReply( - ClientPtr client, - xvQueryPortAttributesReply *rep -){ - char n; - - swaps(&rep->sequenceNumber, n); - swapl(&rep->length, n); - swapl(&rep->num_attributes, n); - swapl(&rep->text_size, n); - - (void)WriteToClient(client, sz_xvQueryPortAttributesReply, (char *)rep); - - return Success; -} - -static int -SWriteQueryImageAttributesReply( - ClientPtr client, - xvQueryImageAttributesReply *rep -){ - char n; - - swaps(&rep->sequenceNumber, n); - swapl(&rep->length, n); - swapl(&rep->num_planes, n); - swapl(&rep->data_size, n); - swaps(&rep->width, n); - swaps(&rep->height, n); - - (void)WriteToClient(client, sz_xvQueryImageAttributesReply, (char *)rep); - - return Success; -} - -static int -SWriteListImageFormatsReply( - ClientPtr client, - xvListImageFormatsReply *rep -){ - char n; - - swaps(&rep->sequenceNumber, n); - swapl(&rep->length, n); - swapl(&rep->num_formats, n); - - (void)WriteToClient(client, sz_xvListImageFormatsReply, (char *)rep); - - return Success; -} - -#define _WriteQueryAdaptorsReply(_c,_d) \ - if ((_c)->swapped) SWriteQueryAdaptorsReply(_c, _d); \ - else WriteToClient(_c, sz_xvQueryAdaptorsReply, (char*)_d) - -#define _WriteQueryExtensionReply(_c,_d) \ - if ((_c)->swapped) SWriteQueryExtensionReply(_c, _d); \ - else WriteToClient(_c, sz_xvQueryExtensionReply, (char*)_d) - -#define _WriteQueryEncodingsReply(_c,_d) \ - if ((_c)->swapped) SWriteQueryEncodingsReply(_c, _d); \ - else WriteToClient(_c, sz_xvQueryEncodingsReply, (char*)_d) - -#define _WriteAdaptorInfo(_c,_d) \ - if ((_c)->swapped) SWriteAdaptorInfo(_c, _d); \ - else WriteToClient(_c, sz_xvAdaptorInfo, (char*)_d) - -#define _WriteAttributeInfo(_c,_d) \ - if ((_c)->swapped) SWriteAttributeInfo(_c, _d); \ - else WriteToClient(_c, sz_xvAttributeInfo, (char*)_d) - -#define _WriteEncodingInfo(_c,_d) \ - if ((_c)->swapped) SWriteEncodingInfo(_c, _d); \ - else WriteToClient(_c, sz_xvEncodingInfo, (char*)_d) - -#define _WriteFormat(_c,_d) \ - if ((_c)->swapped) SWriteFormat(_c, _d); \ - else WriteToClient(_c, sz_xvFormat, (char*)_d) - -#define _WriteGrabPortReply(_c,_d) \ - if ((_c)->swapped) SWriteGrabPortReply(_c, _d); \ - else WriteToClient(_c, sz_xvGrabPortReply, (char*)_d) - -#define _WriteGetPortAttributeReply(_c,_d) \ - if ((_c)->swapped) SWriteGetPortAttributeReply(_c, _d); \ - else WriteToClient(_c, sz_xvGetPortAttributeReply, (char*)_d) - -#define _WriteQueryBestSizeReply(_c,_d) \ - if ((_c)->swapped) SWriteQueryBestSizeReply(_c, _d); \ - else WriteToClient(_c, sz_xvQueryBestSizeReply,(char*) _d) - -#define _WriteQueryPortAttributesReply(_c,_d) \ - if ((_c)->swapped) SWriteQueryPortAttributesReply(_c, _d); \ - else WriteToClient(_c, sz_xvQueryPortAttributesReply,(char*) _d) - -#define _WriteQueryImageAttributesReply(_c,_d) \ - if ((_c)->swapped) SWriteQueryImageAttributesReply(_c, _d); \ - else WriteToClient(_c, sz_xvQueryImageAttributesReply,(char*) _d) - -#define _WriteListImageFormatsReply(_c,_d) \ - if ((_c)->swapped) SWriteListImageFormatsReply(_c, _d); \ - else WriteToClient(_c, sz_xvListImageFormatsReply,(char*) _d) - -#define _WriteImageFormatInfo(_c,_d) \ - if ((_c)->swapped) SWriteImageFormatInfo(_c, _d); \ - else WriteToClient(_c, sz_xvImageFormatInfo, (char*)_d) - -#define _AllocatePort(_i,_p) \ - ((_p)->id != _i) ? (* (_p)->pAdaptor->ddAllocatePort)(_i,_p,&_p) : Success - -static int -ProcXvQueryExtension(ClientPtr client) -{ - xvQueryExtensionReply rep; - /* REQUEST(xvQueryExtensionReq); */ - REQUEST_SIZE_MATCH(xvQueryExtensionReq); - - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.length = 0; - rep.version = XvVersion; - rep.revision = XvRevision; - - _WriteQueryExtensionReply(client, &rep); - - return Success; -} - -static int -ProcXvQueryAdaptors(ClientPtr client) -{ - xvFormat format; - xvAdaptorInfo ainfo; - xvQueryAdaptorsReply rep; - int totalSize, na, nf, rc; - int nameSize; - XvAdaptorPtr pa; - XvFormatPtr pf; - WindowPtr pWin; - ScreenPtr pScreen; - XvScreenPtr pxvs; - - REQUEST(xvQueryAdaptorsReq); - REQUEST_SIZE_MATCH(xvQueryAdaptorsReq); - - rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); - if (rc != Success) - return rc; - - pScreen = pWin->drawable.pScreen; - pxvs = (XvScreenPtr)dixLookupPrivate(&pScreen->devPrivates, - XvGetScreenKey()); - if (!pxvs) - { - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.num_adaptors = 0; - rep.length = 0; - - _WriteQueryAdaptorsReply(client, &rep); - - return Success; - } - - (* pxvs->ddQueryAdaptors)(pScreen, &pxvs->pAdaptors, &pxvs->nAdaptors); - - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.num_adaptors = pxvs->nAdaptors; - - /* CALCULATE THE TOTAL SIZE OF THE REPLY IN BYTES */ - - totalSize = pxvs->nAdaptors * sz_xvAdaptorInfo; - - /* FOR EACH ADPATOR ADD UP THE BYTES FOR ENCODINGS AND FORMATS */ - - na = pxvs->nAdaptors; - pa = pxvs->pAdaptors; - while (na--) - { - totalSize += pad_to_int32(strlen(pa->name)); - totalSize += pa->nFormats * sz_xvFormat; - pa++; - } - - rep.length = bytes_to_int32(totalSize); - - _WriteQueryAdaptorsReply(client, &rep); - - na = pxvs->nAdaptors; - pa = pxvs->pAdaptors; - while (na--) - { - - ainfo.base_id = pa->base_id; - ainfo.num_ports = pa->nPorts; - ainfo.type = pa->type; - ainfo.name_size = nameSize = strlen(pa->name); - ainfo.num_formats = pa->nFormats; - - _WriteAdaptorInfo(client, &ainfo); - - WriteToClient(client, nameSize, pa->name); - - nf = pa->nFormats; - pf = pa->pFormats; - while (nf--) - { - format.depth = pf->depth; - format.visual = pf->visual; - _WriteFormat(client, &format); - pf++; - } - - pa++; - - } - - return (client->noClientException); -} - -static int -ProcXvQueryEncodings(ClientPtr client) -{ - xvEncodingInfo einfo; - xvQueryEncodingsReply rep; - int totalSize; - int nameSize; - XvPortPtr pPort; - int ne; - XvEncodingPtr pe; - int status; - - REQUEST(xvQueryEncodingsReq); - REQUEST_SIZE_MATCH(xvQueryEncodingsReq); - - VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess); - - if ((status = _AllocatePort(stuff->port, pPort)) != Success) - { - client->errorValue = stuff->port; - return (status); - } - - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.num_encodings = pPort->pAdaptor->nEncodings; - - /* FOR EACH ENCODING ADD UP THE BYTES FOR ENCODING NAMES */ - - ne = pPort->pAdaptor->nEncodings; - pe = pPort->pAdaptor->pEncodings; - totalSize = ne * sz_xvEncodingInfo; - while (ne--) - { - totalSize += pad_to_int32(strlen(pe->name)); - pe++; - } - - rep.length = bytes_to_int32(totalSize); - - _WriteQueryEncodingsReply(client, &rep); - - ne = pPort->pAdaptor->nEncodings; - pe = pPort->pAdaptor->pEncodings; - while (ne--) - { - einfo.encoding = pe->id; - einfo.name_size = nameSize = strlen(pe->name); - einfo.width = pe->width; - einfo.height = pe->height; - einfo.rate.numerator = pe->rate.numerator; - einfo.rate.denominator = pe->rate.denominator; - _WriteEncodingInfo(client, &einfo); - WriteToClient(client, nameSize, pe->name); - pe++; - } - - return (client->noClientException); -} - -static int -ProcXvPutVideo(ClientPtr client) -{ - DrawablePtr pDraw; - XvPortPtr pPort; - GCPtr pGC; - int status; - - REQUEST(xvPutVideoReq); - REQUEST_SIZE_MATCH(xvPutVideoReq); - - VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); - VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess); - - if ((status = _AllocatePort(stuff->port, pPort)) != Success) - { - client->errorValue = stuff->port; - return (status); - } - - if (!(pPort->pAdaptor->type & XvInputMask) || - !(pPort->pAdaptor->type & XvVideoMask)) - { - client->errorValue = stuff->port; - return (BadMatch); - } - - status = XvdiMatchPort(pPort, pDraw); - if (status != Success) - { - return status; - } - - return XvdiPutVideo(client, pDraw, pPort, pGC, stuff->vid_x, stuff->vid_y, - stuff->vid_w, stuff->vid_h, stuff->drw_x, stuff->drw_y, - stuff->drw_w, stuff->drw_h); -} - -static int -ProcXvPutStill(ClientPtr client) -{ - DrawablePtr pDraw; - XvPortPtr pPort; - GCPtr pGC; - int status; - - REQUEST(xvPutStillReq); - REQUEST_SIZE_MATCH(xvPutStillReq); - - VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); - VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess); - - if ((status = _AllocatePort(stuff->port, pPort)) != Success) - { - client->errorValue = stuff->port; - return (status); - } - - if (!(pPort->pAdaptor->type & XvInputMask) || - !(pPort->pAdaptor->type & XvStillMask)) - { - client->errorValue = stuff->port; - return (BadMatch); - } - - status = XvdiMatchPort(pPort, pDraw); - if (status != Success) - { - return status; - } - - return XvdiPutStill(client, pDraw, pPort, pGC, stuff->vid_x, stuff->vid_y, - stuff->vid_w, stuff->vid_h, stuff->drw_x, stuff->drw_y, - stuff->drw_w, stuff->drw_h); -} - -static int -ProcXvGetVideo(ClientPtr client) -{ - DrawablePtr pDraw; - XvPortPtr pPort; - GCPtr pGC; - int status; - - REQUEST(xvGetVideoReq); - REQUEST_SIZE_MATCH(xvGetVideoReq); - - VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixReadAccess); - VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess); - - if ((status = _AllocatePort(stuff->port, pPort)) != Success) - { - client->errorValue = stuff->port; - return (status); - } - - if (!(pPort->pAdaptor->type & XvOutputMask) || - !(pPort->pAdaptor->type & XvVideoMask)) - { - client->errorValue = stuff->port; - return (BadMatch); - } - - status = XvdiMatchPort(pPort, pDraw); - if (status != Success) - { - return status; - } - - return XvdiGetVideo(client, pDraw, pPort, pGC, stuff->vid_x, stuff->vid_y, - stuff->vid_w, stuff->vid_h, stuff->drw_x, stuff->drw_y, - stuff->drw_w, stuff->drw_h); -} - -static int -ProcXvGetStill(ClientPtr client) -{ - DrawablePtr pDraw; - XvPortPtr pPort; - GCPtr pGC; - int status; - - REQUEST(xvGetStillReq); - REQUEST_SIZE_MATCH(xvGetStillReq); - - VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixReadAccess); - VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess); - - if ((status = _AllocatePort(stuff->port, pPort)) != Success) - { - client->errorValue = stuff->port; - return (status); - } - - if (!(pPort->pAdaptor->type & XvOutputMask) || - !(pPort->pAdaptor->type & XvStillMask)) - { - client->errorValue = stuff->port; - return (BadMatch); - } - - status = XvdiMatchPort(pPort, pDraw); - if (status != Success) - { - return status; - } - - return XvdiGetStill(client, pDraw, pPort, pGC, stuff->vid_x, stuff->vid_y, - stuff->vid_w, stuff->vid_h, stuff->drw_x, stuff->drw_y, - stuff->drw_w, stuff->drw_h); -} - -static int -ProcXvSelectVideoNotify(ClientPtr client) -{ - DrawablePtr pDraw; - int rc; - REQUEST(xvSelectVideoNotifyReq); - REQUEST_SIZE_MATCH(xvSelectVideoNotifyReq); - - rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0, DixReceiveAccess); - if (rc != Success) - return rc; - - return XvdiSelectVideoNotify(client, pDraw, stuff->onoff); -} - -static int -ProcXvSelectPortNotify(ClientPtr client) -{ - int status; - XvPortPtr pPort; - REQUEST(xvSelectPortNotifyReq); - REQUEST_SIZE_MATCH(xvSelectPortNotifyReq); - - VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess); - - if ((status = _AllocatePort(stuff->port, pPort)) != Success) - { - client->errorValue = stuff->port; - return (status); - } - - return XvdiSelectPortNotify(client, pPort, stuff->onoff); -} - -static int -ProcXvGrabPort(ClientPtr client) -{ - int result, status; - XvPortPtr pPort; - xvGrabPortReply rep; - REQUEST(xvGrabPortReq); - REQUEST_SIZE_MATCH(xvGrabPortReq); - - VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess); - - if ((status = _AllocatePort(stuff->port, pPort)) != Success) - { - client->errorValue = stuff->port; - return (status); - } - - status = XvdiGrabPort(client, pPort, stuff->time, &result); - - if (status != Success) - { - return status; - } - - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.length = 0; - rep.result = result; - - _WriteGrabPortReply(client, &rep); - - return Success; -} - -static int -ProcXvUngrabPort(ClientPtr client) -{ - int status; - XvPortPtr pPort; - REQUEST(xvGrabPortReq); - REQUEST_SIZE_MATCH(xvGrabPortReq); - - VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess); - - if ((status = _AllocatePort(stuff->port, pPort)) != Success) - { - client->errorValue = stuff->port; - return (status); - } - - return XvdiUngrabPort(client, pPort, stuff->time); -} - -static int -ProcXvStopVideo(ClientPtr client) -{ - int status, rc; - DrawablePtr pDraw; - XvPortPtr pPort; - REQUEST(xvStopVideoReq); - REQUEST_SIZE_MATCH(xvStopVideoReq); - - VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess); - - if ((status = _AllocatePort(stuff->port, pPort)) != Success) - { - client->errorValue = stuff->port; - return (status); - } - - rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0, DixWriteAccess); - if (rc != Success) - return rc; - - return XvdiStopVideo(client, pPort, pDraw); -} - -static int -ProcXvSetPortAttribute(ClientPtr client) -{ - int status; - XvPortPtr pPort; - REQUEST(xvSetPortAttributeReq); - REQUEST_SIZE_MATCH(xvSetPortAttributeReq); - - VALIDATE_XV_PORT(stuff->port, pPort, DixSetAttrAccess); - - if ((status = _AllocatePort(stuff->port, pPort)) != Success) - { - client->errorValue = stuff->port; - return (status); - } - - if (!ValidAtom(stuff->attribute)) - { - client->errorValue = stuff->attribute; - return(BadAtom); - } - - status = XvdiSetPortAttribute(client, pPort, stuff->attribute, stuff->value); - - if (status == BadMatch) - client->errorValue = stuff->attribute; - else - client->errorValue = stuff->value; - - return status; -} - -static int -ProcXvGetPortAttribute(ClientPtr client) -{ - INT32 value; - int status; - XvPortPtr pPort; - xvGetPortAttributeReply rep; - REQUEST(xvGetPortAttributeReq); - REQUEST_SIZE_MATCH(xvGetPortAttributeReq); - - VALIDATE_XV_PORT(stuff->port, pPort, DixGetAttrAccess); - - if ((status = _AllocatePort(stuff->port, pPort)) != Success) - { - client->errorValue = stuff->port; - return (status); - } - - if (!ValidAtom(stuff->attribute)) - { - client->errorValue = stuff->attribute; - return(BadAtom); - } - - status = XvdiGetPortAttribute(client, pPort, stuff->attribute, &value); - if (status != Success) - { - client->errorValue = stuff->attribute; - return status; - } - - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.length = 0; - rep.value = value; - - _WriteGetPortAttributeReply(client, &rep); - - return Success; -} - -static int -ProcXvQueryBestSize(ClientPtr client) -{ - int status; - unsigned int actual_width, actual_height; - XvPortPtr pPort; - xvQueryBestSizeReply rep; - REQUEST(xvQueryBestSizeReq); - REQUEST_SIZE_MATCH(xvQueryBestSizeReq); - - VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess); - - if ((status = _AllocatePort(stuff->port, pPort)) != Success) - { - client->errorValue = stuff->port; - return (status); - } - - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.length = 0; - - (* pPort->pAdaptor->ddQueryBestSize)(client, pPort, stuff->motion, - stuff->vid_w, stuff->vid_h, - stuff->drw_w, stuff->drw_h, - &actual_width, &actual_height); - - rep.actual_width = actual_width; - rep.actual_height = actual_height; - - _WriteQueryBestSizeReply(client, &rep); - - return Success; -} - - -static int -ProcXvQueryPortAttributes(ClientPtr client) -{ - int status, size, i; - XvPortPtr pPort; - XvAttributePtr pAtt; - xvQueryPortAttributesReply rep; - xvAttributeInfo Info; - REQUEST(xvQueryPortAttributesReq); - REQUEST_SIZE_MATCH(xvQueryPortAttributesReq); - - VALIDATE_XV_PORT(stuff->port, pPort, DixGetAttrAccess); - - if ((status = _AllocatePort(stuff->port, pPort)) != Success) - { - client->errorValue = stuff->port; - return (status); - } - - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.num_attributes = pPort->pAdaptor->nAttributes; - rep.text_size = 0; - - for(i = 0, pAtt = pPort->pAdaptor->pAttributes; - i < pPort->pAdaptor->nAttributes; i++, pAtt++) - { - rep.text_size += pad_to_int32(strlen(pAtt->name) + 1); - } - - rep.length = (pPort->pAdaptor->nAttributes * sz_xvAttributeInfo) - + rep.text_size; - rep.length >>= 2; - - _WriteQueryPortAttributesReply(client, &rep); - - for(i = 0, pAtt = pPort->pAdaptor->pAttributes; - i < pPort->pAdaptor->nAttributes; i++, pAtt++) - { - size = strlen(pAtt->name) + 1; /* pass the NULL */ - Info.flags = pAtt->flags; - Info.min = pAtt->min_value; - Info.max = pAtt->max_value; - Info.size = pad_to_int32(size); - - _WriteAttributeInfo(client, &Info); - - WriteToClient(client, size, pAtt->name); - } - - return Success; -} - -static int -ProcXvPutImage(ClientPtr client) -{ - DrawablePtr pDraw; - XvPortPtr pPort; - XvImagePtr pImage = NULL; - GCPtr pGC; - int status, i, size; - CARD16 width, height; - - REQUEST(xvPutImageReq); - REQUEST_AT_LEAST_SIZE(xvPutImageReq); - - VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); - VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess); - - if ((status = _AllocatePort(stuff->port, pPort)) != Success) - { - client->errorValue = stuff->port; - return (status); - } - - if (!(pPort->pAdaptor->type & XvImageMask) || - !(pPort->pAdaptor->type & XvInputMask)) - { - client->errorValue = stuff->port; - return (BadMatch); - } - - status = XvdiMatchPort(pPort, pDraw); - if (status != Success) - { - return status; - } - - for(i = 0; i < pPort->pAdaptor->nImages; i++) { - if(pPort->pAdaptor->pImages[i].id == stuff->id) { - pImage = &(pPort->pAdaptor->pImages[i]); - break; - } - } - - if(!pImage) - return BadMatch; - - width = stuff->width; - height = stuff->height; - size = (*pPort->pAdaptor->ddQueryImageAttributes)(client, - pPort, pImage, &width, &height, NULL, NULL); - size += sizeof(xvPutImageReq); - size = bytes_to_int32(size); - - if((width < stuff->width) || (height < stuff->height)) - return BadValue; - - if(client->req_len < size) - return BadLength; - - return XvdiPutImage(client, pDraw, pPort, pGC, stuff->src_x, stuff->src_y, - stuff->src_w, stuff->src_h, stuff->drw_x, stuff->drw_y, - stuff->drw_w, stuff->drw_h, pImage, - (unsigned char*)(&stuff[1]), FALSE, - stuff->width, stuff->height); -} - -#ifdef MITSHM -/* redefined here since it's not in any header file */ -typedef struct _ShmDesc { - struct _ShmDesc *next; - int shmid; - int refcnt; - char *addr; - Bool writable; - unsigned long size; -} ShmDescRec, *ShmDescPtr; - -extern RESTYPE ShmSegType; -extern int BadShmSegCode; -extern int ShmCompletionCode; - -static int -ProcXvShmPutImage(ClientPtr client) -{ - ShmDescPtr shmdesc; - DrawablePtr pDraw; - XvPortPtr pPort; - XvImagePtr pImage = NULL; - GCPtr pGC; - int status, size_needed, i; - CARD16 width, height; - - REQUEST(xvShmPutImageReq); - REQUEST_SIZE_MATCH(xvShmPutImageReq); - - VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); - VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess); - - if ((status = _AllocatePort(stuff->port, pPort)) != Success) - { - client->errorValue = stuff->port; - return (status); - } - - if (!(pPort->pAdaptor->type & XvImageMask) || - !(pPort->pAdaptor->type & XvInputMask)) - { - client->errorValue = stuff->port; - return (BadMatch); - } - - status = XvdiMatchPort(pPort, pDraw); - if (status != Success) - { - return status; - } - - for(i = 0; i < pPort->pAdaptor->nImages; i++) { - if(pPort->pAdaptor->pImages[i].id == stuff->id) { - pImage = &(pPort->pAdaptor->pImages[i]); - break; - } - } - - if(!pImage) - return BadMatch; - - status = dixLookupResourceByType((pointer *)&shmdesc, stuff->shmseg, - ShmSegType, serverClient, DixReadAccess); - if (status != Success) - return (status == BadValue) ? BadShmSegCode : status; - - width = stuff->width; - height = stuff->height; - size_needed = (*pPort->pAdaptor->ddQueryImageAttributes)(client, - pPort, pImage, &width, &height, NULL, NULL); - if((size_needed + stuff->offset) > shmdesc->size) - return BadAccess; - - if((width < stuff->width) || (height < stuff->height)) - return BadValue; - - status = XvdiPutImage(client, pDraw, pPort, pGC, stuff->src_x, stuff->src_y, - stuff->src_w, stuff->src_h, stuff->drw_x, stuff->drw_y, - stuff->drw_w, stuff->drw_h, pImage, - (unsigned char *)shmdesc->addr + stuff->offset, - stuff->send_event, stuff->width, stuff->height); - - if((status == Success) && stuff->send_event) { - xShmCompletionEvent ev; - - ev.type = ShmCompletionCode; - ev.drawable = stuff->drawable; - ev.sequenceNumber = client->sequence; - ev.minorEvent = xv_ShmPutImage; - ev.majorEvent = XvReqCode; - ev.shmseg = stuff->shmseg; - ev.offset = stuff->offset; - WriteEventsToClient(client, 1, (xEvent *) &ev); - } - - return status; -} -#else /* !MITSHM */ -static int -ProcXvShmPutImage(ClientPtr client) -{ - SendErrorToClient(client, XvReqCode, xv_ShmPutImage, 0, BadImplementation); - return(BadImplementation); -} -#endif - -#ifdef XvMCExtension -#include "xvmcext.h" -#endif - -static int -ProcXvQueryImageAttributes(ClientPtr client) -{ - xvQueryImageAttributesReply rep; - int size, num_planes, i; - CARD16 width, height; - XvImagePtr pImage = NULL; - XvPortPtr pPort; - int *offsets; - int *pitches; - int planeLength; - REQUEST(xvQueryImageAttributesReq); - - REQUEST_SIZE_MATCH(xvQueryImageAttributesReq); - - VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess); - - for(i = 0; i < pPort->pAdaptor->nImages; i++) { - if(pPort->pAdaptor->pImages[i].id == stuff->id) { - pImage = &(pPort->pAdaptor->pImages[i]); - break; - } - } - -#ifdef XvMCExtension - if(!pImage) - pImage = XvMCFindXvImage(pPort, stuff->id); -#endif - - if(!pImage) - return BadMatch; - - num_planes = pImage->num_planes; - - if(!(offsets = xalloc(num_planes << 3))) - return BadAlloc; - pitches = offsets + num_planes; - - width = stuff->width; - height = stuff->height; - - size = (*pPort->pAdaptor->ddQueryImageAttributes)(client, pPort, pImage, - &width, &height, offsets, pitches); - - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.length = planeLength = num_planes << 1; - rep.num_planes = num_planes; - rep.width = width; - rep.height = height; - rep.data_size = size; - - _WriteQueryImageAttributesReply(client, &rep); - if(client->swapped) - SwapLongs((CARD32*)offsets, planeLength); - WriteToClient(client, planeLength << 2, (char*)offsets); - - xfree(offsets); - - return Success; -} - -static int -ProcXvListImageFormats(ClientPtr client) -{ - XvPortPtr pPort; - XvImagePtr pImage; - int i; - xvListImageFormatsReply rep; - xvImageFormatInfo info; - REQUEST(xvListImageFormatsReq); - - REQUEST_SIZE_MATCH(xvListImageFormatsReq); - - VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess); - - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.num_formats = pPort->pAdaptor->nImages; - rep.length = bytes_to_int32(pPort->pAdaptor->nImages * sz_xvImageFormatInfo); - - _WriteListImageFormatsReply(client, &rep); - - pImage = pPort->pAdaptor->pImages; - - for(i = 0; i < pPort->pAdaptor->nImages; i++, pImage++) { - info.id = pImage->id; - info.type = pImage->type; - info.byte_order = pImage->byte_order; - memcpy(&info.guid, pImage->guid, 16); - info.bpp = pImage->bits_per_pixel; - info.num_planes = pImage->num_planes; - info.depth = pImage->depth; - info.red_mask = pImage->red_mask; - info.green_mask = pImage->green_mask; - info.blue_mask = pImage->blue_mask; - info.format = pImage->format; - info.y_sample_bits = pImage->y_sample_bits; - info.u_sample_bits = pImage->u_sample_bits; - info.v_sample_bits = pImage->v_sample_bits; - info.horz_y_period = pImage->horz_y_period; - info.horz_u_period = pImage->horz_u_period; - info.horz_v_period = pImage->horz_v_period; - info.vert_y_period = pImage->vert_y_period; - info.vert_u_period = pImage->vert_u_period; - info.vert_v_period = pImage->vert_v_period; - memcpy(&info.comp_order, pImage->component_order, 32); - info.scanline_order = pImage->scanline_order; - _WriteImageFormatInfo(client, &info); - } - - return Success; -} - -static int (*XvProcVector[xvNumRequests])(ClientPtr) = { - ProcXvQueryExtension, - ProcXvQueryAdaptors, - ProcXvQueryEncodings, - ProcXvGrabPort, - ProcXvUngrabPort, - ProcXvPutVideo, - ProcXvPutStill, - ProcXvGetVideo, - ProcXvGetStill, - ProcXvStopVideo, - ProcXvSelectVideoNotify, - ProcXvSelectPortNotify, - ProcXvQueryBestSize, - ProcXvSetPortAttribute, - ProcXvGetPortAttribute, - ProcXvQueryPortAttributes, - ProcXvListImageFormats, - ProcXvQueryImageAttributes, - ProcXvPutImage, - ProcXvShmPutImage, -}; - -int -ProcXvDispatch(ClientPtr client) -{ - REQUEST(xReq); - - UpdateCurrentTime(); - - if (stuff->data > xvNumRequests) { - SendErrorToClient(client, XvReqCode, stuff->data, 0, BadRequest); - return(BadRequest); - } - - return XvProcVector[stuff->data](client); -} - -/* Swapped Procs */ - -static int -SProcXvQueryExtension(ClientPtr client) -{ - char n; - REQUEST(xvQueryExtensionReq); - swaps(&stuff->length, n); - return XvProcVector[xv_QueryExtension](client); -} - -static int -SProcXvQueryAdaptors(ClientPtr client) -{ - char n; - REQUEST(xvQueryAdaptorsReq); - swaps(&stuff->length, n); - swapl(&stuff->window, n); - return XvProcVector[xv_QueryAdaptors](client); -} - -static int -SProcXvQueryEncodings(ClientPtr client) -{ - char n; - REQUEST(xvQueryEncodingsReq); - swaps(&stuff->length, n); - swapl(&stuff->port, n); - return XvProcVector[xv_QueryEncodings](client); -} - -static int -SProcXvGrabPort(ClientPtr client) -{ - char n; - REQUEST(xvGrabPortReq); - swaps(&stuff->length, n); - swapl(&stuff->port, n); - swapl(&stuff->time, n); - return XvProcVector[xv_GrabPort](client); -} - -static int -SProcXvUngrabPort(ClientPtr client) -{ - char n; - REQUEST(xvUngrabPortReq); - swaps(&stuff->length, n); - swapl(&stuff->port, n); - swapl(&stuff->time, n); - return XvProcVector[xv_UngrabPort](client); -} - -static int -SProcXvPutVideo(ClientPtr client) -{ - char n; - REQUEST(xvPutVideoReq); - swaps(&stuff->length, n); - swapl(&stuff->port, n); - swapl(&stuff->drawable, n); - swapl(&stuff->gc, n); - swaps(&stuff->vid_x, n); - swaps(&stuff->vid_y, n); - swaps(&stuff->vid_w, n); - swaps(&stuff->vid_h, n); - swaps(&stuff->drw_x, n); - swaps(&stuff->drw_y, n); - swaps(&stuff->drw_w, n); - swaps(&stuff->drw_h, n); - return XvProcVector[xv_PutVideo](client); -} - -static int -SProcXvPutStill(ClientPtr client) -{ - char n; - REQUEST(xvPutStillReq); - swaps(&stuff->length, n); - swapl(&stuff->port, n); - swapl(&stuff->drawable, n); - swapl(&stuff->gc, n); - swaps(&stuff->vid_x, n); - swaps(&stuff->vid_y, n); - swaps(&stuff->vid_w, n); - swaps(&stuff->vid_h, n); - swaps(&stuff->drw_x, n); - swaps(&stuff->drw_y, n); - swaps(&stuff->drw_w, n); - swaps(&stuff->drw_h, n); - return XvProcVector[xv_PutStill](client); -} - -static int -SProcXvGetVideo(ClientPtr client) -{ - char n; - REQUEST(xvGetVideoReq); - swaps(&stuff->length, n); - swapl(&stuff->port, n); - swapl(&stuff->drawable, n); - swapl(&stuff->gc, n); - swaps(&stuff->vid_x, n); - swaps(&stuff->vid_y, n); - swaps(&stuff->vid_w, n); - swaps(&stuff->vid_h, n); - swaps(&stuff->drw_x, n); - swaps(&stuff->drw_y, n); - swaps(&stuff->drw_w, n); - swaps(&stuff->drw_h, n); - return XvProcVector[xv_GetVideo](client); -} - -static int -SProcXvGetStill(ClientPtr client) -{ - char n; - REQUEST(xvGetStillReq); - swaps(&stuff->length, n); - swapl(&stuff->port, n); - swapl(&stuff->drawable, n); - swapl(&stuff->gc, n); - swaps(&stuff->vid_x, n); - swaps(&stuff->vid_y, n); - swaps(&stuff->vid_w, n); - swaps(&stuff->vid_h, n); - swaps(&stuff->drw_x, n); - swaps(&stuff->drw_y, n); - swaps(&stuff->drw_w, n); - swaps(&stuff->drw_h, n); - return XvProcVector[xv_GetStill](client); -} - -static int -SProcXvPutImage(ClientPtr client) -{ - char n; - REQUEST(xvPutImageReq); - swaps(&stuff->length, n); - swapl(&stuff->port, n); - swapl(&stuff->drawable, n); - swapl(&stuff->gc, n); - swapl(&stuff->id, n); - swaps(&stuff->src_x, n); - swaps(&stuff->src_y, n); - swaps(&stuff->src_w, n); - swaps(&stuff->src_h, n); - swaps(&stuff->drw_x, n); - swaps(&stuff->drw_y, n); - swaps(&stuff->drw_w, n); - swaps(&stuff->drw_h, n); - swaps(&stuff->width, n); - swaps(&stuff->height, n); - return XvProcVector[xv_PutImage](client); -} - -#ifdef MITSHM -static int -SProcXvShmPutImage(ClientPtr client) -{ - char n; - REQUEST(xvShmPutImageReq); - swaps(&stuff->length, n); - swapl(&stuff->port, n); - swapl(&stuff->drawable, n); - swapl(&stuff->gc, n); - swapl(&stuff->shmseg, n); - swapl(&stuff->id, n); - swapl(&stuff->offset, n); - swaps(&stuff->src_x, n); - swaps(&stuff->src_y, n); - swaps(&stuff->src_w, n); - swaps(&stuff->src_h, n); - swaps(&stuff->drw_x, n); - swaps(&stuff->drw_y, n); - swaps(&stuff->drw_w, n); - swaps(&stuff->drw_h, n); - swaps(&stuff->width, n); - swaps(&stuff->height, n); - return XvProcVector[xv_ShmPutImage](client); -} -#else /* MITSHM */ -#define SProcXvShmPutImage ProcXvShmPutImage -#endif - -static int -SProcXvSelectVideoNotify(ClientPtr client) -{ - char n; - REQUEST(xvSelectVideoNotifyReq); - swaps(&stuff->length, n); - swapl(&stuff->drawable, n); - return XvProcVector[xv_SelectVideoNotify](client); -} - -static int -SProcXvSelectPortNotify(ClientPtr client) -{ - char n; - REQUEST(xvSelectPortNotifyReq); - swaps(&stuff->length, n); - swapl(&stuff->port, n); - return XvProcVector[xv_SelectPortNotify](client); -} - -static int -SProcXvStopVideo(ClientPtr client) -{ - char n; - REQUEST(xvStopVideoReq); - swaps(&stuff->length, n); - swapl(&stuff->port, n); - swapl(&stuff->drawable, n); - return XvProcVector[xv_StopVideo](client); -} - -static int -SProcXvSetPortAttribute(ClientPtr client) -{ - char n; - REQUEST(xvSetPortAttributeReq); - swaps(&stuff->length, n); - swapl(&stuff->port, n); - swapl(&stuff->attribute, n); - swapl(&stuff->value, n); - return XvProcVector[xv_SetPortAttribute](client); -} - -static int -SProcXvGetPortAttribute(ClientPtr client) -{ - char n; - REQUEST(xvGetPortAttributeReq); - swaps(&stuff->length, n); - swapl(&stuff->port, n); - swapl(&stuff->attribute, n); - return XvProcVector[xv_GetPortAttribute](client); -} - -static int -SProcXvQueryBestSize(ClientPtr client) -{ - char n; - REQUEST(xvQueryBestSizeReq); - swaps(&stuff->length, n); - swapl(&stuff->port, n); - swaps(&stuff->vid_w, n); - swaps(&stuff->vid_h, n); - swaps(&stuff->drw_w, n); - swaps(&stuff->drw_h, n); - return XvProcVector[xv_QueryBestSize](client); -} - -static int -SProcXvQueryPortAttributes(ClientPtr client) -{ - char n; - REQUEST(xvQueryPortAttributesReq); - swaps(&stuff->length, n); - swapl(&stuff->port, n); - return XvProcVector[xv_QueryPortAttributes](client); -} - -static int -SProcXvQueryImageAttributes(ClientPtr client) -{ - char n; - REQUEST(xvQueryImageAttributesReq); - swaps(&stuff->length, n); - swapl(&stuff->port, n); - swapl(&stuff->id, n); - swaps(&stuff->width, n); - swaps(&stuff->height, n); - return XvProcVector[xv_QueryImageAttributes](client); -} - -static int -SProcXvListImageFormats(ClientPtr client) -{ - char n; - REQUEST(xvListImageFormatsReq); - swaps(&stuff->length, n); - swapl(&stuff->port, n); - return XvProcVector[xv_ListImageFormats](client); -} - -static int (*SXvProcVector[xvNumRequests])(ClientPtr) = { - SProcXvQueryExtension, - SProcXvQueryAdaptors, - SProcXvQueryEncodings, - SProcXvGrabPort, - SProcXvUngrabPort, - SProcXvPutVideo, - SProcXvPutStill, - SProcXvGetVideo, - SProcXvGetStill, - SProcXvStopVideo, - SProcXvSelectVideoNotify, - SProcXvSelectPortNotify, - SProcXvQueryBestSize, - SProcXvSetPortAttribute, - SProcXvGetPortAttribute, - SProcXvQueryPortAttributes, - SProcXvListImageFormats, - SProcXvQueryImageAttributes, - SProcXvPutImage, - SProcXvShmPutImage, -}; - -int -SProcXvDispatch(ClientPtr client) -{ - REQUEST(xReq); - - UpdateCurrentTime(); - - if (stuff->data > xvNumRequests) { - SendErrorToClient(client, XvReqCode, stuff->data, 0, BadRequest); - return(BadRequest); - } - - return SXvProcVector[stuff->data](client); -} - -#ifdef PANORAMIX -static int -XineramaXvStopVideo(ClientPtr client) -{ - int result, i; - PanoramiXRes *draw, *port; - REQUEST(xvStopVideoReq); - REQUEST_SIZE_MATCH(xvStopVideoReq); - - result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable, - XRC_DRAWABLE, client, DixWriteAccess); - if (result != Success) - return (result == BadValue) ? BadDrawable : result; - - result = dixLookupResourceByType((pointer *)&port, stuff->port, - XvXRTPort, client, DixReadAccess); - if (result != Success) - return (result == BadValue) ? _XvBadPort : result; - - FOR_NSCREENS_BACKWARD(i) { - if(port->info[i].id) { - stuff->drawable = draw->info[i].id; - stuff->port = port->info[i].id; - result = ProcXvStopVideo(client); - } - } - - return result; -} - -static int -XineramaXvSetPortAttribute(ClientPtr client) -{ - REQUEST(xvSetPortAttributeReq); - PanoramiXRes *port; - int result, i; - - REQUEST_SIZE_MATCH(xvSetPortAttributeReq); - - result = dixLookupResourceByType((pointer *)&port, stuff->port, - XvXRTPort, client, DixReadAccess); - if (result != Success) - return (result == BadValue) ? _XvBadPort : result; - - FOR_NSCREENS_BACKWARD(i) { - if(port->info[i].id) { - stuff->port = port->info[i].id; - result = ProcXvSetPortAttribute(client); - } - } - return result; -} - -#ifdef MITSHM -static int -XineramaXvShmPutImage(ClientPtr client) -{ - REQUEST(xvShmPutImageReq); - PanoramiXRes *draw, *gc, *port; - Bool send_event = stuff->send_event; - Bool isRoot; - int result, i, x, y; - - REQUEST_SIZE_MATCH(xvShmPutImageReq); - - result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable, - XRC_DRAWABLE, client, DixWriteAccess); - if (result != Success) - return (result == BadValue) ? BadDrawable : result; - - result = dixLookupResourceByType((pointer *)&gc, stuff->gc, - XRT_GC, client, DixReadAccess); - if (result != Success) - return (result == BadValue) ? BadGC : result; - - result = dixLookupResourceByType((pointer *)&port, stuff->port, - XvXRTPort, client, DixReadAccess); - if (result != Success) - return (result == BadValue) ? _XvBadPort : result; - - isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; - - x = stuff->drw_x; - y = stuff->drw_y; - - FOR_NSCREENS_BACKWARD(i) { - if(port->info[i].id) { - stuff->drawable = draw->info[i].id; - stuff->port = port->info[i].id; - stuff->gc = gc->info[i].id; - stuff->drw_x = x; - stuff->drw_y = y; - if(isRoot) { - stuff->drw_x -= panoramiXdataPtr[i].x; - stuff->drw_y -= panoramiXdataPtr[i].y; - } - stuff->send_event = (send_event && !i) ? 1 : 0; - - result = ProcXvShmPutImage(client); - } - } - return result; -} -#else -#define XineramaXvShmPutImage ProcXvShmPutImage -#endif - -static int -XineramaXvPutImage(ClientPtr client) -{ - REQUEST(xvPutImageReq); - PanoramiXRes *draw, *gc, *port; - Bool isRoot; - int result, i, x, y; - - REQUEST_AT_LEAST_SIZE(xvPutImageReq); - - result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable, - XRC_DRAWABLE, client, DixWriteAccess); - if (result != Success) - return (result == BadValue) ? BadDrawable : result; - - result = dixLookupResourceByType((pointer *)&gc, stuff->gc, - XRT_GC, client, DixReadAccess); - if (result != Success) - return (result == BadValue) ? BadGC : result; - - result = dixLookupResourceByType((pointer *)&port, stuff->port, - XvXRTPort, client, DixReadAccess); - if (result != Success) - return (result == BadValue) ? _XvBadPort : result; - - isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; - - x = stuff->drw_x; - y = stuff->drw_y; - - FOR_NSCREENS_BACKWARD(i) { - if(port->info[i].id) { - stuff->drawable = draw->info[i].id; - stuff->port = port->info[i].id; - stuff->gc = gc->info[i].id; - stuff->drw_x = x; - stuff->drw_y = y; - if(isRoot) { - stuff->drw_x -= panoramiXdataPtr[i].x; - stuff->drw_y -= panoramiXdataPtr[i].y; - } - - result = ProcXvPutImage(client); - } - } - return result; -} - -static int -XineramaXvPutVideo(ClientPtr client) -{ - REQUEST(xvPutImageReq); - PanoramiXRes *draw, *gc, *port; - Bool isRoot; - int result, i, x, y; - - REQUEST_AT_LEAST_SIZE(xvPutVideoReq); - - result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable, - XRC_DRAWABLE, client, DixWriteAccess); - if (result != Success) - return (result == BadValue) ? BadDrawable : result; - - result = dixLookupResourceByType((pointer *)&gc, stuff->gc, - XRT_GC, client, DixReadAccess); - if (result != Success) - return (result == BadValue) ? BadGC : result; - - result = dixLookupResourceByType((pointer *)&port, stuff->port, - XvXRTPort, client, DixReadAccess); - if (result != Success) - return (result == BadValue) ? _XvBadPort : result; - - isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; - - x = stuff->drw_x; - y = stuff->drw_y; - - FOR_NSCREENS_BACKWARD(i) { - if(port->info[i].id) { - stuff->drawable = draw->info[i].id; - stuff->port = port->info[i].id; - stuff->gc = gc->info[i].id; - stuff->drw_x = x; - stuff->drw_y = y; - if(isRoot) { - stuff->drw_x -= panoramiXdataPtr[i].x; - stuff->drw_y -= panoramiXdataPtr[i].y; - } - - result = ProcXvPutVideo(client); - } - } - return result; -} - -static int -XineramaXvPutStill(ClientPtr client) -{ - REQUEST(xvPutImageReq); - PanoramiXRes *draw, *gc, *port; - Bool isRoot; - int result, i, x, y; - - REQUEST_AT_LEAST_SIZE(xvPutImageReq); - - result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable, - XRC_DRAWABLE, client, DixWriteAccess); - if (result != Success) - return (result == BadValue) ? BadDrawable : result; - - result = dixLookupResourceByType((pointer *)&gc, stuff->gc, - XRT_GC, client, DixReadAccess); - if (result != Success) - return (result == BadValue) ? BadGC : result; - - result = dixLookupResourceByType((pointer *)&port, stuff->port, - XvXRTPort, client, DixReadAccess); - if (result != Success) - return (result == BadValue) ? _XvBadPort : result; - - isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; - - x = stuff->drw_x; - y = stuff->drw_y; - - FOR_NSCREENS_BACKWARD(i) { - if(port->info[i].id) { - stuff->drawable = draw->info[i].id; - stuff->port = port->info[i].id; - stuff->gc = gc->info[i].id; - stuff->drw_x = x; - stuff->drw_y = y; - if(isRoot) { - stuff->drw_x -= panoramiXdataPtr[i].x; - stuff->drw_y -= panoramiXdataPtr[i].y; - } - - result = ProcXvPutStill(client); - } - } - return result; -} - -static Bool -isImageAdaptor(XvAdaptorPtr pAdapt) -{ - return (pAdapt->type & XvImageMask) && (pAdapt->nImages > 0); -} - -static Bool -hasOverlay(XvAdaptorPtr pAdapt) -{ - int i; - for(i = 0; i < pAdapt->nAttributes; i++) - if(!strcmp(pAdapt->pAttributes[i].name, "XV_COLORKEY")) - return TRUE; - return FALSE; -} - -static XvAdaptorPtr -matchAdaptor(ScreenPtr pScreen, XvAdaptorPtr refAdapt, Bool isOverlay) -{ - int i; - XvScreenPtr xvsp = dixLookupPrivate(&pScreen->devPrivates, XvGetScreenKey()); - /* Do not try to go on if xv is not supported on this screen */ - if(xvsp == NULL) - return NULL; - - /* if the adaptor has the same name it's a perfect match */ - for(i = 0; i < xvsp->nAdaptors; i++) { - XvAdaptorPtr pAdapt = xvsp->pAdaptors + i; - if(!strcmp(refAdapt->name, pAdapt->name)) - return pAdapt; - } - - /* otherwise we only look for XvImage adaptors */ - if(!isImageAdaptor(refAdapt)) - return NULL; - - /* prefer overlay/overlay non-overlay/non-overlay pairing */ - for(i = 0; i < xvsp->nAdaptors; i++) { - XvAdaptorPtr pAdapt = xvsp->pAdaptors + i; - if(isImageAdaptor(pAdapt) && isOverlay == hasOverlay(pAdapt)) - return pAdapt; - } - - /* but we'll take any XvImage pairing if we can get it */ - for(i = 0; i < xvsp->nAdaptors; i++) { - XvAdaptorPtr pAdapt = xvsp->pAdaptors + i; - if(isImageAdaptor(pAdapt)) - return pAdapt; - } - return NULL; -} - -void XineramifyXv(void) -{ - XvScreenPtr xvsp0 = dixLookupPrivate(&screenInfo.screens[0]->devPrivates, XvGetScreenKey()); - XvAdaptorPtr MatchingAdaptors[MAXSCREENS]; - int i, j, k; - - XvXRTPort = CreateNewResourceType(XineramaDeleteResource, "XvXRTPort"); - - if (!xvsp0 || !XvXRTPort) return; - - for(i = 0; i < xvsp0->nAdaptors; i++) { - Bool isOverlay; - XvAdaptorPtr refAdapt = xvsp0->pAdaptors + i; - if(!(refAdapt->type & XvInputMask)) continue; - - MatchingAdaptors[0] = refAdapt; - isOverlay = hasOverlay(refAdapt); - for(j = 1; j < PanoramiXNumScreens; j++) - MatchingAdaptors[j] = matchAdaptor(screenInfo.screens[j], refAdapt, isOverlay); - - /* now create a resource for each port */ - for(j = 0; j < refAdapt->nPorts; j++) { - PanoramiXRes *port = xalloc(sizeof(PanoramiXRes)); - if(!port) - break; - - for(k = 0; k < PanoramiXNumScreens; k++) { - if(MatchingAdaptors[k] && (MatchingAdaptors[k]->nPorts > j)) - port->info[k].id = MatchingAdaptors[k]->base_id + j; - else - port->info[k].id = 0; - } - AddResource(port->info[0].id, XvXRTPort, port); - } - } - - /* munge the dispatch vector */ - XvProcVector[xv_PutVideo] = XineramaXvPutVideo; - XvProcVector[xv_PutStill] = XineramaXvPutStill; - XvProcVector[xv_StopVideo] = XineramaXvStopVideo; - XvProcVector[xv_SetPortAttribute] = XineramaXvSetPortAttribute; - XvProcVector[xv_PutImage] = XineramaXvPutImage; - XvProcVector[xv_ShmPutImage] = XineramaXvShmPutImage; -} -#endif /* PANORAMIX */ - -void -XvResetProcVector(void) -{ -#ifdef PANORAMIX - XvProcVector[xv_PutVideo] = ProcXvPutVideo; - XvProcVector[xv_PutStill] = ProcXvPutStill; - XvProcVector[xv_StopVideo] = ProcXvStopVideo; - XvProcVector[xv_SetPortAttribute] = ProcXvSetPortAttribute; - XvProcVector[xv_PutImage] = ProcXvPutImage; - XvProcVector[xv_ShmPutImage] = ProcXvShmPutImage; -#endif -} +/*********************************************************** +Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts, +and the Massachusetts Institute of Technology, Cambridge, 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 names of Digital or MIT 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. +******************************************************************/ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include + +#include +#include +#include "misc.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "gcstruct.h" +#include "dixstruct.h" +#include "resource.h" +#include "opaque.h" + +#include +#include +#include "xvdix.h" +#ifdef MITSHM +#include +#endif + +#include "xvdisp.h" + +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" + +unsigned long XvXRTPort; +#endif + +static int +SWriteQueryExtensionReply( + ClientPtr client, + xvQueryExtensionReply *rep +){ + char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swaps(&rep->version, n); + swaps(&rep->revision, n); + + (void)WriteToClient(client, sz_xvQueryExtensionReply, (char *)rep); + + return Success; +} + +static int +SWriteQueryAdaptorsReply( + ClientPtr client, + xvQueryAdaptorsReply *rep +){ + char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swaps(&rep->num_adaptors, n); + + (void)WriteToClient(client, sz_xvQueryAdaptorsReply, (char *)rep); + + return Success; +} + +static int +SWriteQueryEncodingsReply( + ClientPtr client, + xvQueryEncodingsReply *rep +){ + char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swaps(&rep->num_encodings, n); + + (void)WriteToClient(client, sz_xvQueryEncodingsReply, (char *)rep); + + return Success; +} + +static int +SWriteAdaptorInfo( + ClientPtr client, + xvAdaptorInfo *pAdaptor +){ + char n; + + swapl(&pAdaptor->base_id, n); + swaps(&pAdaptor->name_size, n); + swaps(&pAdaptor->num_ports, n); + swaps(&pAdaptor->num_formats, n); + + (void)WriteToClient(client, sz_xvAdaptorInfo, (char *)pAdaptor); + + return Success; +} + +static int +SWriteEncodingInfo( + ClientPtr client, + xvEncodingInfo *pEncoding +){ + char n; + + swapl(&pEncoding->encoding, n); + swaps(&pEncoding->name_size, n); + swaps(&pEncoding->width, n); + swaps(&pEncoding->height, n); + swapl(&pEncoding->rate.numerator, n); + swapl(&pEncoding->rate.denominator, n); + (void)WriteToClient(client, sz_xvEncodingInfo, (char *)pEncoding); + + return Success; +} + +static int +SWriteFormat( + ClientPtr client, + xvFormat *pFormat +){ + char n; + + swapl(&pFormat->visual, n); + (void)WriteToClient(client, sz_xvFormat, (char *)pFormat); + + return Success; +} + +static int +SWriteAttributeInfo( + ClientPtr client, + xvAttributeInfo *pAtt +){ + char n; + + swapl(&pAtt->flags, n); + swapl(&pAtt->size, n); + swapl(&pAtt->min, n); + swapl(&pAtt->max, n); + (void)WriteToClient(client, sz_xvAttributeInfo, (char *)pAtt); + + return Success; +} + +static int +SWriteImageFormatInfo( + ClientPtr client, + xvImageFormatInfo *pImage +){ + char n; + + swapl(&pImage->id, n); + swapl(&pImage->red_mask, n); + swapl(&pImage->green_mask, n); + swapl(&pImage->blue_mask, n); + swapl(&pImage->y_sample_bits, n); + swapl(&pImage->u_sample_bits, n); + swapl(&pImage->v_sample_bits, n); + swapl(&pImage->horz_y_period, n); + swapl(&pImage->horz_u_period, n); + swapl(&pImage->horz_v_period, n); + swapl(&pImage->vert_y_period, n); + swapl(&pImage->vert_u_period, n); + swapl(&pImage->vert_v_period, n); + + (void)WriteToClient(client, sz_xvImageFormatInfo, (char *)pImage); + + return Success; +} + +static int +SWriteGrabPortReply( + ClientPtr client, + xvGrabPortReply *rep +){ + char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + + (void)WriteToClient(client, sz_xvGrabPortReply, (char *)rep); + + return Success; +} + +static int +SWriteGetPortAttributeReply( + ClientPtr client, + xvGetPortAttributeReply *rep +){ + char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swapl(&rep->value, n); + + (void)WriteToClient(client, sz_xvGetPortAttributeReply, (char *)rep); + + return Success; +} + +static int +SWriteQueryBestSizeReply( + ClientPtr client, + xvQueryBestSizeReply *rep +){ + char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swaps(&rep->actual_width, n); + swaps(&rep->actual_height, n); + + (void)WriteToClient(client, sz_xvQueryBestSizeReply, (char *)rep); + + return Success; +} + +static int +SWriteQueryPortAttributesReply( + ClientPtr client, + xvQueryPortAttributesReply *rep +){ + char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swapl(&rep->num_attributes, n); + swapl(&rep->text_size, n); + + (void)WriteToClient(client, sz_xvQueryPortAttributesReply, (char *)rep); + + return Success; +} + +static int +SWriteQueryImageAttributesReply( + ClientPtr client, + xvQueryImageAttributesReply *rep +){ + char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swapl(&rep->num_planes, n); + swapl(&rep->data_size, n); + swaps(&rep->width, n); + swaps(&rep->height, n); + + (void)WriteToClient(client, sz_xvQueryImageAttributesReply, (char *)rep); + + return Success; +} + +static int +SWriteListImageFormatsReply( + ClientPtr client, + xvListImageFormatsReply *rep +){ + char n; + + swaps(&rep->sequenceNumber, n); + swapl(&rep->length, n); + swapl(&rep->num_formats, n); + + (void)WriteToClient(client, sz_xvListImageFormatsReply, (char *)rep); + + return Success; +} + +#define _WriteQueryAdaptorsReply(_c,_d) \ + if ((_c)->swapped) SWriteQueryAdaptorsReply(_c, _d); \ + else WriteToClient(_c, sz_xvQueryAdaptorsReply, (char*)_d) + +#define _WriteQueryExtensionReply(_c,_d) \ + if ((_c)->swapped) SWriteQueryExtensionReply(_c, _d); \ + else WriteToClient(_c, sz_xvQueryExtensionReply, (char*)_d) + +#define _WriteQueryEncodingsReply(_c,_d) \ + if ((_c)->swapped) SWriteQueryEncodingsReply(_c, _d); \ + else WriteToClient(_c, sz_xvQueryEncodingsReply, (char*)_d) + +#define _WriteAdaptorInfo(_c,_d) \ + if ((_c)->swapped) SWriteAdaptorInfo(_c, _d); \ + else WriteToClient(_c, sz_xvAdaptorInfo, (char*)_d) + +#define _WriteAttributeInfo(_c,_d) \ + if ((_c)->swapped) SWriteAttributeInfo(_c, _d); \ + else WriteToClient(_c, sz_xvAttributeInfo, (char*)_d) + +#define _WriteEncodingInfo(_c,_d) \ + if ((_c)->swapped) SWriteEncodingInfo(_c, _d); \ + else WriteToClient(_c, sz_xvEncodingInfo, (char*)_d) + +#define _WriteFormat(_c,_d) \ + if ((_c)->swapped) SWriteFormat(_c, _d); \ + else WriteToClient(_c, sz_xvFormat, (char*)_d) + +#define _WriteGrabPortReply(_c,_d) \ + if ((_c)->swapped) SWriteGrabPortReply(_c, _d); \ + else WriteToClient(_c, sz_xvGrabPortReply, (char*)_d) + +#define _WriteGetPortAttributeReply(_c,_d) \ + if ((_c)->swapped) SWriteGetPortAttributeReply(_c, _d); \ + else WriteToClient(_c, sz_xvGetPortAttributeReply, (char*)_d) + +#define _WriteQueryBestSizeReply(_c,_d) \ + if ((_c)->swapped) SWriteQueryBestSizeReply(_c, _d); \ + else WriteToClient(_c, sz_xvQueryBestSizeReply,(char*) _d) + +#define _WriteQueryPortAttributesReply(_c,_d) \ + if ((_c)->swapped) SWriteQueryPortAttributesReply(_c, _d); \ + else WriteToClient(_c, sz_xvQueryPortAttributesReply,(char*) _d) + +#define _WriteQueryImageAttributesReply(_c,_d) \ + if ((_c)->swapped) SWriteQueryImageAttributesReply(_c, _d); \ + else WriteToClient(_c, sz_xvQueryImageAttributesReply,(char*) _d) + +#define _WriteListImageFormatsReply(_c,_d) \ + if ((_c)->swapped) SWriteListImageFormatsReply(_c, _d); \ + else WriteToClient(_c, sz_xvListImageFormatsReply,(char*) _d) + +#define _WriteImageFormatInfo(_c,_d) \ + if ((_c)->swapped) SWriteImageFormatInfo(_c, _d); \ + else WriteToClient(_c, sz_xvImageFormatInfo, (char*)_d) + +#define _AllocatePort(_i,_p) \ + ((_p)->id != _i) ? (* (_p)->pAdaptor->ddAllocatePort)(_i,_p,&_p) : Success + +static int +ProcXvQueryExtension(ClientPtr client) +{ + xvQueryExtensionReply rep; + /* REQUEST(xvQueryExtensionReq); */ + REQUEST_SIZE_MATCH(xvQueryExtensionReq); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.version = XvVersion; + rep.revision = XvRevision; + + _WriteQueryExtensionReply(client, &rep); + + return Success; +} + +static int +ProcXvQueryAdaptors(ClientPtr client) +{ + xvFormat format; + xvAdaptorInfo ainfo; + xvQueryAdaptorsReply rep; + int totalSize, na, nf, rc; + int nameSize; + XvAdaptorPtr pa; + XvFormatPtr pf; + WindowPtr pWin; + ScreenPtr pScreen; + XvScreenPtr pxvs; + + REQUEST(xvQueryAdaptorsReq); + REQUEST_SIZE_MATCH(xvQueryAdaptorsReq); + + rc = dixLookupWindow(&pWin, stuff->window, client, DixGetAttrAccess); + if (rc != Success) + return rc; + + pScreen = pWin->drawable.pScreen; + pxvs = (XvScreenPtr)dixLookupPrivate(&pScreen->devPrivates, + XvGetScreenKey()); + if (!pxvs) + { + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.num_adaptors = 0; + rep.length = 0; + + _WriteQueryAdaptorsReply(client, &rep); + + return Success; + } + + (* pxvs->ddQueryAdaptors)(pScreen, &pxvs->pAdaptors, &pxvs->nAdaptors); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.num_adaptors = pxvs->nAdaptors; + + /* CALCULATE THE TOTAL SIZE OF THE REPLY IN BYTES */ + + totalSize = pxvs->nAdaptors * sz_xvAdaptorInfo; + + /* FOR EACH ADPATOR ADD UP THE BYTES FOR ENCODINGS AND FORMATS */ + + na = pxvs->nAdaptors; + pa = pxvs->pAdaptors; + while (na--) + { + totalSize += pad_to_int32(strlen(pa->name)); + totalSize += pa->nFormats * sz_xvFormat; + pa++; + } + + rep.length = bytes_to_int32(totalSize); + + _WriteQueryAdaptorsReply(client, &rep); + + na = pxvs->nAdaptors; + pa = pxvs->pAdaptors; + while (na--) + { + + ainfo.base_id = pa->base_id; + ainfo.num_ports = pa->nPorts; + ainfo.type = pa->type; + ainfo.name_size = nameSize = strlen(pa->name); + ainfo.num_formats = pa->nFormats; + + _WriteAdaptorInfo(client, &ainfo); + + WriteToClient(client, nameSize, pa->name); + + nf = pa->nFormats; + pf = pa->pFormats; + while (nf--) + { + format.depth = pf->depth; + format.visual = pf->visual; + _WriteFormat(client, &format); + pf++; + } + + pa++; + + } + + return Success; +} + +static int +ProcXvQueryEncodings(ClientPtr client) +{ + xvEncodingInfo einfo; + xvQueryEncodingsReply rep; + int totalSize; + int nameSize; + XvPortPtr pPort; + int ne; + XvEncodingPtr pe; + int status; + + REQUEST(xvQueryEncodingsReq); + REQUEST_SIZE_MATCH(xvQueryEncodingsReq); + + VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess); + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.num_encodings = pPort->pAdaptor->nEncodings; + + /* FOR EACH ENCODING ADD UP THE BYTES FOR ENCODING NAMES */ + + ne = pPort->pAdaptor->nEncodings; + pe = pPort->pAdaptor->pEncodings; + totalSize = ne * sz_xvEncodingInfo; + while (ne--) + { + totalSize += pad_to_int32(strlen(pe->name)); + pe++; + } + + rep.length = bytes_to_int32(totalSize); + + _WriteQueryEncodingsReply(client, &rep); + + ne = pPort->pAdaptor->nEncodings; + pe = pPort->pAdaptor->pEncodings; + while (ne--) + { + einfo.encoding = pe->id; + einfo.name_size = nameSize = strlen(pe->name); + einfo.width = pe->width; + einfo.height = pe->height; + einfo.rate.numerator = pe->rate.numerator; + einfo.rate.denominator = pe->rate.denominator; + _WriteEncodingInfo(client, &einfo); + WriteToClient(client, nameSize, pe->name); + pe++; + } + + return Success; +} + +static int +ProcXvPutVideo(ClientPtr client) +{ + DrawablePtr pDraw; + XvPortPtr pPort; + GCPtr pGC; + int status; + + REQUEST(xvPutVideoReq); + REQUEST_SIZE_MATCH(xvPutVideoReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); + VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess); + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!(pPort->pAdaptor->type & XvInputMask) || + !(pPort->pAdaptor->type & XvVideoMask)) + { + client->errorValue = stuff->port; + return (BadMatch); + } + + status = XvdiMatchPort(pPort, pDraw); + if (status != Success) + { + return status; + } + + return XvdiPutVideo(client, pDraw, pPort, pGC, stuff->vid_x, stuff->vid_y, + stuff->vid_w, stuff->vid_h, stuff->drw_x, stuff->drw_y, + stuff->drw_w, stuff->drw_h); +} + +static int +ProcXvPutStill(ClientPtr client) +{ + DrawablePtr pDraw; + XvPortPtr pPort; + GCPtr pGC; + int status; + + REQUEST(xvPutStillReq); + REQUEST_SIZE_MATCH(xvPutStillReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); + VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess); + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!(pPort->pAdaptor->type & XvInputMask) || + !(pPort->pAdaptor->type & XvStillMask)) + { + client->errorValue = stuff->port; + return (BadMatch); + } + + status = XvdiMatchPort(pPort, pDraw); + if (status != Success) + { + return status; + } + + return XvdiPutStill(client, pDraw, pPort, pGC, stuff->vid_x, stuff->vid_y, + stuff->vid_w, stuff->vid_h, stuff->drw_x, stuff->drw_y, + stuff->drw_w, stuff->drw_h); +} + +static int +ProcXvGetVideo(ClientPtr client) +{ + DrawablePtr pDraw; + XvPortPtr pPort; + GCPtr pGC; + int status; + + REQUEST(xvGetVideoReq); + REQUEST_SIZE_MATCH(xvGetVideoReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixReadAccess); + VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess); + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!(pPort->pAdaptor->type & XvOutputMask) || + !(pPort->pAdaptor->type & XvVideoMask)) + { + client->errorValue = stuff->port; + return (BadMatch); + } + + status = XvdiMatchPort(pPort, pDraw); + if (status != Success) + { + return status; + } + + return XvdiGetVideo(client, pDraw, pPort, pGC, stuff->vid_x, stuff->vid_y, + stuff->vid_w, stuff->vid_h, stuff->drw_x, stuff->drw_y, + stuff->drw_w, stuff->drw_h); +} + +static int +ProcXvGetStill(ClientPtr client) +{ + DrawablePtr pDraw; + XvPortPtr pPort; + GCPtr pGC; + int status; + + REQUEST(xvGetStillReq); + REQUEST_SIZE_MATCH(xvGetStillReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixReadAccess); + VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess); + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!(pPort->pAdaptor->type & XvOutputMask) || + !(pPort->pAdaptor->type & XvStillMask)) + { + client->errorValue = stuff->port; + return (BadMatch); + } + + status = XvdiMatchPort(pPort, pDraw); + if (status != Success) + { + return status; + } + + return XvdiGetStill(client, pDraw, pPort, pGC, stuff->vid_x, stuff->vid_y, + stuff->vid_w, stuff->vid_h, stuff->drw_x, stuff->drw_y, + stuff->drw_w, stuff->drw_h); +} + +static int +ProcXvSelectVideoNotify(ClientPtr client) +{ + DrawablePtr pDraw; + int rc; + REQUEST(xvSelectVideoNotifyReq); + REQUEST_SIZE_MATCH(xvSelectVideoNotifyReq); + + rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0, DixReceiveAccess); + if (rc != Success) + return rc; + + return XvdiSelectVideoNotify(client, pDraw, stuff->onoff); +} + +static int +ProcXvSelectPortNotify(ClientPtr client) +{ + int status; + XvPortPtr pPort; + REQUEST(xvSelectPortNotifyReq); + REQUEST_SIZE_MATCH(xvSelectPortNotifyReq); + + VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess); + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + return XvdiSelectPortNotify(client, pPort, stuff->onoff); +} + +static int +ProcXvGrabPort(ClientPtr client) +{ + int result, status; + XvPortPtr pPort; + xvGrabPortReply rep; + REQUEST(xvGrabPortReq); + REQUEST_SIZE_MATCH(xvGrabPortReq); + + VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess); + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + status = XvdiGrabPort(client, pPort, stuff->time, &result); + + if (status != Success) + { + return status; + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.result = result; + + _WriteGrabPortReply(client, &rep); + + return Success; +} + +static int +ProcXvUngrabPort(ClientPtr client) +{ + int status; + XvPortPtr pPort; + REQUEST(xvGrabPortReq); + REQUEST_SIZE_MATCH(xvGrabPortReq); + + VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess); + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + return XvdiUngrabPort(client, pPort, stuff->time); +} + +static int +ProcXvStopVideo(ClientPtr client) +{ + int status, rc; + DrawablePtr pDraw; + XvPortPtr pPort; + REQUEST(xvStopVideoReq); + REQUEST_SIZE_MATCH(xvStopVideoReq); + + VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess); + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0, DixWriteAccess); + if (rc != Success) + return rc; + + return XvdiStopVideo(client, pPort, pDraw); +} + +static int +ProcXvSetPortAttribute(ClientPtr client) +{ + int status; + XvPortPtr pPort; + REQUEST(xvSetPortAttributeReq); + REQUEST_SIZE_MATCH(xvSetPortAttributeReq); + + VALIDATE_XV_PORT(stuff->port, pPort, DixSetAttrAccess); + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!ValidAtom(stuff->attribute)) + { + client->errorValue = stuff->attribute; + return(BadAtom); + } + + status = XvdiSetPortAttribute(client, pPort, stuff->attribute, stuff->value); + + if (status == BadMatch) + client->errorValue = stuff->attribute; + else + client->errorValue = stuff->value; + + return status; +} + +static int +ProcXvGetPortAttribute(ClientPtr client) +{ + INT32 value; + int status; + XvPortPtr pPort; + xvGetPortAttributeReply rep; + REQUEST(xvGetPortAttributeReq); + REQUEST_SIZE_MATCH(xvGetPortAttributeReq); + + VALIDATE_XV_PORT(stuff->port, pPort, DixGetAttrAccess); + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!ValidAtom(stuff->attribute)) + { + client->errorValue = stuff->attribute; + return(BadAtom); + } + + status = XvdiGetPortAttribute(client, pPort, stuff->attribute, &value); + if (status != Success) + { + client->errorValue = stuff->attribute; + return status; + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.value = value; + + _WriteGetPortAttributeReply(client, &rep); + + return Success; +} + +static int +ProcXvQueryBestSize(ClientPtr client) +{ + int status; + unsigned int actual_width, actual_height; + XvPortPtr pPort; + xvQueryBestSizeReply rep; + REQUEST(xvQueryBestSizeReq); + REQUEST_SIZE_MATCH(xvQueryBestSizeReq); + + VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess); + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + + (* pPort->pAdaptor->ddQueryBestSize)(client, pPort, stuff->motion, + stuff->vid_w, stuff->vid_h, + stuff->drw_w, stuff->drw_h, + &actual_width, &actual_height); + + rep.actual_width = actual_width; + rep.actual_height = actual_height; + + _WriteQueryBestSizeReply(client, &rep); + + return Success; +} + + +static int +ProcXvQueryPortAttributes(ClientPtr client) +{ + int status, size, i; + XvPortPtr pPort; + XvAttributePtr pAtt; + xvQueryPortAttributesReply rep; + xvAttributeInfo Info; + REQUEST(xvQueryPortAttributesReq); + REQUEST_SIZE_MATCH(xvQueryPortAttributesReq); + + VALIDATE_XV_PORT(stuff->port, pPort, DixGetAttrAccess); + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.num_attributes = pPort->pAdaptor->nAttributes; + rep.text_size = 0; + + for(i = 0, pAtt = pPort->pAdaptor->pAttributes; + i < pPort->pAdaptor->nAttributes; i++, pAtt++) + { + rep.text_size += pad_to_int32(strlen(pAtt->name) + 1); + } + + rep.length = (pPort->pAdaptor->nAttributes * sz_xvAttributeInfo) + + rep.text_size; + rep.length >>= 2; + + _WriteQueryPortAttributesReply(client, &rep); + + for(i = 0, pAtt = pPort->pAdaptor->pAttributes; + i < pPort->pAdaptor->nAttributes; i++, pAtt++) + { + size = strlen(pAtt->name) + 1; /* pass the NULL */ + Info.flags = pAtt->flags; + Info.min = pAtt->min_value; + Info.max = pAtt->max_value; + Info.size = pad_to_int32(size); + + _WriteAttributeInfo(client, &Info); + + WriteToClient(client, size, pAtt->name); + } + + return Success; +} + +static int +ProcXvPutImage(ClientPtr client) +{ + DrawablePtr pDraw; + XvPortPtr pPort; + XvImagePtr pImage = NULL; + GCPtr pGC; + int status, i, size; + CARD16 width, height; + + REQUEST(xvPutImageReq); + REQUEST_AT_LEAST_SIZE(xvPutImageReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); + VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess); + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!(pPort->pAdaptor->type & XvImageMask) || + !(pPort->pAdaptor->type & XvInputMask)) + { + client->errorValue = stuff->port; + return (BadMatch); + } + + status = XvdiMatchPort(pPort, pDraw); + if (status != Success) + { + return status; + } + + for(i = 0; i < pPort->pAdaptor->nImages; i++) { + if(pPort->pAdaptor->pImages[i].id == stuff->id) { + pImage = &(pPort->pAdaptor->pImages[i]); + break; + } + } + + if(!pImage) + return BadMatch; + + width = stuff->width; + height = stuff->height; + size = (*pPort->pAdaptor->ddQueryImageAttributes)(client, + pPort, pImage, &width, &height, NULL, NULL); + size += sizeof(xvPutImageReq); + size = bytes_to_int32(size); + + if((width < stuff->width) || (height < stuff->height)) + return BadValue; + + if(client->req_len < size) + return BadLength; + + return XvdiPutImage(client, pDraw, pPort, pGC, stuff->src_x, stuff->src_y, + stuff->src_w, stuff->src_h, stuff->drw_x, stuff->drw_y, + stuff->drw_w, stuff->drw_h, pImage, + (unsigned char*)(&stuff[1]), FALSE, + stuff->width, stuff->height); +} + +#ifdef MITSHM +/* redefined here since it's not in any header file */ +typedef struct _ShmDesc { + struct _ShmDesc *next; + int shmid; + int refcnt; + char *addr; + Bool writable; + unsigned long size; +} ShmDescRec, *ShmDescPtr; + +extern RESTYPE ShmSegType; +extern int BadShmSegCode; +extern int ShmCompletionCode; + +static int +ProcXvShmPutImage(ClientPtr client) +{ + ShmDescPtr shmdesc; + DrawablePtr pDraw; + XvPortPtr pPort; + XvImagePtr pImage = NULL; + GCPtr pGC; + int status, size_needed, i; + CARD16 width, height; + + REQUEST(xvShmPutImageReq); + REQUEST_SIZE_MATCH(xvShmPutImageReq); + + VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); + VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess); + + if ((status = _AllocatePort(stuff->port, pPort)) != Success) + { + client->errorValue = stuff->port; + return (status); + } + + if (!(pPort->pAdaptor->type & XvImageMask) || + !(pPort->pAdaptor->type & XvInputMask)) + { + client->errorValue = stuff->port; + return (BadMatch); + } + + status = XvdiMatchPort(pPort, pDraw); + if (status != Success) + { + return status; + } + + for(i = 0; i < pPort->pAdaptor->nImages; i++) { + if(pPort->pAdaptor->pImages[i].id == stuff->id) { + pImage = &(pPort->pAdaptor->pImages[i]); + break; + } + } + + if(!pImage) + return BadMatch; + + status = dixLookupResourceByType((pointer *)&shmdesc, stuff->shmseg, + ShmSegType, serverClient, DixReadAccess); + if (status != Success) + return (status == BadValue) ? BadShmSegCode : status; + + width = stuff->width; + height = stuff->height; + size_needed = (*pPort->pAdaptor->ddQueryImageAttributes)(client, + pPort, pImage, &width, &height, NULL, NULL); + if((size_needed + stuff->offset) > shmdesc->size) + return BadAccess; + + if((width < stuff->width) || (height < stuff->height)) + return BadValue; + + status = XvdiPutImage(client, pDraw, pPort, pGC, stuff->src_x, stuff->src_y, + stuff->src_w, stuff->src_h, stuff->drw_x, stuff->drw_y, + stuff->drw_w, stuff->drw_h, pImage, + (unsigned char *)shmdesc->addr + stuff->offset, + stuff->send_event, stuff->width, stuff->height); + + if((status == Success) && stuff->send_event) { + xShmCompletionEvent ev; + + ev.type = ShmCompletionCode; + ev.drawable = stuff->drawable; + ev.sequenceNumber = client->sequence; + ev.minorEvent = xv_ShmPutImage; + ev.majorEvent = XvReqCode; + ev.shmseg = stuff->shmseg; + ev.offset = stuff->offset; + WriteEventsToClient(client, 1, (xEvent *) &ev); + } + + return status; +} +#else /* !MITSHM */ +static int +ProcXvShmPutImage(ClientPtr client) +{ + SendErrorToClient(client, XvReqCode, xv_ShmPutImage, 0, BadImplementation); + return(BadImplementation); +} +#endif + +#ifdef XvMCExtension +#include "xvmcext.h" +#endif + +static int +ProcXvQueryImageAttributes(ClientPtr client) +{ + xvQueryImageAttributesReply rep; + int size, num_planes, i; + CARD16 width, height; + XvImagePtr pImage = NULL; + XvPortPtr pPort; + int *offsets; + int *pitches; + int planeLength; + REQUEST(xvQueryImageAttributesReq); + + REQUEST_SIZE_MATCH(xvQueryImageAttributesReq); + + VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess); + + for(i = 0; i < pPort->pAdaptor->nImages; i++) { + if(pPort->pAdaptor->pImages[i].id == stuff->id) { + pImage = &(pPort->pAdaptor->pImages[i]); + break; + } + } + +#ifdef XvMCExtension + if(!pImage) + pImage = XvMCFindXvImage(pPort, stuff->id); +#endif + + if(!pImage) + return BadMatch; + + num_planes = pImage->num_planes; + + if(!(offsets = malloc(num_planes << 3))) + return BadAlloc; + pitches = offsets + num_planes; + + width = stuff->width; + height = stuff->height; + + size = (*pPort->pAdaptor->ddQueryImageAttributes)(client, pPort, pImage, + &width, &height, offsets, pitches); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = planeLength = num_planes << 1; + rep.num_planes = num_planes; + rep.width = width; + rep.height = height; + rep.data_size = size; + + _WriteQueryImageAttributesReply(client, &rep); + if(client->swapped) + SwapLongs((CARD32*)offsets, planeLength); + WriteToClient(client, planeLength << 2, (char*)offsets); + + free(offsets); + + return Success; +} + +static int +ProcXvListImageFormats(ClientPtr client) +{ + XvPortPtr pPort; + XvImagePtr pImage; + int i; + xvListImageFormatsReply rep; + xvImageFormatInfo info; + REQUEST(xvListImageFormatsReq); + + REQUEST_SIZE_MATCH(xvListImageFormatsReq); + + VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.num_formats = pPort->pAdaptor->nImages; + rep.length = bytes_to_int32(pPort->pAdaptor->nImages * sz_xvImageFormatInfo); + + _WriteListImageFormatsReply(client, &rep); + + pImage = pPort->pAdaptor->pImages; + + for(i = 0; i < pPort->pAdaptor->nImages; i++, pImage++) { + info.id = pImage->id; + info.type = pImage->type; + info.byte_order = pImage->byte_order; + memcpy(&info.guid, pImage->guid, 16); + info.bpp = pImage->bits_per_pixel; + info.num_planes = pImage->num_planes; + info.depth = pImage->depth; + info.red_mask = pImage->red_mask; + info.green_mask = pImage->green_mask; + info.blue_mask = pImage->blue_mask; + info.format = pImage->format; + info.y_sample_bits = pImage->y_sample_bits; + info.u_sample_bits = pImage->u_sample_bits; + info.v_sample_bits = pImage->v_sample_bits; + info.horz_y_period = pImage->horz_y_period; + info.horz_u_period = pImage->horz_u_period; + info.horz_v_period = pImage->horz_v_period; + info.vert_y_period = pImage->vert_y_period; + info.vert_u_period = pImage->vert_u_period; + info.vert_v_period = pImage->vert_v_period; + memcpy(&info.comp_order, pImage->component_order, 32); + info.scanline_order = pImage->scanline_order; + _WriteImageFormatInfo(client, &info); + } + + return Success; +} + +static int (*XvProcVector[xvNumRequests])(ClientPtr) = { + ProcXvQueryExtension, + ProcXvQueryAdaptors, + ProcXvQueryEncodings, + ProcXvGrabPort, + ProcXvUngrabPort, + ProcXvPutVideo, + ProcXvPutStill, + ProcXvGetVideo, + ProcXvGetStill, + ProcXvStopVideo, + ProcXvSelectVideoNotify, + ProcXvSelectPortNotify, + ProcXvQueryBestSize, + ProcXvSetPortAttribute, + ProcXvGetPortAttribute, + ProcXvQueryPortAttributes, + ProcXvListImageFormats, + ProcXvQueryImageAttributes, + ProcXvPutImage, + ProcXvShmPutImage, +}; + +int +ProcXvDispatch(ClientPtr client) +{ + REQUEST(xReq); + + UpdateCurrentTime(); + + if (stuff->data > xvNumRequests) { + SendErrorToClient(client, XvReqCode, stuff->data, 0, BadRequest); + return(BadRequest); + } + + return XvProcVector[stuff->data](client); +} + +/* Swapped Procs */ + +static int +SProcXvQueryExtension(ClientPtr client) +{ + char n; + REQUEST(xvQueryExtensionReq); + swaps(&stuff->length, n); + return XvProcVector[xv_QueryExtension](client); +} + +static int +SProcXvQueryAdaptors(ClientPtr client) +{ + char n; + REQUEST(xvQueryAdaptorsReq); + swaps(&stuff->length, n); + swapl(&stuff->window, n); + return XvProcVector[xv_QueryAdaptors](client); +} + +static int +SProcXvQueryEncodings(ClientPtr client) +{ + char n; + REQUEST(xvQueryEncodingsReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + return XvProcVector[xv_QueryEncodings](client); +} + +static int +SProcXvGrabPort(ClientPtr client) +{ + char n; + REQUEST(xvGrabPortReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->time, n); + return XvProcVector[xv_GrabPort](client); +} + +static int +SProcXvUngrabPort(ClientPtr client) +{ + char n; + REQUEST(xvUngrabPortReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->time, n); + return XvProcVector[xv_UngrabPort](client); +} + +static int +SProcXvPutVideo(ClientPtr client) +{ + char n; + REQUEST(xvPutVideoReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swaps(&stuff->vid_x, n); + swaps(&stuff->vid_y, n); + swaps(&stuff->vid_w, n); + swaps(&stuff->vid_h, n); + swaps(&stuff->drw_x, n); + swaps(&stuff->drw_y, n); + swaps(&stuff->drw_w, n); + swaps(&stuff->drw_h, n); + return XvProcVector[xv_PutVideo](client); +} + +static int +SProcXvPutStill(ClientPtr client) +{ + char n; + REQUEST(xvPutStillReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swaps(&stuff->vid_x, n); + swaps(&stuff->vid_y, n); + swaps(&stuff->vid_w, n); + swaps(&stuff->vid_h, n); + swaps(&stuff->drw_x, n); + swaps(&stuff->drw_y, n); + swaps(&stuff->drw_w, n); + swaps(&stuff->drw_h, n); + return XvProcVector[xv_PutStill](client); +} + +static int +SProcXvGetVideo(ClientPtr client) +{ + char n; + REQUEST(xvGetVideoReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swaps(&stuff->vid_x, n); + swaps(&stuff->vid_y, n); + swaps(&stuff->vid_w, n); + swaps(&stuff->vid_h, n); + swaps(&stuff->drw_x, n); + swaps(&stuff->drw_y, n); + swaps(&stuff->drw_w, n); + swaps(&stuff->drw_h, n); + return XvProcVector[xv_GetVideo](client); +} + +static int +SProcXvGetStill(ClientPtr client) +{ + char n; + REQUEST(xvGetStillReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swaps(&stuff->vid_x, n); + swaps(&stuff->vid_y, n); + swaps(&stuff->vid_w, n); + swaps(&stuff->vid_h, n); + swaps(&stuff->drw_x, n); + swaps(&stuff->drw_y, n); + swaps(&stuff->drw_w, n); + swaps(&stuff->drw_h, n); + return XvProcVector[xv_GetStill](client); +} + +static int +SProcXvPutImage(ClientPtr client) +{ + char n; + REQUEST(xvPutImageReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swapl(&stuff->id, n); + swaps(&stuff->src_x, n); + swaps(&stuff->src_y, n); + swaps(&stuff->src_w, n); + swaps(&stuff->src_h, n); + swaps(&stuff->drw_x, n); + swaps(&stuff->drw_y, n); + swaps(&stuff->drw_w, n); + swaps(&stuff->drw_h, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + return XvProcVector[xv_PutImage](client); +} + +#ifdef MITSHM +static int +SProcXvShmPutImage(ClientPtr client) +{ + char n; + REQUEST(xvShmPutImageReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->drawable, n); + swapl(&stuff->gc, n); + swapl(&stuff->shmseg, n); + swapl(&stuff->id, n); + swapl(&stuff->offset, n); + swaps(&stuff->src_x, n); + swaps(&stuff->src_y, n); + swaps(&stuff->src_w, n); + swaps(&stuff->src_h, n); + swaps(&stuff->drw_x, n); + swaps(&stuff->drw_y, n); + swaps(&stuff->drw_w, n); + swaps(&stuff->drw_h, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + return XvProcVector[xv_ShmPutImage](client); +} +#else /* MITSHM */ +#define SProcXvShmPutImage ProcXvShmPutImage +#endif + +static int +SProcXvSelectVideoNotify(ClientPtr client) +{ + char n; + REQUEST(xvSelectVideoNotifyReq); + swaps(&stuff->length, n); + swapl(&stuff->drawable, n); + return XvProcVector[xv_SelectVideoNotify](client); +} + +static int +SProcXvSelectPortNotify(ClientPtr client) +{ + char n; + REQUEST(xvSelectPortNotifyReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + return XvProcVector[xv_SelectPortNotify](client); +} + +static int +SProcXvStopVideo(ClientPtr client) +{ + char n; + REQUEST(xvStopVideoReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->drawable, n); + return XvProcVector[xv_StopVideo](client); +} + +static int +SProcXvSetPortAttribute(ClientPtr client) +{ + char n; + REQUEST(xvSetPortAttributeReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->attribute, n); + swapl(&stuff->value, n); + return XvProcVector[xv_SetPortAttribute](client); +} + +static int +SProcXvGetPortAttribute(ClientPtr client) +{ + char n; + REQUEST(xvGetPortAttributeReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->attribute, n); + return XvProcVector[xv_GetPortAttribute](client); +} + +static int +SProcXvQueryBestSize(ClientPtr client) +{ + char n; + REQUEST(xvQueryBestSizeReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swaps(&stuff->vid_w, n); + swaps(&stuff->vid_h, n); + swaps(&stuff->drw_w, n); + swaps(&stuff->drw_h, n); + return XvProcVector[xv_QueryBestSize](client); +} + +static int +SProcXvQueryPortAttributes(ClientPtr client) +{ + char n; + REQUEST(xvQueryPortAttributesReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + return XvProcVector[xv_QueryPortAttributes](client); +} + +static int +SProcXvQueryImageAttributes(ClientPtr client) +{ + char n; + REQUEST(xvQueryImageAttributesReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + swapl(&stuff->id, n); + swaps(&stuff->width, n); + swaps(&stuff->height, n); + return XvProcVector[xv_QueryImageAttributes](client); +} + +static int +SProcXvListImageFormats(ClientPtr client) +{ + char n; + REQUEST(xvListImageFormatsReq); + swaps(&stuff->length, n); + swapl(&stuff->port, n); + return XvProcVector[xv_ListImageFormats](client); +} + +static int (*SXvProcVector[xvNumRequests])(ClientPtr) = { + SProcXvQueryExtension, + SProcXvQueryAdaptors, + SProcXvQueryEncodings, + SProcXvGrabPort, + SProcXvUngrabPort, + SProcXvPutVideo, + SProcXvPutStill, + SProcXvGetVideo, + SProcXvGetStill, + SProcXvStopVideo, + SProcXvSelectVideoNotify, + SProcXvSelectPortNotify, + SProcXvQueryBestSize, + SProcXvSetPortAttribute, + SProcXvGetPortAttribute, + SProcXvQueryPortAttributes, + SProcXvListImageFormats, + SProcXvQueryImageAttributes, + SProcXvPutImage, + SProcXvShmPutImage, +}; + +int +SProcXvDispatch(ClientPtr client) +{ + REQUEST(xReq); + + UpdateCurrentTime(); + + if (stuff->data > xvNumRequests) { + SendErrorToClient(client, XvReqCode, stuff->data, 0, BadRequest); + return(BadRequest); + } + + return SXvProcVector[stuff->data](client); +} + +#ifdef PANORAMIX +static int +XineramaXvStopVideo(ClientPtr client) +{ + int result, i; + PanoramiXRes *draw, *port; + REQUEST(xvStopVideoReq); + REQUEST_SIZE_MATCH(xvStopVideoReq); + + result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable, + XRC_DRAWABLE, client, DixWriteAccess); + if (result != Success) + return (result == BadValue) ? BadDrawable : result; + + result = dixLookupResourceByType((pointer *)&port, stuff->port, + XvXRTPort, client, DixReadAccess); + if (result != Success) + return (result == BadValue) ? _XvBadPort : result; + + FOR_NSCREENS_BACKWARD(i) { + if(port->info[i].id) { + stuff->drawable = draw->info[i].id; + stuff->port = port->info[i].id; + result = ProcXvStopVideo(client); + } + } + + return result; +} + +static int +XineramaXvSetPortAttribute(ClientPtr client) +{ + REQUEST(xvSetPortAttributeReq); + PanoramiXRes *port; + int result, i; + + REQUEST_SIZE_MATCH(xvSetPortAttributeReq); + + result = dixLookupResourceByType((pointer *)&port, stuff->port, + XvXRTPort, client, DixReadAccess); + if (result != Success) + return (result == BadValue) ? _XvBadPort : result; + + FOR_NSCREENS_BACKWARD(i) { + if(port->info[i].id) { + stuff->port = port->info[i].id; + result = ProcXvSetPortAttribute(client); + } + } + return result; +} + +#ifdef MITSHM +static int +XineramaXvShmPutImage(ClientPtr client) +{ + REQUEST(xvShmPutImageReq); + PanoramiXRes *draw, *gc, *port; + Bool send_event = stuff->send_event; + Bool isRoot; + int result, i, x, y; + + REQUEST_SIZE_MATCH(xvShmPutImageReq); + + result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable, + XRC_DRAWABLE, client, DixWriteAccess); + if (result != Success) + return (result == BadValue) ? BadDrawable : result; + + result = dixLookupResourceByType((pointer *)&gc, stuff->gc, + XRT_GC, client, DixReadAccess); + if (result != Success) + return (result == BadValue) ? BadGC : result; + + result = dixLookupResourceByType((pointer *)&port, stuff->port, + XvXRTPort, client, DixReadAccess); + if (result != Success) + return (result == BadValue) ? _XvBadPort : result; + + isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; + + x = stuff->drw_x; + y = stuff->drw_y; + + FOR_NSCREENS_BACKWARD(i) { + if(port->info[i].id) { + stuff->drawable = draw->info[i].id; + stuff->port = port->info[i].id; + stuff->gc = gc->info[i].id; + stuff->drw_x = x; + stuff->drw_y = y; + if(isRoot) { + stuff->drw_x -= panoramiXdataPtr[i].x; + stuff->drw_y -= panoramiXdataPtr[i].y; + } + stuff->send_event = (send_event && !i) ? 1 : 0; + + result = ProcXvShmPutImage(client); + } + } + return result; +} +#else +#define XineramaXvShmPutImage ProcXvShmPutImage +#endif + +static int +XineramaXvPutImage(ClientPtr client) +{ + REQUEST(xvPutImageReq); + PanoramiXRes *draw, *gc, *port; + Bool isRoot; + int result, i, x, y; + + REQUEST_AT_LEAST_SIZE(xvPutImageReq); + + result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable, + XRC_DRAWABLE, client, DixWriteAccess); + if (result != Success) + return (result == BadValue) ? BadDrawable : result; + + result = dixLookupResourceByType((pointer *)&gc, stuff->gc, + XRT_GC, client, DixReadAccess); + if (result != Success) + return (result == BadValue) ? BadGC : result; + + result = dixLookupResourceByType((pointer *)&port, stuff->port, + XvXRTPort, client, DixReadAccess); + if (result != Success) + return (result == BadValue) ? _XvBadPort : result; + + isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; + + x = stuff->drw_x; + y = stuff->drw_y; + + FOR_NSCREENS_BACKWARD(i) { + if(port->info[i].id) { + stuff->drawable = draw->info[i].id; + stuff->port = port->info[i].id; + stuff->gc = gc->info[i].id; + stuff->drw_x = x; + stuff->drw_y = y; + if(isRoot) { + stuff->drw_x -= panoramiXdataPtr[i].x; + stuff->drw_y -= panoramiXdataPtr[i].y; + } + + result = ProcXvPutImage(client); + } + } + return result; +} + +static int +XineramaXvPutVideo(ClientPtr client) +{ + REQUEST(xvPutImageReq); + PanoramiXRes *draw, *gc, *port; + Bool isRoot; + int result, i, x, y; + + REQUEST_AT_LEAST_SIZE(xvPutVideoReq); + + result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable, + XRC_DRAWABLE, client, DixWriteAccess); + if (result != Success) + return (result == BadValue) ? BadDrawable : result; + + result = dixLookupResourceByType((pointer *)&gc, stuff->gc, + XRT_GC, client, DixReadAccess); + if (result != Success) + return (result == BadValue) ? BadGC : result; + + result = dixLookupResourceByType((pointer *)&port, stuff->port, + XvXRTPort, client, DixReadAccess); + if (result != Success) + return (result == BadValue) ? _XvBadPort : result; + + isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; + + x = stuff->drw_x; + y = stuff->drw_y; + + FOR_NSCREENS_BACKWARD(i) { + if(port->info[i].id) { + stuff->drawable = draw->info[i].id; + stuff->port = port->info[i].id; + stuff->gc = gc->info[i].id; + stuff->drw_x = x; + stuff->drw_y = y; + if(isRoot) { + stuff->drw_x -= panoramiXdataPtr[i].x; + stuff->drw_y -= panoramiXdataPtr[i].y; + } + + result = ProcXvPutVideo(client); + } + } + return result; +} + +static int +XineramaXvPutStill(ClientPtr client) +{ + REQUEST(xvPutImageReq); + PanoramiXRes *draw, *gc, *port; + Bool isRoot; + int result, i, x, y; + + REQUEST_AT_LEAST_SIZE(xvPutImageReq); + + result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable, + XRC_DRAWABLE, client, DixWriteAccess); + if (result != Success) + return (result == BadValue) ? BadDrawable : result; + + result = dixLookupResourceByType((pointer *)&gc, stuff->gc, + XRT_GC, client, DixReadAccess); + if (result != Success) + return (result == BadValue) ? BadGC : result; + + result = dixLookupResourceByType((pointer *)&port, stuff->port, + XvXRTPort, client, DixReadAccess); + if (result != Success) + return (result == BadValue) ? _XvBadPort : result; + + isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; + + x = stuff->drw_x; + y = stuff->drw_y; + + FOR_NSCREENS_BACKWARD(i) { + if(port->info[i].id) { + stuff->drawable = draw->info[i].id; + stuff->port = port->info[i].id; + stuff->gc = gc->info[i].id; + stuff->drw_x = x; + stuff->drw_y = y; + if(isRoot) { + stuff->drw_x -= panoramiXdataPtr[i].x; + stuff->drw_y -= panoramiXdataPtr[i].y; + } + + result = ProcXvPutStill(client); + } + } + return result; +} + +static Bool +isImageAdaptor(XvAdaptorPtr pAdapt) +{ + return (pAdapt->type & XvImageMask) && (pAdapt->nImages > 0); +} + +static Bool +hasOverlay(XvAdaptorPtr pAdapt) +{ + int i; + for(i = 0; i < pAdapt->nAttributes; i++) + if(!strcmp(pAdapt->pAttributes[i].name, "XV_COLORKEY")) + return TRUE; + return FALSE; +} + +static XvAdaptorPtr +matchAdaptor(ScreenPtr pScreen, XvAdaptorPtr refAdapt, Bool isOverlay) +{ + int i; + XvScreenPtr xvsp = dixLookupPrivate(&pScreen->devPrivates, XvGetScreenKey()); + /* Do not try to go on if xv is not supported on this screen */ + if(xvsp == NULL) + return NULL; + + /* if the adaptor has the same name it's a perfect match */ + for(i = 0; i < xvsp->nAdaptors; i++) { + XvAdaptorPtr pAdapt = xvsp->pAdaptors + i; + if(!strcmp(refAdapt->name, pAdapt->name)) + return pAdapt; + } + + /* otherwise we only look for XvImage adaptors */ + if(!isImageAdaptor(refAdapt)) + return NULL; + + /* prefer overlay/overlay non-overlay/non-overlay pairing */ + for(i = 0; i < xvsp->nAdaptors; i++) { + XvAdaptorPtr pAdapt = xvsp->pAdaptors + i; + if(isImageAdaptor(pAdapt) && isOverlay == hasOverlay(pAdapt)) + return pAdapt; + } + + /* but we'll take any XvImage pairing if we can get it */ + for(i = 0; i < xvsp->nAdaptors; i++) { + XvAdaptorPtr pAdapt = xvsp->pAdaptors + i; + if(isImageAdaptor(pAdapt)) + return pAdapt; + } + return NULL; +} + +void XineramifyXv(void) +{ + XvScreenPtr xvsp0 = dixLookupPrivate(&screenInfo.screens[0]->devPrivates, XvGetScreenKey()); + XvAdaptorPtr MatchingAdaptors[MAXSCREENS]; + int i, j, k; + + XvXRTPort = CreateNewResourceType(XineramaDeleteResource, "XvXRTPort"); + + if (!xvsp0 || !XvXRTPort) return; + + for(i = 0; i < xvsp0->nAdaptors; i++) { + Bool isOverlay; + XvAdaptorPtr refAdapt = xvsp0->pAdaptors + i; + if(!(refAdapt->type & XvInputMask)) continue; + + MatchingAdaptors[0] = refAdapt; + isOverlay = hasOverlay(refAdapt); + for(j = 1; j < PanoramiXNumScreens; j++) + MatchingAdaptors[j] = matchAdaptor(screenInfo.screens[j], refAdapt, isOverlay); + + /* now create a resource for each port */ + for(j = 0; j < refAdapt->nPorts; j++) { + PanoramiXRes *port = malloc(sizeof(PanoramiXRes)); + if(!port) + break; + + for(k = 0; k < PanoramiXNumScreens; k++) { + if(MatchingAdaptors[k] && (MatchingAdaptors[k]->nPorts > j)) + port->info[k].id = MatchingAdaptors[k]->base_id + j; + else + port->info[k].id = 0; + } + AddResource(port->info[0].id, XvXRTPort, port); + } + } + + /* munge the dispatch vector */ + XvProcVector[xv_PutVideo] = XineramaXvPutVideo; + XvProcVector[xv_PutStill] = XineramaXvPutStill; + XvProcVector[xv_StopVideo] = XineramaXvStopVideo; + XvProcVector[xv_SetPortAttribute] = XineramaXvSetPortAttribute; + XvProcVector[xv_PutImage] = XineramaXvPutImage; + XvProcVector[xv_ShmPutImage] = XineramaXvShmPutImage; +} +#endif /* PANORAMIX */ + +void +XvResetProcVector(void) +{ +#ifdef PANORAMIX + XvProcVector[xv_PutVideo] = ProcXvPutVideo; + XvProcVector[xv_PutStill] = ProcXvPutStill; + XvProcVector[xv_StopVideo] = ProcXvStopVideo; + XvProcVector[xv_SetPortAttribute] = ProcXvSetPortAttribute; + XvProcVector[xv_PutImage] = ProcXvPutImage; + XvProcVector[xv_ShmPutImage] = ProcXvShmPutImage; +#endif +} diff --git a/xorg-server/Xext/xvmain.c b/xorg-server/Xext/xvmain.c index 05a68907a..413b94015 100644 --- a/xorg-server/Xext/xvmain.c +++ b/xorg-server/Xext/xvmain.c @@ -1,1190 +1,1188 @@ -/*********************************************************** -Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts, -and the Massachusetts Institute of Technology, Cambridge, 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 names of Digital or MIT 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. - -******************************************************************/ - -/* -** File: -** -** xvmain.c --- Xv server extension main device independent module. -** -** Author: -** -** David Carver (Digital Workstation Engineering/Project Athena) -** -** Revisions: -** -** 04.09.91 Carver -** - change: stop video always generates an event even when video -** wasn't active -** -** 29.08.91 Carver -** - change: unrealizing windows no longer preempts video -** -** 11.06.91 Carver -** - changed SetPortControl to SetPortAttribute -** - changed GetPortControl to GetPortAttribute -** - changed QueryBestSize -** -** 28.05.91 Carver -** - fixed Put and Get requests to not preempt operations to same drawable -** -** 15.05.91 Carver -** - version 2.0 upgrade -** -** 19.03.91 Carver -** - fixed Put and Get requests to honor grabbed ports. -** - fixed Video requests to update di structure with new drawable, and -** client after calling ddx. -** -** 24.01.91 Carver -** - version 1.4 upgrade -** -** Notes: -** -** Port structures reference client structures in a two different -** ways: when grabs, or video is active. Each reference is encoded -** as fake client resources and thus when the client is goes away so -** does the reference (it is zeroed). No other action is taken, so -** video doesn't necessarily stop. It probably will as a result of -** other resources going away, but if a client starts video using -** none of its own resources, then the video will continue to play -** after the client disappears. -** -** -*/ - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include - -#include -#include -#include "misc.h" -#include "os.h" -#include "scrnintstr.h" -#include "windowstr.h" -#include "pixmapstr.h" -#include "gc.h" -#include "extnsionst.h" -#include "dixstruct.h" -#include "resource.h" -#include "opaque.h" -#include "input.h" - -#define GLOBAL - -#include -#include -#include "xvdix.h" - -#ifdef PANORAMIX -#include "panoramiX.h" -#include "panoramiXsrv.h" -#endif -#include "xvdisp.h" - -static int XvScreenKeyIndex; -static DevPrivateKey XvScreenKey = &XvScreenKeyIndex; -unsigned long XvExtensionGeneration = 0; -unsigned long XvScreenGeneration = 0; -unsigned long XvResourceGeneration = 0; - -int XvReqCode; -int XvEventBase; -int XvErrorBase; - -unsigned long XvRTPort; -unsigned long XvRTEncoding; -unsigned long XvRTGrab; -unsigned long XvRTVideoNotify; -unsigned long XvRTVideoNotifyList; -unsigned long XvRTPortNotify; - - - -/* EXTERNAL */ - -extern XID clientErrorValue; - -static void WriteSwappedVideoNotifyEvent(xvEvent *, xvEvent *); -static void WriteSwappedPortNotifyEvent(xvEvent *, xvEvent *); -static Bool CreateResourceTypes(void); - -static Bool XvCloseScreen(int, ScreenPtr); -static Bool XvDestroyPixmap(PixmapPtr); -static Bool XvDestroyWindow(WindowPtr); -static void XvResetProc(ExtensionEntry*); -static int XvdiDestroyGrab(pointer, XID); -static int XvdiDestroyEncoding(pointer, XID); -static int XvdiDestroyVideoNotify(pointer, XID); -static int XvdiDestroyPortNotify(pointer, XID); -static int XvdiDestroyVideoNotifyList(pointer, XID); -static int XvdiDestroyPort(pointer, XID); -static int XvdiSendVideoNotify(XvPortPtr, DrawablePtr, int); - - - - -/* -** XvExtensionInit -** -** -*/ - -void -XvExtensionInit(void) -{ - ExtensionEntry *extEntry; - - /* LOOK TO SEE IF ANY SCREENS WERE INITIALIZED; IF NOT THEN - INIT GLOBAL VARIABLES SO THE EXTENSION CAN FUNCTION */ - if (XvScreenGeneration != serverGeneration) - { - if (!CreateResourceTypes()) - { - ErrorF("XvExtensionInit: Unable to allocate resource types\n"); - return; - } -#ifdef PANORAMIX - XineramaRegisterConnectionBlockCallback(XineramifyXv); -#endif - XvScreenGeneration = serverGeneration; - } - - if (XvExtensionGeneration != serverGeneration) - { - XvExtensionGeneration = serverGeneration; - - extEntry = AddExtension(XvName, XvNumEvents, XvNumErrors, - ProcXvDispatch, SProcXvDispatch, - XvResetProc, StandardMinorOpcode); - if (!extEntry) - { - FatalError("XvExtensionInit: AddExtensions failed\n"); - } - - XvReqCode = extEntry->base; - XvEventBase = extEntry->eventBase; - XvErrorBase = extEntry->errorBase; - - EventSwapVector[XvEventBase+XvVideoNotify] = - (EventSwapPtr)WriteSwappedVideoNotifyEvent; - EventSwapVector[XvEventBase+XvPortNotify] = - (EventSwapPtr)WriteSwappedPortNotifyEvent; - - (void)MakeAtom(XvName, strlen(XvName), xTrue); - - } -} - -static Bool -CreateResourceTypes(void) - -{ - - if (XvResourceGeneration == serverGeneration) return TRUE; - - XvResourceGeneration = serverGeneration; - - if (!(XvRTPort = CreateNewResourceType(XvdiDestroyPort, "XvRTPort"))) - { - ErrorF("CreateResourceTypes: failed to allocate port resource.\n"); - return FALSE; - } - - if (!(XvRTGrab = CreateNewResourceType(XvdiDestroyGrab, "XvRTGrab"))) - { - ErrorF("CreateResourceTypes: failed to allocate grab resource.\n"); - return FALSE; - } - - if (!(XvRTEncoding = CreateNewResourceType(XvdiDestroyEncoding, - "XvRTEncoding"))) - { - ErrorF("CreateResourceTypes: failed to allocate encoding resource.\n"); - return FALSE; - } - - if (!(XvRTVideoNotify = CreateNewResourceType(XvdiDestroyVideoNotify, - "XvRTVideoNotify"))) - { - ErrorF("CreateResourceTypes: failed to allocate video notify resource.\n"); - return FALSE; - } - - if (!(XvRTVideoNotifyList = CreateNewResourceType(XvdiDestroyVideoNotifyList, - "XvRTVideoNotifyList"))) - { - ErrorF("CreateResourceTypes: failed to allocate video notify list resource.\n"); - return FALSE; - } - - if (!(XvRTPortNotify = CreateNewResourceType(XvdiDestroyPortNotify, - "XvRTPortNotify"))) - { - ErrorF("CreateResourceTypes: failed to allocate port notify resource.\n"); - return FALSE; - } - - return TRUE; - -} - -int -XvScreenInit(ScreenPtr pScreen) -{ - XvScreenPtr pxvs; - - if (XvScreenGeneration != serverGeneration) - { - if (!CreateResourceTypes()) - { - ErrorF("XvScreenInit: Unable to allocate resource types\n"); - return BadAlloc; - } -#ifdef PANORAMIX - XineramaRegisterConnectionBlockCallback(XineramifyXv); -#endif - XvScreenGeneration = serverGeneration; - } - - if (dixLookupPrivate(&pScreen->devPrivates, XvScreenKey)) - { - ErrorF("XvScreenInit: screen devPrivates ptr non-NULL before init\n"); - } - - /* ALLOCATE SCREEN PRIVATE RECORD */ - - pxvs = xalloc (sizeof (XvScreenRec)); - if (!pxvs) - { - ErrorF("XvScreenInit: Unable to allocate screen private structure\n"); - return BadAlloc; - } - - dixSetPrivate(&pScreen->devPrivates, XvScreenKey, pxvs); - - - pxvs->DestroyPixmap = pScreen->DestroyPixmap; - pxvs->DestroyWindow = pScreen->DestroyWindow; - pxvs->CloseScreen = pScreen->CloseScreen; - - pScreen->DestroyPixmap = XvDestroyPixmap; - pScreen->DestroyWindow = XvDestroyWindow; - pScreen->CloseScreen = XvCloseScreen; - - return Success; -} - -static Bool -XvCloseScreen( - int ii, - ScreenPtr pScreen -){ - - XvScreenPtr pxvs; - - pxvs = (XvScreenPtr)dixLookupPrivate(&pScreen->devPrivates, XvScreenKey); - - pScreen->DestroyPixmap = pxvs->DestroyPixmap; - pScreen->DestroyWindow = pxvs->DestroyWindow; - pScreen->CloseScreen = pxvs->CloseScreen; - - (* pxvs->ddCloseScreen)(ii, pScreen); - - xfree(pxvs); - - dixSetPrivate(&pScreen->devPrivates, XvScreenKey, NULL); - - return (*pScreen->CloseScreen)(ii, pScreen); -} - -static void -XvResetProc(ExtensionEntry* extEntry) -{ - XvResetProcVector(); -} - -DevPrivateKey -XvGetScreenKey(void) -{ - return XvScreenKey; -} - -unsigned long -XvGetRTPort(void) -{ - return XvRTPort; -} - -static Bool -XvDestroyPixmap(PixmapPtr pPix) -{ - Bool status; - ScreenPtr pScreen; - XvScreenPtr pxvs; - XvAdaptorPtr pa; - int na; - XvPortPtr pp; - int np; - - pScreen = pPix->drawable.pScreen; - - SCREEN_PROLOGUE(pScreen, DestroyPixmap); - - pxvs = (XvScreenPtr)dixLookupPrivate(&pScreen->devPrivates, XvScreenKey); - - /* CHECK TO SEE IF THIS PORT IS IN USE */ - - pa = pxvs->pAdaptors; - na = pxvs->nAdaptors; - while (na--) - { - np = pa->nPorts; - pp = pa->pPorts; - - while (np--) - { - if (pp->pDraw == (DrawablePtr)pPix) - { - XvdiSendVideoNotify(pp, pp->pDraw, XvPreempted); - - (void)(* pp->pAdaptor->ddStopVideo)(NULL, pp, pp->pDraw); - - pp->pDraw = NULL; - pp->client = NULL; - pp->time = currentTime; - } - pp++; - } - pa++; - } - - status = (* pScreen->DestroyPixmap)(pPix); - - SCREEN_EPILOGUE(pScreen, DestroyPixmap, XvDestroyPixmap); - - return status; - -} - -static Bool -XvDestroyWindow(WindowPtr pWin) -{ - Bool status; - ScreenPtr pScreen; - XvScreenPtr pxvs; - XvAdaptorPtr pa; - int na; - XvPortPtr pp; - int np; - - pScreen = pWin->drawable.pScreen; - - SCREEN_PROLOGUE(pScreen, DestroyWindow); - - pxvs = (XvScreenPtr)dixLookupPrivate(&pScreen->devPrivates, XvScreenKey); - - /* CHECK TO SEE IF THIS PORT IS IN USE */ - - pa = pxvs->pAdaptors; - na = pxvs->nAdaptors; - while (na--) - { - np = pa->nPorts; - pp = pa->pPorts; - - while (np--) - { - if (pp->pDraw == (DrawablePtr)pWin) - { - XvdiSendVideoNotify(pp, pp->pDraw, XvPreempted); - - (void)(* pp->pAdaptor->ddStopVideo)(NULL, pp, pp->pDraw); - - pp->pDraw = NULL; - pp->client = NULL; - pp->time = currentTime; - } - pp++; - } - pa++; - } - - - status = (* pScreen->DestroyWindow)(pWin); - - SCREEN_EPILOGUE(pScreen, DestroyWindow, XvDestroyWindow); - - return status; - -} - -/* The XvdiVideoStopped procedure is a hook for the device dependent layer. - It provides a way for the dd layer to inform the di layer that video has - stopped in a port for reasons that the di layer had no control over; note - that it doesn't call back into the dd layer */ - -int -XvdiVideoStopped(XvPortPtr pPort, int reason) -{ - - /* IF PORT ISN'T ACTIVE THEN WE'RE DONE */ - - if (!pPort->pDraw) return Success; - - XvdiSendVideoNotify(pPort, pPort->pDraw, reason); - - pPort->pDraw = NULL; - pPort->client = NULL; - pPort->time = currentTime; - - return Success; - -} - -static int -XvdiDestroyPort(pointer pPort, XID id) -{ - return (* ((XvPortPtr)pPort)->pAdaptor->ddFreePort)(pPort); -} - -static int -XvdiDestroyGrab(pointer pGrab, XID id) -{ - ((XvGrabPtr)pGrab)->client = NULL; - return Success; -} - -static int -XvdiDestroyVideoNotify(pointer pn, XID id) -{ - /* JUST CLEAR OUT THE client POINTER FIELD */ - - ((XvVideoNotifyPtr)pn)->client = NULL; - return Success; -} - -static int -XvdiDestroyPortNotify(pointer pn, XID id) -{ - /* JUST CLEAR OUT THE client POINTER FIELD */ - - ((XvPortNotifyPtr)pn)->client = NULL; - return Success; -} - -static int -XvdiDestroyVideoNotifyList(pointer pn, XID id) -{ - XvVideoNotifyPtr npn,cpn; - - /* ACTUALLY DESTROY THE NOTITY LIST */ - - cpn = (XvVideoNotifyPtr)pn; - - while (cpn) - { - npn = cpn->next; - if (cpn->client) FreeResource(cpn->id, XvRTVideoNotify); - xfree(cpn); - cpn = npn; - } - return Success; -} - -static int -XvdiDestroyEncoding(pointer value, XID id) -{ - return Success; -} - -static int -XvdiSendVideoNotify(XvPortPtr pPort, DrawablePtr pDraw, int reason) -{ - xvEvent event; - XvVideoNotifyPtr pn; - - dixLookupResourceByType((pointer *)&pn, pDraw->id, XvRTVideoNotifyList, - serverClient, DixReadAccess); - - while (pn) - { - if (pn->client) - { - event.u.u.type = XvEventBase + XvVideoNotify; - event.u.u.sequenceNumber = pn->client->sequence; - event.u.videoNotify.time = currentTime.milliseconds; - event.u.videoNotify.drawable = pDraw->id; - event.u.videoNotify.port = pPort->id; - event.u.videoNotify.reason = reason; - TryClientEvents(pn->client, NULL, (xEventPtr)&event, 1, - NoEventMask, NoEventMask, NullGrab); - } - pn = pn->next; - } - - return Success; - -} - - -int -XvdiSendPortNotify( - XvPortPtr pPort, - Atom attribute, - INT32 value -){ - xvEvent event; - XvPortNotifyPtr pn; - - pn = pPort->pNotify; - - while (pn) - { - if (pn->client) - { - event.u.u.type = XvEventBase + XvPortNotify; - event.u.u.sequenceNumber = pn->client->sequence; - event.u.portNotify.time = currentTime.milliseconds; - event.u.portNotify.port = pPort->id; - event.u.portNotify.attribute = attribute; - event.u.portNotify.value = value; - TryClientEvents(pn->client, NULL, (xEventPtr)&event, 1, - NoEventMask, NoEventMask, NullGrab); - } - pn = pn->next; - } - - return Success; - -} - - -#define CHECK_SIZE(dw, dh, sw, sh) { \ - if(!dw || !dh || !sw || !sh) return Success; \ - /* The region code will break these if they are too large */ \ - if((dw > 32767) || (dh > 32767) || (sw > 32767) || (sh > 32767)) \ - return BadValue; \ -} - - -int -XvdiPutVideo( - ClientPtr client, - DrawablePtr pDraw, - XvPortPtr pPort, - GCPtr pGC, - INT16 vid_x, INT16 vid_y, - CARD16 vid_w, CARD16 vid_h, - INT16 drw_x, INT16 drw_y, - CARD16 drw_w, CARD16 drw_h -){ - DrawablePtr pOldDraw; - - CHECK_SIZE(drw_w, drw_h, vid_w, vid_h); - - /* UPDATE TIME VARIABLES FOR USE IN EVENTS */ - - UpdateCurrentTime(); - - /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN - INFORM CLIENT OF ITS FAILURE */ - - if (pPort->grab.client && (pPort->grab.client != client)) - { - XvdiSendVideoNotify(pPort, pDraw, XvBusy); - return Success; - } - - /* CHECK TO SEE IF PORT IS IN USE; IF SO THEN WE MUST DELIVER INTERRUPTED - EVENTS TO ANY CLIENTS WHO WANT THEM */ - - pOldDraw = pPort->pDraw; - if ((pOldDraw) && (pOldDraw != pDraw)) - { - XvdiSendVideoNotify(pPort, pPort->pDraw, XvPreempted); - } - - (void) (* pPort->pAdaptor->ddPutVideo)(client, pDraw, pPort, pGC, - vid_x, vid_y, vid_w, vid_h, - drw_x, drw_y, drw_w, drw_h); - - if ((pPort->pDraw) && (pOldDraw != pDraw)) - { - pPort->client = client; - XvdiSendVideoNotify(pPort, pPort->pDraw, XvStarted); - } - - pPort->time = currentTime; - - return (Success); - -} - -int -XvdiPutStill( - ClientPtr client, - DrawablePtr pDraw, - XvPortPtr pPort, - GCPtr pGC, - INT16 vid_x, INT16 vid_y, - CARD16 vid_w, CARD16 vid_h, - INT16 drw_x, INT16 drw_y, - CARD16 drw_w, CARD16 drw_h -){ - int status; - - CHECK_SIZE(drw_w, drw_h, vid_w, vid_h); - - /* UPDATE TIME VARIABLES FOR USE IN EVENTS */ - - UpdateCurrentTime(); - - /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN - INFORM CLIENT OF ITS FAILURE */ - - if (pPort->grab.client && (pPort->grab.client != client)) - { - XvdiSendVideoNotify(pPort, pDraw, XvBusy); - return Success; - } - - pPort->time = currentTime; - - status = (* pPort->pAdaptor->ddPutStill)(client, pDraw, pPort, pGC, - vid_x, vid_y, vid_w, vid_h, - drw_x, drw_y, drw_w, drw_h); - - return status; - -} - -int -XvdiPutImage( - ClientPtr client, - DrawablePtr pDraw, - XvPortPtr pPort, - GCPtr pGC, - INT16 src_x, INT16 src_y, - CARD16 src_w, CARD16 src_h, - INT16 drw_x, INT16 drw_y, - CARD16 drw_w, CARD16 drw_h, - XvImagePtr image, - unsigned char* data, - Bool sync, - CARD16 width, CARD16 height -){ - CHECK_SIZE(drw_w, drw_h, src_w, src_h); - - /* UPDATE TIME VARIABLES FOR USE IN EVENTS */ - - UpdateCurrentTime(); - - /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN - INFORM CLIENT OF ITS FAILURE */ - - if (pPort->grab.client && (pPort->grab.client != client)) - { - XvdiSendVideoNotify(pPort, pDraw, XvBusy); - return Success; - } - - pPort->time = currentTime; - - return (* pPort->pAdaptor->ddPutImage)(client, pDraw, pPort, pGC, - src_x, src_y, src_w, src_h, - drw_x, drw_y, drw_w, drw_h, - image, data, sync, width, height); -} - - -int -XvdiGetVideo( - ClientPtr client, - DrawablePtr pDraw, - XvPortPtr pPort, - GCPtr pGC, - INT16 vid_x, INT16 vid_y, - CARD16 vid_w, CARD16 vid_h, - INT16 drw_x, INT16 drw_y, - CARD16 drw_w, CARD16 drw_h -){ - DrawablePtr pOldDraw; - - CHECK_SIZE(drw_w, drw_h, vid_w, vid_h); - - /* UPDATE TIME VARIABLES FOR USE IN EVENTS */ - - UpdateCurrentTime(); - - /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN - INFORM CLIENT OF ITS FAILURE */ - - if (pPort->grab.client && (pPort->grab.client != client)) - { - XvdiSendVideoNotify(pPort, pDraw, XvBusy); - return Success; - } - - /* CHECK TO SEE IF PORT IS IN USE; IF SO THEN WE MUST DELIVER INTERRUPTED - EVENTS TO ANY CLIENTS WHO WANT THEM */ - - pOldDraw = pPort->pDraw; - if ((pOldDraw) && (pOldDraw != pDraw)) - { - XvdiSendVideoNotify(pPort, pPort->pDraw, XvPreempted); - } - - (void) (* pPort->pAdaptor->ddGetVideo)(client, pDraw, pPort, pGC, - vid_x, vid_y, vid_w, vid_h, - drw_x, drw_y, drw_w, drw_h); - - if ((pPort->pDraw) && (pOldDraw != pDraw)) - { - pPort->client = client; - XvdiSendVideoNotify(pPort, pPort->pDraw, XvStarted); - } - - pPort->time = currentTime; - - return (Success); - -} - -int -XvdiGetStill( - ClientPtr client, - DrawablePtr pDraw, - XvPortPtr pPort, - GCPtr pGC, - INT16 vid_x, INT16 vid_y, - CARD16 vid_w, CARD16 vid_h, - INT16 drw_x, INT16 drw_y, - CARD16 drw_w, CARD16 drw_h -){ - int status; - - CHECK_SIZE(drw_w, drw_h, vid_w, vid_h); - - /* UPDATE TIME VARIABLES FOR USE IN EVENTS */ - - UpdateCurrentTime(); - - /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN - INFORM CLIENT OF ITS FAILURE */ - - if (pPort->grab.client && (pPort->grab.client != client)) - { - XvdiSendVideoNotify(pPort, pDraw, XvBusy); - return Success; - } - - status = (* pPort->pAdaptor->ddGetStill)(client, pDraw, pPort, pGC, - vid_x, vid_y, vid_w, vid_h, - drw_x, drw_y, drw_w, drw_h); - - pPort->time = currentTime; - - return status; - -} - -int -XvdiGrabPort( - ClientPtr client, - XvPortPtr pPort, - Time ctime, - int *p_result -){ - unsigned long id; - TimeStamp time; - - UpdateCurrentTime(); - time = ClientTimeToServerTime(ctime); - - if (pPort->grab.client && (client != pPort->grab.client)) - { - *p_result = XvAlreadyGrabbed; - return Success; - } - - if ((CompareTimeStamps(time, currentTime) == LATER) || - (CompareTimeStamps(time, pPort->time) == EARLIER)) - { - *p_result = XvInvalidTime; - return Success; - } - - if (client == pPort->grab.client) - { - *p_result = Success; - return Success; - } - - id = FakeClientID(client->index); - - if (!AddResource(id, XvRTGrab, &pPort->grab)) - { - return BadAlloc; - } - - /* IF THERE IS ACTIVE VIDEO THEN STOP IT */ - - if ((pPort->pDraw) && (client != pPort->client)) - { - XvdiStopVideo(NULL, pPort, pPort->pDraw); - } - - pPort->grab.client = client; - pPort->grab.id = id; - - pPort->time = currentTime; - - *p_result = Success; - - return Success; - -} - -int -XvdiUngrabPort( - ClientPtr client, - XvPortPtr pPort, - Time ctime -){ - TimeStamp time; - - UpdateCurrentTime(); - time = ClientTimeToServerTime(ctime); - - if ((!pPort->grab.client) || (client != pPort->grab.client)) - { - return Success; - } - - if ((CompareTimeStamps(time, currentTime) == LATER) || - (CompareTimeStamps(time, pPort->time) == EARLIER)) - { - return Success; - } - - /* FREE THE GRAB RESOURCE; AND SET THE GRAB CLIENT TO NULL */ - - FreeResource(pPort->grab.id, XvRTGrab); - pPort->grab.client = NULL; - - pPort->time = currentTime; - - return Success; - -} - - -int -XvdiSelectVideoNotify( - ClientPtr client, - DrawablePtr pDraw, - BOOL onoff -){ - XvVideoNotifyPtr pn,tpn,fpn; - int rc; - - /* FIND VideoNotify LIST */ - - rc = dixLookupResourceByType((pointer *)&pn, pDraw->id, XvRTVideoNotifyList, - client, DixWriteAccess); - if (rc != Success && rc != BadValue) - return rc; - - /* IF ONE DONES'T EXIST AND NO MASK, THEN JUST RETURN */ - - if (!onoff && !pn) return Success; - - /* IF ONE DOESN'T EXIST CREATE IT AND ADD A RESOURCE SO THAT THE LIST - WILL BE DELETED WHEN THE DRAWABLE IS DESTROYED */ - - if (!pn) - { - if (!(tpn = xalloc(sizeof(XvVideoNotifyRec)))) - return BadAlloc; - tpn->next = NULL; - if (!AddResource(pDraw->id, XvRTVideoNotifyList, tpn)) - { - xfree(tpn); - return BadAlloc; - } - } - else - { - /* LOOK TO SEE IF ENTRY ALREADY EXISTS */ - - fpn = NULL; - tpn = pn; - while (tpn) - { - if (tpn->client == client) - { - if (!onoff) tpn->client = NULL; - return Success; - } - if (!tpn->client) fpn = tpn; /* TAKE NOTE OF FREE ENTRY */ - tpn = tpn->next; - } - - /* IF TUNNING OFF, THEN JUST RETURN */ - - if (!onoff) return Success; - - /* IF ONE ISN'T FOUND THEN ALLOCATE ONE AND LINK IT INTO THE LIST */ - - if (fpn) - { - tpn = fpn; - } - else - { - if (!(tpn = xalloc(sizeof(XvVideoNotifyRec)))) - return BadAlloc; - tpn->next = pn->next; - pn->next = tpn; - } - } - - /* INIT CLIENT PTR IN CASE WE CAN'T ADD RESOURCE */ - /* ADD RESOURCE SO THAT IF CLIENT EXITS THE CLIENT PTR WILL BE CLEARED */ - - tpn->client = NULL; - tpn->id = FakeClientID(client->index); - AddResource(tpn->id, XvRTVideoNotify, tpn); - - tpn->client = client; - return Success; - -} - -int -XvdiSelectPortNotify( - ClientPtr client, - XvPortPtr pPort, - BOOL onoff -){ - XvPortNotifyPtr pn,tpn; - - /* SEE IF CLIENT IS ALREADY IN LIST */ - - tpn = NULL; - pn = pPort->pNotify; - while (pn) - { - if (!pn->client) tpn = pn; /* TAKE NOTE OF FREE ENTRY */ - if (pn->client == client) break; - pn = pn->next; - } - - /* IS THE CLIENT ALREADY ON THE LIST? */ - - if (pn) - { - /* REMOVE IT? */ - - if (!onoff) - { - pn->client = NULL; - FreeResource(pn->id, XvRTPortNotify); - } - - return Success; - } - - /* DIDN'T FIND IT; SO REUSE LIST ELEMENT IF ONE IS FREE OTHERWISE - CREATE A NEW ONE AND ADD IT TO THE BEGINNING OF THE LIST */ - - if (!tpn) - { - if (!(tpn = xalloc(sizeof(XvPortNotifyRec)))) - return BadAlloc; - tpn->next = pPort->pNotify; - pPort->pNotify = tpn; - } - - tpn->client = client; - tpn->id = FakeClientID(client->index); - AddResource(tpn->id, XvRTPortNotify, tpn); - - return Success; - -} - -int -XvdiStopVideo( - ClientPtr client, - XvPortPtr pPort, - DrawablePtr pDraw -){ - int status; - - /* IF PORT ISN'T ACTIVE THEN WE'RE DONE */ - - if (!pPort->pDraw || (pPort->pDraw != pDraw)) - { - XvdiSendVideoNotify(pPort, pDraw, XvStopped); - return Success; - } - - /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN - INFORM CLIENT OF ITS FAILURE */ - - if ((client) && (pPort->grab.client) && (pPort->grab.client != client)) - { - XvdiSendVideoNotify(pPort, pDraw, XvBusy); - return Success; - } - - XvdiSendVideoNotify(pPort, pDraw, XvStopped); - - status = (* pPort->pAdaptor->ddStopVideo)(client, pPort, pDraw); - - pPort->pDraw = NULL; - pPort->client = (ClientPtr)client; - pPort->time = currentTime; - - return status; - -} - -int -XvdiPreemptVideo( - ClientPtr client, - XvPortPtr pPort, - DrawablePtr pDraw -){ - int status; - - /* IF PORT ISN'T ACTIVE THEN WE'RE DONE */ - - if (!pPort->pDraw || (pPort->pDraw != pDraw)) return Success; - - XvdiSendVideoNotify(pPort, pPort->pDraw, XvPreempted); - - status = (* pPort->pAdaptor->ddStopVideo)(client, pPort, pPort->pDraw); - - pPort->pDraw = NULL; - pPort->client = (ClientPtr)client; - pPort->time = currentTime; - - return status; - -} - -int -XvdiMatchPort( - XvPortPtr pPort, - DrawablePtr pDraw -){ - - XvAdaptorPtr pa; - XvFormatPtr pf; - int nf; - - pa = pPort->pAdaptor; - - if (pa->pScreen != pDraw->pScreen) return BadMatch; - - nf = pa->nFormats; - pf = pa->pFormats; - - while (nf--) - { - if ((pf->depth == pDraw->depth) -#if 0 - && ((pDraw->type == DRAWABLE_PIXMAP) || - (wVisual(((WindowPtr)pDraw)) == pf->visual)) -#endif - ) - return Success; - pf++; - } - - return BadMatch; - -} - -int -XvdiSetPortAttribute( - ClientPtr client, - XvPortPtr pPort, - Atom attribute, - INT32 value -){ - - XvdiSendPortNotify(pPort, attribute, value); - - return - (* pPort->pAdaptor->ddSetPortAttribute)(client, pPort, attribute, value); - -} - -int -XvdiGetPortAttribute( - ClientPtr client, - XvPortPtr pPort, - Atom attribute, - INT32 *p_value -){ - - return - (* pPort->pAdaptor->ddGetPortAttribute)(client, pPort, attribute, p_value); - -} - -static void -WriteSwappedVideoNotifyEvent(xvEvent *from, xvEvent *to) - -{ - - to->u.u.type = from->u.u.type; - to->u.u.detail = from->u.u.detail; - cpswaps(from->u.videoNotify.sequenceNumber, - to->u.videoNotify.sequenceNumber); - cpswapl(from->u.videoNotify.time, to->u.videoNotify.time); - cpswapl(from->u.videoNotify.drawable, to->u.videoNotify.drawable); - cpswapl(from->u.videoNotify.port, to->u.videoNotify.port); - -} - -static void -WriteSwappedPortNotifyEvent(xvEvent *from, xvEvent *to) - -{ - - to->u.u.type = from->u.u.type; - to->u.u.detail = from->u.u.detail; - cpswaps(from->u.portNotify.sequenceNumber, to->u.portNotify.sequenceNumber); - cpswapl(from->u.portNotify.time, to->u.portNotify.time); - cpswapl(from->u.portNotify.port, to->u.portNotify.port); - cpswapl(from->u.portNotify.value, to->u.portNotify.value); - -} +/*********************************************************** +Copyright 1991 by Digital Equipment Corporation, Maynard, Massachusetts, +and the Massachusetts Institute of Technology, Cambridge, 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 names of Digital or MIT 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. + +******************************************************************/ + +/* +** File: +** +** xvmain.c --- Xv server extension main device independent module. +** +** Author: +** +** David Carver (Digital Workstation Engineering/Project Athena) +** +** Revisions: +** +** 04.09.91 Carver +** - change: stop video always generates an event even when video +** wasn't active +** +** 29.08.91 Carver +** - change: unrealizing windows no longer preempts video +** +** 11.06.91 Carver +** - changed SetPortControl to SetPortAttribute +** - changed GetPortControl to GetPortAttribute +** - changed QueryBestSize +** +** 28.05.91 Carver +** - fixed Put and Get requests to not preempt operations to same drawable +** +** 15.05.91 Carver +** - version 2.0 upgrade +** +** 19.03.91 Carver +** - fixed Put and Get requests to honor grabbed ports. +** - fixed Video requests to update di structure with new drawable, and +** client after calling ddx. +** +** 24.01.91 Carver +** - version 1.4 upgrade +** +** Notes: +** +** Port structures reference client structures in a two different +** ways: when grabs, or video is active. Each reference is encoded +** as fake client resources and thus when the client is goes away so +** does the reference (it is zeroed). No other action is taken, so +** video doesn't necessarily stop. It probably will as a result of +** other resources going away, but if a client starts video using +** none of its own resources, then the video will continue to play +** after the client disappears. +** +** +*/ + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include + +#include +#include +#include "misc.h" +#include "os.h" +#include "scrnintstr.h" +#include "windowstr.h" +#include "pixmapstr.h" +#include "gc.h" +#include "extnsionst.h" +#include "dixstruct.h" +#include "resource.h" +#include "opaque.h" +#include "input.h" + +#define GLOBAL + +#include +#include +#include "xvdix.h" + +#ifdef PANORAMIX +#include "panoramiX.h" +#include "panoramiXsrv.h" +#endif +#include "xvdisp.h" + +static int XvScreenKeyIndex; +static DevPrivateKey XvScreenKey = &XvScreenKeyIndex; +unsigned long XvExtensionGeneration = 0; +unsigned long XvScreenGeneration = 0; +unsigned long XvResourceGeneration = 0; + +int XvReqCode; +int XvEventBase; +int XvErrorBase; + +unsigned long XvRTPort; +unsigned long XvRTEncoding; +unsigned long XvRTGrab; +unsigned long XvRTVideoNotify; +unsigned long XvRTVideoNotifyList; +unsigned long XvRTPortNotify; + + + +/* EXTERNAL */ + +static void WriteSwappedVideoNotifyEvent(xvEvent *, xvEvent *); +static void WriteSwappedPortNotifyEvent(xvEvent *, xvEvent *); +static Bool CreateResourceTypes(void); + +static Bool XvCloseScreen(int, ScreenPtr); +static Bool XvDestroyPixmap(PixmapPtr); +static Bool XvDestroyWindow(WindowPtr); +static void XvResetProc(ExtensionEntry*); +static int XvdiDestroyGrab(pointer, XID); +static int XvdiDestroyEncoding(pointer, XID); +static int XvdiDestroyVideoNotify(pointer, XID); +static int XvdiDestroyPortNotify(pointer, XID); +static int XvdiDestroyVideoNotifyList(pointer, XID); +static int XvdiDestroyPort(pointer, XID); +static int XvdiSendVideoNotify(XvPortPtr, DrawablePtr, int); + + + + +/* +** XvExtensionInit +** +** +*/ + +void +XvExtensionInit(void) +{ + ExtensionEntry *extEntry; + + /* LOOK TO SEE IF ANY SCREENS WERE INITIALIZED; IF NOT THEN + INIT GLOBAL VARIABLES SO THE EXTENSION CAN FUNCTION */ + if (XvScreenGeneration != serverGeneration) + { + if (!CreateResourceTypes()) + { + ErrorF("XvExtensionInit: Unable to allocate resource types\n"); + return; + } +#ifdef PANORAMIX + XineramaRegisterConnectionBlockCallback(XineramifyXv); +#endif + XvScreenGeneration = serverGeneration; + } + + if (XvExtensionGeneration != serverGeneration) + { + XvExtensionGeneration = serverGeneration; + + extEntry = AddExtension(XvName, XvNumEvents, XvNumErrors, + ProcXvDispatch, SProcXvDispatch, + XvResetProc, StandardMinorOpcode); + if (!extEntry) + { + FatalError("XvExtensionInit: AddExtensions failed\n"); + } + + XvReqCode = extEntry->base; + XvEventBase = extEntry->eventBase; + XvErrorBase = extEntry->errorBase; + + EventSwapVector[XvEventBase+XvVideoNotify] = + (EventSwapPtr)WriteSwappedVideoNotifyEvent; + EventSwapVector[XvEventBase+XvPortNotify] = + (EventSwapPtr)WriteSwappedPortNotifyEvent; + + (void)MakeAtom(XvName, strlen(XvName), xTrue); + + } +} + +static Bool +CreateResourceTypes(void) + +{ + + if (XvResourceGeneration == serverGeneration) return TRUE; + + XvResourceGeneration = serverGeneration; + + if (!(XvRTPort = CreateNewResourceType(XvdiDestroyPort, "XvRTPort"))) + { + ErrorF("CreateResourceTypes: failed to allocate port resource.\n"); + return FALSE; + } + + if (!(XvRTGrab = CreateNewResourceType(XvdiDestroyGrab, "XvRTGrab"))) + { + ErrorF("CreateResourceTypes: failed to allocate grab resource.\n"); + return FALSE; + } + + if (!(XvRTEncoding = CreateNewResourceType(XvdiDestroyEncoding, + "XvRTEncoding"))) + { + ErrorF("CreateResourceTypes: failed to allocate encoding resource.\n"); + return FALSE; + } + + if (!(XvRTVideoNotify = CreateNewResourceType(XvdiDestroyVideoNotify, + "XvRTVideoNotify"))) + { + ErrorF("CreateResourceTypes: failed to allocate video notify resource.\n"); + return FALSE; + } + + if (!(XvRTVideoNotifyList = CreateNewResourceType(XvdiDestroyVideoNotifyList, + "XvRTVideoNotifyList"))) + { + ErrorF("CreateResourceTypes: failed to allocate video notify list resource.\n"); + return FALSE; + } + + if (!(XvRTPortNotify = CreateNewResourceType(XvdiDestroyPortNotify, + "XvRTPortNotify"))) + { + ErrorF("CreateResourceTypes: failed to allocate port notify resource.\n"); + return FALSE; + } + + return TRUE; + +} + +int +XvScreenInit(ScreenPtr pScreen) +{ + XvScreenPtr pxvs; + + if (XvScreenGeneration != serverGeneration) + { + if (!CreateResourceTypes()) + { + ErrorF("XvScreenInit: Unable to allocate resource types\n"); + return BadAlloc; + } +#ifdef PANORAMIX + XineramaRegisterConnectionBlockCallback(XineramifyXv); +#endif + XvScreenGeneration = serverGeneration; + } + + if (dixLookupPrivate(&pScreen->devPrivates, XvScreenKey)) + { + ErrorF("XvScreenInit: screen devPrivates ptr non-NULL before init\n"); + } + + /* ALLOCATE SCREEN PRIVATE RECORD */ + + pxvs = malloc(sizeof (XvScreenRec)); + if (!pxvs) + { + ErrorF("XvScreenInit: Unable to allocate screen private structure\n"); + return BadAlloc; + } + + dixSetPrivate(&pScreen->devPrivates, XvScreenKey, pxvs); + + + pxvs->DestroyPixmap = pScreen->DestroyPixmap; + pxvs->DestroyWindow = pScreen->DestroyWindow; + pxvs->CloseScreen = pScreen->CloseScreen; + + pScreen->DestroyPixmap = XvDestroyPixmap; + pScreen->DestroyWindow = XvDestroyWindow; + pScreen->CloseScreen = XvCloseScreen; + + return Success; +} + +static Bool +XvCloseScreen( + int ii, + ScreenPtr pScreen +){ + + XvScreenPtr pxvs; + + pxvs = (XvScreenPtr)dixLookupPrivate(&pScreen->devPrivates, XvScreenKey); + + pScreen->DestroyPixmap = pxvs->DestroyPixmap; + pScreen->DestroyWindow = pxvs->DestroyWindow; + pScreen->CloseScreen = pxvs->CloseScreen; + + (* pxvs->ddCloseScreen)(ii, pScreen); + + free(pxvs); + + dixSetPrivate(&pScreen->devPrivates, XvScreenKey, NULL); + + return (*pScreen->CloseScreen)(ii, pScreen); +} + +static void +XvResetProc(ExtensionEntry* extEntry) +{ + XvResetProcVector(); +} + +DevPrivateKey +XvGetScreenKey(void) +{ + return XvScreenKey; +} + +unsigned long +XvGetRTPort(void) +{ + return XvRTPort; +} + +static Bool +XvDestroyPixmap(PixmapPtr pPix) +{ + Bool status; + ScreenPtr pScreen; + XvScreenPtr pxvs; + XvAdaptorPtr pa; + int na; + XvPortPtr pp; + int np; + + pScreen = pPix->drawable.pScreen; + + SCREEN_PROLOGUE(pScreen, DestroyPixmap); + + pxvs = (XvScreenPtr)dixLookupPrivate(&pScreen->devPrivates, XvScreenKey); + + /* CHECK TO SEE IF THIS PORT IS IN USE */ + + pa = pxvs->pAdaptors; + na = pxvs->nAdaptors; + while (na--) + { + np = pa->nPorts; + pp = pa->pPorts; + + while (np--) + { + if (pp->pDraw == (DrawablePtr)pPix) + { + XvdiSendVideoNotify(pp, pp->pDraw, XvPreempted); + + (void)(* pp->pAdaptor->ddStopVideo)(NULL, pp, pp->pDraw); + + pp->pDraw = NULL; + pp->client = NULL; + pp->time = currentTime; + } + pp++; + } + pa++; + } + + status = (* pScreen->DestroyPixmap)(pPix); + + SCREEN_EPILOGUE(pScreen, DestroyPixmap, XvDestroyPixmap); + + return status; + +} + +static Bool +XvDestroyWindow(WindowPtr pWin) +{ + Bool status; + ScreenPtr pScreen; + XvScreenPtr pxvs; + XvAdaptorPtr pa; + int na; + XvPortPtr pp; + int np; + + pScreen = pWin->drawable.pScreen; + + SCREEN_PROLOGUE(pScreen, DestroyWindow); + + pxvs = (XvScreenPtr)dixLookupPrivate(&pScreen->devPrivates, XvScreenKey); + + /* CHECK TO SEE IF THIS PORT IS IN USE */ + + pa = pxvs->pAdaptors; + na = pxvs->nAdaptors; + while (na--) + { + np = pa->nPorts; + pp = pa->pPorts; + + while (np--) + { + if (pp->pDraw == (DrawablePtr)pWin) + { + XvdiSendVideoNotify(pp, pp->pDraw, XvPreempted); + + (void)(* pp->pAdaptor->ddStopVideo)(NULL, pp, pp->pDraw); + + pp->pDraw = NULL; + pp->client = NULL; + pp->time = currentTime; + } + pp++; + } + pa++; + } + + + status = (* pScreen->DestroyWindow)(pWin); + + SCREEN_EPILOGUE(pScreen, DestroyWindow, XvDestroyWindow); + + return status; + +} + +/* The XvdiVideoStopped procedure is a hook for the device dependent layer. + It provides a way for the dd layer to inform the di layer that video has + stopped in a port for reasons that the di layer had no control over; note + that it doesn't call back into the dd layer */ + +int +XvdiVideoStopped(XvPortPtr pPort, int reason) +{ + + /* IF PORT ISN'T ACTIVE THEN WE'RE DONE */ + + if (!pPort->pDraw) return Success; + + XvdiSendVideoNotify(pPort, pPort->pDraw, reason); + + pPort->pDraw = NULL; + pPort->client = NULL; + pPort->time = currentTime; + + return Success; + +} + +static int +XvdiDestroyPort(pointer pPort, XID id) +{ + return (* ((XvPortPtr)pPort)->pAdaptor->ddFreePort)(pPort); +} + +static int +XvdiDestroyGrab(pointer pGrab, XID id) +{ + ((XvGrabPtr)pGrab)->client = NULL; + return Success; +} + +static int +XvdiDestroyVideoNotify(pointer pn, XID id) +{ + /* JUST CLEAR OUT THE client POINTER FIELD */ + + ((XvVideoNotifyPtr)pn)->client = NULL; + return Success; +} + +static int +XvdiDestroyPortNotify(pointer pn, XID id) +{ + /* JUST CLEAR OUT THE client POINTER FIELD */ + + ((XvPortNotifyPtr)pn)->client = NULL; + return Success; +} + +static int +XvdiDestroyVideoNotifyList(pointer pn, XID id) +{ + XvVideoNotifyPtr npn,cpn; + + /* ACTUALLY DESTROY THE NOTITY LIST */ + + cpn = (XvVideoNotifyPtr)pn; + + while (cpn) + { + npn = cpn->next; + if (cpn->client) FreeResource(cpn->id, XvRTVideoNotify); + free(cpn); + cpn = npn; + } + return Success; +} + +static int +XvdiDestroyEncoding(pointer value, XID id) +{ + return Success; +} + +static int +XvdiSendVideoNotify(XvPortPtr pPort, DrawablePtr pDraw, int reason) +{ + xvEvent event; + XvVideoNotifyPtr pn; + + dixLookupResourceByType((pointer *)&pn, pDraw->id, XvRTVideoNotifyList, + serverClient, DixReadAccess); + + while (pn) + { + if (pn->client) + { + event.u.u.type = XvEventBase + XvVideoNotify; + event.u.u.sequenceNumber = pn->client->sequence; + event.u.videoNotify.time = currentTime.milliseconds; + event.u.videoNotify.drawable = pDraw->id; + event.u.videoNotify.port = pPort->id; + event.u.videoNotify.reason = reason; + TryClientEvents(pn->client, NULL, (xEventPtr)&event, 1, + NoEventMask, NoEventMask, NullGrab); + } + pn = pn->next; + } + + return Success; + +} + + +int +XvdiSendPortNotify( + XvPortPtr pPort, + Atom attribute, + INT32 value +){ + xvEvent event; + XvPortNotifyPtr pn; + + pn = pPort->pNotify; + + while (pn) + { + if (pn->client) + { + event.u.u.type = XvEventBase + XvPortNotify; + event.u.u.sequenceNumber = pn->client->sequence; + event.u.portNotify.time = currentTime.milliseconds; + event.u.portNotify.port = pPort->id; + event.u.portNotify.attribute = attribute; + event.u.portNotify.value = value; + TryClientEvents(pn->client, NULL, (xEventPtr)&event, 1, + NoEventMask, NoEventMask, NullGrab); + } + pn = pn->next; + } + + return Success; + +} + + +#define CHECK_SIZE(dw, dh, sw, sh) { \ + if(!dw || !dh || !sw || !sh) return Success; \ + /* The region code will break these if they are too large */ \ + if((dw > 32767) || (dh > 32767) || (sw > 32767) || (sh > 32767)) \ + return BadValue; \ +} + + +int +XvdiPutVideo( + ClientPtr client, + DrawablePtr pDraw, + XvPortPtr pPort, + GCPtr pGC, + INT16 vid_x, INT16 vid_y, + CARD16 vid_w, CARD16 vid_h, + INT16 drw_x, INT16 drw_y, + CARD16 drw_w, CARD16 drw_h +){ + DrawablePtr pOldDraw; + + CHECK_SIZE(drw_w, drw_h, vid_w, vid_h); + + /* UPDATE TIME VARIABLES FOR USE IN EVENTS */ + + UpdateCurrentTime(); + + /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN + INFORM CLIENT OF ITS FAILURE */ + + if (pPort->grab.client && (pPort->grab.client != client)) + { + XvdiSendVideoNotify(pPort, pDraw, XvBusy); + return Success; + } + + /* CHECK TO SEE IF PORT IS IN USE; IF SO THEN WE MUST DELIVER INTERRUPTED + EVENTS TO ANY CLIENTS WHO WANT THEM */ + + pOldDraw = pPort->pDraw; + if ((pOldDraw) && (pOldDraw != pDraw)) + { + XvdiSendVideoNotify(pPort, pPort->pDraw, XvPreempted); + } + + (void) (* pPort->pAdaptor->ddPutVideo)(client, pDraw, pPort, pGC, + vid_x, vid_y, vid_w, vid_h, + drw_x, drw_y, drw_w, drw_h); + + if ((pPort->pDraw) && (pOldDraw != pDraw)) + { + pPort->client = client; + XvdiSendVideoNotify(pPort, pPort->pDraw, XvStarted); + } + + pPort->time = currentTime; + + return (Success); + +} + +int +XvdiPutStill( + ClientPtr client, + DrawablePtr pDraw, + XvPortPtr pPort, + GCPtr pGC, + INT16 vid_x, INT16 vid_y, + CARD16 vid_w, CARD16 vid_h, + INT16 drw_x, INT16 drw_y, + CARD16 drw_w, CARD16 drw_h +){ + int status; + + CHECK_SIZE(drw_w, drw_h, vid_w, vid_h); + + /* UPDATE TIME VARIABLES FOR USE IN EVENTS */ + + UpdateCurrentTime(); + + /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN + INFORM CLIENT OF ITS FAILURE */ + + if (pPort->grab.client && (pPort->grab.client != client)) + { + XvdiSendVideoNotify(pPort, pDraw, XvBusy); + return Success; + } + + pPort->time = currentTime; + + status = (* pPort->pAdaptor->ddPutStill)(client, pDraw, pPort, pGC, + vid_x, vid_y, vid_w, vid_h, + drw_x, drw_y, drw_w, drw_h); + + return status; + +} + +int +XvdiPutImage( + ClientPtr client, + DrawablePtr pDraw, + XvPortPtr pPort, + GCPtr pGC, + INT16 src_x, INT16 src_y, + CARD16 src_w, CARD16 src_h, + INT16 drw_x, INT16 drw_y, + CARD16 drw_w, CARD16 drw_h, + XvImagePtr image, + unsigned char* data, + Bool sync, + CARD16 width, CARD16 height +){ + CHECK_SIZE(drw_w, drw_h, src_w, src_h); + + /* UPDATE TIME VARIABLES FOR USE IN EVENTS */ + + UpdateCurrentTime(); + + /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN + INFORM CLIENT OF ITS FAILURE */ + + if (pPort->grab.client && (pPort->grab.client != client)) + { + XvdiSendVideoNotify(pPort, pDraw, XvBusy); + return Success; + } + + pPort->time = currentTime; + + return (* pPort->pAdaptor->ddPutImage)(client, pDraw, pPort, pGC, + src_x, src_y, src_w, src_h, + drw_x, drw_y, drw_w, drw_h, + image, data, sync, width, height); +} + + +int +XvdiGetVideo( + ClientPtr client, + DrawablePtr pDraw, + XvPortPtr pPort, + GCPtr pGC, + INT16 vid_x, INT16 vid_y, + CARD16 vid_w, CARD16 vid_h, + INT16 drw_x, INT16 drw_y, + CARD16 drw_w, CARD16 drw_h +){ + DrawablePtr pOldDraw; + + CHECK_SIZE(drw_w, drw_h, vid_w, vid_h); + + /* UPDATE TIME VARIABLES FOR USE IN EVENTS */ + + UpdateCurrentTime(); + + /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN + INFORM CLIENT OF ITS FAILURE */ + + if (pPort->grab.client && (pPort->grab.client != client)) + { + XvdiSendVideoNotify(pPort, pDraw, XvBusy); + return Success; + } + + /* CHECK TO SEE IF PORT IS IN USE; IF SO THEN WE MUST DELIVER INTERRUPTED + EVENTS TO ANY CLIENTS WHO WANT THEM */ + + pOldDraw = pPort->pDraw; + if ((pOldDraw) && (pOldDraw != pDraw)) + { + XvdiSendVideoNotify(pPort, pPort->pDraw, XvPreempted); + } + + (void) (* pPort->pAdaptor->ddGetVideo)(client, pDraw, pPort, pGC, + vid_x, vid_y, vid_w, vid_h, + drw_x, drw_y, drw_w, drw_h); + + if ((pPort->pDraw) && (pOldDraw != pDraw)) + { + pPort->client = client; + XvdiSendVideoNotify(pPort, pPort->pDraw, XvStarted); + } + + pPort->time = currentTime; + + return (Success); + +} + +int +XvdiGetStill( + ClientPtr client, + DrawablePtr pDraw, + XvPortPtr pPort, + GCPtr pGC, + INT16 vid_x, INT16 vid_y, + CARD16 vid_w, CARD16 vid_h, + INT16 drw_x, INT16 drw_y, + CARD16 drw_w, CARD16 drw_h +){ + int status; + + CHECK_SIZE(drw_w, drw_h, vid_w, vid_h); + + /* UPDATE TIME VARIABLES FOR USE IN EVENTS */ + + UpdateCurrentTime(); + + /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN + INFORM CLIENT OF ITS FAILURE */ + + if (pPort->grab.client && (pPort->grab.client != client)) + { + XvdiSendVideoNotify(pPort, pDraw, XvBusy); + return Success; + } + + status = (* pPort->pAdaptor->ddGetStill)(client, pDraw, pPort, pGC, + vid_x, vid_y, vid_w, vid_h, + drw_x, drw_y, drw_w, drw_h); + + pPort->time = currentTime; + + return status; + +} + +int +XvdiGrabPort( + ClientPtr client, + XvPortPtr pPort, + Time ctime, + int *p_result +){ + unsigned long id; + TimeStamp time; + + UpdateCurrentTime(); + time = ClientTimeToServerTime(ctime); + + if (pPort->grab.client && (client != pPort->grab.client)) + { + *p_result = XvAlreadyGrabbed; + return Success; + } + + if ((CompareTimeStamps(time, currentTime) == LATER) || + (CompareTimeStamps(time, pPort->time) == EARLIER)) + { + *p_result = XvInvalidTime; + return Success; + } + + if (client == pPort->grab.client) + { + *p_result = Success; + return Success; + } + + id = FakeClientID(client->index); + + if (!AddResource(id, XvRTGrab, &pPort->grab)) + { + return BadAlloc; + } + + /* IF THERE IS ACTIVE VIDEO THEN STOP IT */ + + if ((pPort->pDraw) && (client != pPort->client)) + { + XvdiStopVideo(NULL, pPort, pPort->pDraw); + } + + pPort->grab.client = client; + pPort->grab.id = id; + + pPort->time = currentTime; + + *p_result = Success; + + return Success; + +} + +int +XvdiUngrabPort( + ClientPtr client, + XvPortPtr pPort, + Time ctime +){ + TimeStamp time; + + UpdateCurrentTime(); + time = ClientTimeToServerTime(ctime); + + if ((!pPort->grab.client) || (client != pPort->grab.client)) + { + return Success; + } + + if ((CompareTimeStamps(time, currentTime) == LATER) || + (CompareTimeStamps(time, pPort->time) == EARLIER)) + { + return Success; + } + + /* FREE THE GRAB RESOURCE; AND SET THE GRAB CLIENT TO NULL */ + + FreeResource(pPort->grab.id, XvRTGrab); + pPort->grab.client = NULL; + + pPort->time = currentTime; + + return Success; + +} + + +int +XvdiSelectVideoNotify( + ClientPtr client, + DrawablePtr pDraw, + BOOL onoff +){ + XvVideoNotifyPtr pn,tpn,fpn; + int rc; + + /* FIND VideoNotify LIST */ + + rc = dixLookupResourceByType((pointer *)&pn, pDraw->id, XvRTVideoNotifyList, + client, DixWriteAccess); + if (rc != Success && rc != BadValue) + return rc; + + /* IF ONE DONES'T EXIST AND NO MASK, THEN JUST RETURN */ + + if (!onoff && !pn) return Success; + + /* IF ONE DOESN'T EXIST CREATE IT AND ADD A RESOURCE SO THAT THE LIST + WILL BE DELETED WHEN THE DRAWABLE IS DESTROYED */ + + if (!pn) + { + if (!(tpn = malloc(sizeof(XvVideoNotifyRec)))) + return BadAlloc; + tpn->next = NULL; + if (!AddResource(pDraw->id, XvRTVideoNotifyList, tpn)) + { + free(tpn); + return BadAlloc; + } + } + else + { + /* LOOK TO SEE IF ENTRY ALREADY EXISTS */ + + fpn = NULL; + tpn = pn; + while (tpn) + { + if (tpn->client == client) + { + if (!onoff) tpn->client = NULL; + return Success; + } + if (!tpn->client) fpn = tpn; /* TAKE NOTE OF FREE ENTRY */ + tpn = tpn->next; + } + + /* IF TUNNING OFF, THEN JUST RETURN */ + + if (!onoff) return Success; + + /* IF ONE ISN'T FOUND THEN ALLOCATE ONE AND LINK IT INTO THE LIST */ + + if (fpn) + { + tpn = fpn; + } + else + { + if (!(tpn = malloc(sizeof(XvVideoNotifyRec)))) + return BadAlloc; + tpn->next = pn->next; + pn->next = tpn; + } + } + + /* INIT CLIENT PTR IN CASE WE CAN'T ADD RESOURCE */ + /* ADD RESOURCE SO THAT IF CLIENT EXITS THE CLIENT PTR WILL BE CLEARED */ + + tpn->client = NULL; + tpn->id = FakeClientID(client->index); + AddResource(tpn->id, XvRTVideoNotify, tpn); + + tpn->client = client; + return Success; + +} + +int +XvdiSelectPortNotify( + ClientPtr client, + XvPortPtr pPort, + BOOL onoff +){ + XvPortNotifyPtr pn,tpn; + + /* SEE IF CLIENT IS ALREADY IN LIST */ + + tpn = NULL; + pn = pPort->pNotify; + while (pn) + { + if (!pn->client) tpn = pn; /* TAKE NOTE OF FREE ENTRY */ + if (pn->client == client) break; + pn = pn->next; + } + + /* IS THE CLIENT ALREADY ON THE LIST? */ + + if (pn) + { + /* REMOVE IT? */ + + if (!onoff) + { + pn->client = NULL; + FreeResource(pn->id, XvRTPortNotify); + } + + return Success; + } + + /* DIDN'T FIND IT; SO REUSE LIST ELEMENT IF ONE IS FREE OTHERWISE + CREATE A NEW ONE AND ADD IT TO THE BEGINNING OF THE LIST */ + + if (!tpn) + { + if (!(tpn = malloc(sizeof(XvPortNotifyRec)))) + return BadAlloc; + tpn->next = pPort->pNotify; + pPort->pNotify = tpn; + } + + tpn->client = client; + tpn->id = FakeClientID(client->index); + AddResource(tpn->id, XvRTPortNotify, tpn); + + return Success; + +} + +int +XvdiStopVideo( + ClientPtr client, + XvPortPtr pPort, + DrawablePtr pDraw +){ + int status; + + /* IF PORT ISN'T ACTIVE THEN WE'RE DONE */ + + if (!pPort->pDraw || (pPort->pDraw != pDraw)) + { + XvdiSendVideoNotify(pPort, pDraw, XvStopped); + return Success; + } + + /* CHECK FOR GRAB; IF THIS CLIENT DOESN'T HAVE THE PORT GRABBED THEN + INFORM CLIENT OF ITS FAILURE */ + + if ((client) && (pPort->grab.client) && (pPort->grab.client != client)) + { + XvdiSendVideoNotify(pPort, pDraw, XvBusy); + return Success; + } + + XvdiSendVideoNotify(pPort, pDraw, XvStopped); + + status = (* pPort->pAdaptor->ddStopVideo)(client, pPort, pDraw); + + pPort->pDraw = NULL; + pPort->client = (ClientPtr)client; + pPort->time = currentTime; + + return status; + +} + +int +XvdiPreemptVideo( + ClientPtr client, + XvPortPtr pPort, + DrawablePtr pDraw +){ + int status; + + /* IF PORT ISN'T ACTIVE THEN WE'RE DONE */ + + if (!pPort->pDraw || (pPort->pDraw != pDraw)) return Success; + + XvdiSendVideoNotify(pPort, pPort->pDraw, XvPreempted); + + status = (* pPort->pAdaptor->ddStopVideo)(client, pPort, pPort->pDraw); + + pPort->pDraw = NULL; + pPort->client = (ClientPtr)client; + pPort->time = currentTime; + + return status; + +} + +int +XvdiMatchPort( + XvPortPtr pPort, + DrawablePtr pDraw +){ + + XvAdaptorPtr pa; + XvFormatPtr pf; + int nf; + + pa = pPort->pAdaptor; + + if (pa->pScreen != pDraw->pScreen) return BadMatch; + + nf = pa->nFormats; + pf = pa->pFormats; + + while (nf--) + { + if ((pf->depth == pDraw->depth) +#if 0 + && ((pDraw->type == DRAWABLE_PIXMAP) || + (wVisual(((WindowPtr)pDraw)) == pf->visual)) +#endif + ) + return Success; + pf++; + } + + return BadMatch; + +} + +int +XvdiSetPortAttribute( + ClientPtr client, + XvPortPtr pPort, + Atom attribute, + INT32 value +){ + + XvdiSendPortNotify(pPort, attribute, value); + + return + (* pPort->pAdaptor->ddSetPortAttribute)(client, pPort, attribute, value); + +} + +int +XvdiGetPortAttribute( + ClientPtr client, + XvPortPtr pPort, + Atom attribute, + INT32 *p_value +){ + + return + (* pPort->pAdaptor->ddGetPortAttribute)(client, pPort, attribute, p_value); + +} + +static void +WriteSwappedVideoNotifyEvent(xvEvent *from, xvEvent *to) + +{ + + to->u.u.type = from->u.u.type; + to->u.u.detail = from->u.u.detail; + cpswaps(from->u.videoNotify.sequenceNumber, + to->u.videoNotify.sequenceNumber); + cpswapl(from->u.videoNotify.time, to->u.videoNotify.time); + cpswapl(from->u.videoNotify.drawable, to->u.videoNotify.drawable); + cpswapl(from->u.videoNotify.port, to->u.videoNotify.port); + +} + +static void +WriteSwappedPortNotifyEvent(xvEvent *from, xvEvent *to) + +{ + + to->u.u.type = from->u.u.type; + to->u.u.detail = from->u.u.detail; + cpswaps(from->u.portNotify.sequenceNumber, to->u.portNotify.sequenceNumber); + cpswapl(from->u.portNotify.time, to->u.portNotify.time); + cpswapl(from->u.portNotify.port, to->u.portNotify.port); + cpswapl(from->u.portNotify.value, to->u.portNotify.value); + +} diff --git a/xorg-server/Xext/xvmc.c b/xorg-server/Xext/xvmc.c index c85f85eb4..18a81c76b 100644 --- a/xorg-server/Xext/xvmc.c +++ b/xorg-server/Xext/xvmc.c @@ -1,787 +1,787 @@ - -#ifdef HAVE_DIX_CONFIG_H -#include -#endif - -#include - -#include -#include -#include "misc.h" -#include "os.h" -#include "dixstruct.h" -#include "resource.h" -#include "scrnintstr.h" -#include "extnsionst.h" -#include "servermd.h" -#include -#include "xvdix.h" -#include -#include -#include -#include "xvmcext.h" -#include "protocol-versions.h" - -#ifdef HAS_XVMCSHM -#include -#include -#include -#endif /* HAS_XVMCSHM */ - - - -#define DR_CLIENT_DRIVER_NAME_SIZE 48 -#define DR_BUSID_SIZE 48 - -static int XvMCScreenKeyIndex; -static DevPrivateKey XvMCScreenKey; - -unsigned long XvMCGeneration = 0; - -int XvMCReqCode; -int XvMCEventBase; -int XvMCErrorBase; - -unsigned long XvMCRTContext; -unsigned long XvMCRTSurface; -unsigned long XvMCRTSubpicture; - -typedef struct { - int num_adaptors; - XvMCAdaptorPtr adaptors; - CloseScreenProcPtr CloseScreen; - char clientDriverName[DR_CLIENT_DRIVER_NAME_SIZE]; - char busID[DR_BUSID_SIZE]; - int major; - int minor; - int patchLevel; -} XvMCScreenRec, *XvMCScreenPtr; - -#define XVMC_GET_PRIVATE(pScreen) \ - (XvMCScreenPtr)(dixLookupPrivate(&(pScreen)->devPrivates, XvMCScreenKey)) - - -static int -XvMCDestroyContextRes(pointer data, XID id) -{ - XvMCContextPtr pContext = (XvMCContextPtr)data; - - pContext->refcnt--; - - if(!pContext->refcnt) { - XvMCScreenPtr pScreenPriv = XVMC_GET_PRIVATE(pContext->pScreen); - (*pScreenPriv->adaptors[pContext->adapt_num].DestroyContext)(pContext); - xfree(pContext); - } - - return Success; -} - -static int -XvMCDestroySurfaceRes(pointer data, XID id) -{ - XvMCSurfacePtr pSurface = (XvMCSurfacePtr)data; - XvMCContextPtr pContext = pSurface->context; - XvMCScreenPtr pScreenPriv = XVMC_GET_PRIVATE(pContext->pScreen); - - (*pScreenPriv->adaptors[pContext->adapt_num].DestroySurface)(pSurface); - xfree(pSurface); - - XvMCDestroyContextRes((pointer)pContext, pContext->context_id); - - return Success; -} - - -static int -XvMCDestroySubpictureRes(pointer data, XID id) -{ - XvMCSubpicturePtr pSubpict = (XvMCSubpicturePtr)data; - XvMCContextPtr pContext = pSubpict->context; - XvMCScreenPtr pScreenPriv = XVMC_GET_PRIVATE(pContext->pScreen); - - (*pScreenPriv->adaptors[pContext->adapt_num].DestroySubpicture)(pSubpict); - xfree(pSubpict); - - XvMCDestroyContextRes((pointer)pContext, pContext->context_id); - - return Success; -} - -static int -ProcXvMCQueryVersion(ClientPtr client) -{ - xvmcQueryVersionReply rep; - /* REQUEST(xvmcQueryVersionReq); */ - REQUEST_SIZE_MATCH(xvmcQueryVersionReq); - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.length = 0; - rep.major = SERVER_XVMC_MAJOR_VERSION; - rep.minor = SERVER_XVMC_MINOR_VERSION; - WriteToClient(client, sizeof(xvmcQueryVersionReply), (char*)&rep); - return Success; -} - - -static int -ProcXvMCListSurfaceTypes(ClientPtr client) -{ - XvPortPtr pPort; - int i; - XvMCScreenPtr pScreenPriv; - xvmcListSurfaceTypesReply rep; - xvmcSurfaceInfo info; - XvMCAdaptorPtr adaptor = NULL; - XvMCSurfaceInfoPtr surface; - REQUEST(xvmcListSurfaceTypesReq); - REQUEST_SIZE_MATCH(xvmcListSurfaceTypesReq); - - VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess); - - if(XvMCScreenKey) { /* any adaptors at all */ - ScreenPtr pScreen = pPort->pAdaptor->pScreen; - if((pScreenPriv = XVMC_GET_PRIVATE(pScreen))) { /* any this screen */ - for(i = 0; i < pScreenPriv->num_adaptors; i++) { - if(pPort->pAdaptor == pScreenPriv->adaptors[i].xv_adaptor) { - adaptor = &(pScreenPriv->adaptors[i]); - break; - } - } - } - } - - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.num = (adaptor) ? adaptor->num_surfaces : 0; - rep.length = bytes_to_int32(rep.num * sizeof(xvmcSurfaceInfo)); - - WriteToClient(client, sizeof(xvmcListSurfaceTypesReply), (char*)&rep); - - for(i = 0; i < rep.num; i++) { - surface = adaptor->surfaces[i]; - info.surface_type_id = surface->surface_type_id; - info.chroma_format = surface->chroma_format; - info.max_width = surface->max_width; - info.max_height = surface->max_height; - info.subpicture_max_width = surface->subpicture_max_width; - info.subpicture_max_height = surface->subpicture_max_height; - info.mc_type = surface->mc_type; - info.flags = surface->flags; - WriteToClient(client, sizeof(xvmcSurfaceInfo), (char*)&info); - } - - return Success; -} - -static int -ProcXvMCCreateContext(ClientPtr client) -{ - XvPortPtr pPort; - CARD32 *data = NULL; - int dwords = 0; - int i, result, adapt_num = -1; - ScreenPtr pScreen; - XvMCContextPtr pContext; - XvMCScreenPtr pScreenPriv; - XvMCAdaptorPtr adaptor = NULL; - XvMCSurfaceInfoPtr surface = NULL; - xvmcCreateContextReply rep; - REQUEST(xvmcCreateContextReq); - REQUEST_SIZE_MATCH(xvmcCreateContextReq); - - VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess); - - pScreen = pPort->pAdaptor->pScreen; - - if(XvMCScreenKey == NULL) /* no XvMC adaptors */ - return BadMatch; - - if(!(pScreenPriv = XVMC_GET_PRIVATE(pScreen))) /* none this screen */ - return BadMatch; - - for(i = 0; i < pScreenPriv->num_adaptors; i++) { - if(pPort->pAdaptor == pScreenPriv->adaptors[i].xv_adaptor) { - adaptor = &(pScreenPriv->adaptors[i]); - adapt_num = i; - break; - } - } - - if(adapt_num < 0) /* none this port */ - return BadMatch; - - for(i = 0; i < adaptor->num_surfaces; i++) { - if(adaptor->surfaces[i]->surface_type_id == stuff->surface_type_id) { - surface = adaptor->surfaces[i]; - break; - } - } - - /* adaptor doesn't support this suface_type_id */ - if(!surface) return BadMatch; - - - if((stuff->width > surface->max_width) || - (stuff->height > surface->max_height)) - return BadValue; - - if(!(pContext = xalloc(sizeof(XvMCContextRec)))) { - return BadAlloc; - } - - - pContext->pScreen = pScreen; - pContext->adapt_num = adapt_num; - pContext->context_id = stuff->context_id; - pContext->surface_type_id = stuff->surface_type_id; - pContext->width = stuff->width; - pContext->height = stuff->height; - pContext->flags = stuff->flags; - pContext->refcnt = 1; - - result = (*adaptor->CreateContext)(pPort, pContext, &dwords, &data); - - if(result != Success) { - xfree(pContext); - return result; - } - - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.width_actual = pContext->width; - rep.height_actual = pContext->height; - rep.flags_return = pContext->flags; - rep.length = dwords; - - WriteToClient(client, sizeof(xvmcCreateContextReply), (char*)&rep); - if(dwords) - WriteToClient(client, dwords << 2, (char*)data); - AddResource(pContext->context_id, XvMCRTContext, pContext); - - if(data) - xfree(data); - - return Success; -} - -static int -ProcXvMCDestroyContext(ClientPtr client) -{ - pointer val; - int rc; - REQUEST(xvmcDestroyContextReq); - REQUEST_SIZE_MATCH(xvmcDestroyContextReq); - - rc = dixLookupResourceByType(&val, stuff->context_id, XvMCRTContext, - client, DixDestroyAccess); - if (rc != Success) - return (rc == BadValue) ? XvMCBadContext + XvMCErrorBase : rc; - - FreeResource(stuff->context_id, RT_NONE); - - return Success; -} - -static int -ProcXvMCCreateSurface(ClientPtr client) -{ - CARD32 *data = NULL; - int dwords = 0; - int result; - XvMCContextPtr pContext; - XvMCSurfacePtr pSurface; - XvMCScreenPtr pScreenPriv; - xvmcCreateSurfaceReply rep; - REQUEST(xvmcCreateSurfaceReq); - REQUEST_SIZE_MATCH(xvmcCreateSurfaceReq); - - result = dixLookupResourceByType((pointer *)&pContext, stuff->context_id, - XvMCRTContext, client, DixUseAccess); - if (result != Success) - return (result == BadValue) ? XvMCBadContext + XvMCErrorBase : result; - - pScreenPriv = XVMC_GET_PRIVATE(pContext->pScreen); - - if(!(pSurface = xalloc(sizeof(XvMCSurfaceRec)))) - return BadAlloc; - - pSurface->surface_id = stuff->surface_id; - pSurface->surface_type_id = pContext->surface_type_id; - pSurface->context = pContext; - - result = (*pScreenPriv->adaptors[pContext->adapt_num].CreateSurface)( - pSurface, &dwords, &data); - - if(result != Success) { - xfree(pSurface); - return result; - } - - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.length = dwords; - - WriteToClient(client, sizeof(xvmcCreateSurfaceReply), (char*)&rep); - if(dwords) - WriteToClient(client, dwords << 2, (char*)data); - AddResource(pSurface->surface_id, XvMCRTSurface, pSurface); - - if(data) - xfree(data); - - pContext->refcnt++; - - return Success; -} - -static int -ProcXvMCDestroySurface(ClientPtr client) -{ - pointer val; - int rc; - REQUEST(xvmcDestroySurfaceReq); - REQUEST_SIZE_MATCH(xvmcDestroySurfaceReq); - - rc = dixLookupResourceByType(&val, stuff->surface_id, XvMCRTSurface, - client, DixDestroyAccess); - if (rc != Success) - return (rc == BadValue) ? XvMCBadSurface + XvMCErrorBase : rc; - - FreeResource(stuff->surface_id, RT_NONE); - - return Success; -} - -static int -ProcXvMCCreateSubpicture(ClientPtr client) -{ - Bool image_supported = FALSE; - CARD32 *data = NULL; - int i, result, dwords = 0; - XvMCContextPtr pContext; - XvMCSubpicturePtr pSubpicture; - XvMCScreenPtr pScreenPriv; - xvmcCreateSubpictureReply rep; - XvMCAdaptorPtr adaptor; - XvMCSurfaceInfoPtr surface = NULL; - REQUEST(xvmcCreateSubpictureReq); - REQUEST_SIZE_MATCH(xvmcCreateSubpictureReq); - - result = dixLookupResourceByType((pointer *)&pContext, stuff->context_id, - XvMCRTContext, client, DixUseAccess); - if (result != Success) - return (result == BadValue) ? XvMCBadContext + XvMCErrorBase : result; - - pScreenPriv = XVMC_GET_PRIVATE(pContext->pScreen); - - adaptor = &(pScreenPriv->adaptors[pContext->adapt_num]); - - /* find which surface this context supports */ - for(i = 0; i < adaptor->num_surfaces; i++) { - if(adaptor->surfaces[i]->surface_type_id == pContext->surface_type_id){ - surface = adaptor->surfaces[i]; - break; - } - } - - if(!surface) return BadMatch; - - /* make sure this surface supports that xvimage format */ - if(!surface->compatible_subpictures) return BadMatch; - - for(i = 0; i < surface->compatible_subpictures->num_xvimages; i++) { - if(surface->compatible_subpictures->xvimage_ids[i] == stuff->xvimage_id) { - image_supported = TRUE; - break; - } - } - - if(!image_supported) return BadMatch; - - /* make sure the size is OK */ - if((stuff->width > surface->subpicture_max_width) || - (stuff->height > surface->subpicture_max_height)) - return BadValue; - - if(!(pSubpicture = xalloc(sizeof(XvMCSubpictureRec)))) - return BadAlloc; - - pSubpicture->subpicture_id = stuff->subpicture_id; - pSubpicture->xvimage_id = stuff->xvimage_id; - pSubpicture->width = stuff->width; - pSubpicture->height = stuff->height; - pSubpicture->num_palette_entries = 0; /* overwritten by DDX */ - pSubpicture->entry_bytes = 0; /* overwritten by DDX */ - pSubpicture->component_order[0] = 0; /* overwritten by DDX */ - pSubpicture->component_order[1] = 0; - pSubpicture->component_order[2] = 0; - pSubpicture->component_order[3] = 0; - pSubpicture->context = pContext; - - result = (*pScreenPriv->adaptors[pContext->adapt_num].CreateSubpicture)( - pSubpicture, &dwords, &data); - - if(result != Success) { - xfree(pSubpicture); - return result; - } - - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.width_actual = pSubpicture->width; - rep.height_actual = pSubpicture->height; - rep.num_palette_entries = pSubpicture->num_palette_entries; - rep.entry_bytes = pSubpicture->entry_bytes; - rep.component_order[0] = pSubpicture->component_order[0]; - rep.component_order[1] = pSubpicture->component_order[1]; - rep.component_order[2] = pSubpicture->component_order[2]; - rep.component_order[3] = pSubpicture->component_order[3]; - rep.length = dwords; - - WriteToClient(client, sizeof(xvmcCreateSubpictureReply), (char*)&rep); - if(dwords) - WriteToClient(client, dwords << 2, (char*)data); - AddResource(pSubpicture->subpicture_id, XvMCRTSubpicture, pSubpicture); - - if(data) - xfree(data); - - pContext->refcnt++; - - return Success; -} - -static int -ProcXvMCDestroySubpicture(ClientPtr client) -{ - pointer val; - int rc; - REQUEST(xvmcDestroySubpictureReq); - REQUEST_SIZE_MATCH(xvmcDestroySubpictureReq); - - rc = dixLookupResourceByType(&val, stuff->subpicture_id, XvMCRTSubpicture, - client, DixDestroyAccess); - if (rc != Success) - return (rc == BadValue) ? XvMCBadSubpicture + XvMCErrorBase : rc; - - FreeResource(stuff->subpicture_id, RT_NONE); - - return Success; -} - - -static int -ProcXvMCListSubpictureTypes(ClientPtr client) -{ - XvPortPtr pPort; - xvmcListSubpictureTypesReply rep; - XvMCScreenPtr pScreenPriv; - ScreenPtr pScreen; - XvMCAdaptorPtr adaptor = NULL; - XvMCSurfaceInfoPtr surface = NULL; - xvImageFormatInfo info; - XvImagePtr pImage; - int i, j; - REQUEST(xvmcListSubpictureTypesReq); - REQUEST_SIZE_MATCH(xvmcListSubpictureTypesReq); - - VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess); - - pScreen = pPort->pAdaptor->pScreen; - - if(XvMCScreenKey == NULL) /* No XvMC adaptors */ - return BadMatch; - - if(!(pScreenPriv = XVMC_GET_PRIVATE(pScreen))) - return BadMatch; /* None this screen */ - - for(i = 0; i < pScreenPriv->num_adaptors; i++) { - if(pPort->pAdaptor == pScreenPriv->adaptors[i].xv_adaptor) { - adaptor = &(pScreenPriv->adaptors[i]); - break; - } - } - - if(!adaptor) return BadMatch; - - for(i = 0; i < adaptor->num_surfaces; i++) { - if(adaptor->surfaces[i]->surface_type_id == stuff->surface_type_id) { - surface = adaptor->surfaces[i]; - break; - } - } - - if(!surface) return BadMatch; - - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.num = 0; - if(surface->compatible_subpictures) - rep.num = surface->compatible_subpictures->num_xvimages; - - rep.length = bytes_to_int32(rep.num * sizeof(xvImageFormatInfo)); - - WriteToClient(client, sizeof(xvmcListSubpictureTypesReply), (char*)&rep); - - for(i = 0; i < rep.num; i++) { - pImage = NULL; - for(j = 0; j < adaptor->num_subpictures; j++) { - if(surface->compatible_subpictures->xvimage_ids[i] == - adaptor->subpictures[j]->id) - { - pImage = adaptor->subpictures[j]; - break; - } - } - if(!pImage) return BadImplementation; - - info.id = pImage->id; - info.type = pImage->type; - info.byte_order = pImage->byte_order; - memcpy(&info.guid, pImage->guid, 16); - info.bpp = pImage->bits_per_pixel; - info.num_planes = pImage->num_planes; - info.depth = pImage->depth; - info.red_mask = pImage->red_mask; - info.green_mask = pImage->green_mask; - info.blue_mask = pImage->blue_mask; - info.format = pImage->format; - info.y_sample_bits = pImage->y_sample_bits; - info.u_sample_bits = pImage->u_sample_bits; - info.v_sample_bits = pImage->v_sample_bits; - info.horz_y_period = pImage->horz_y_period; - info.horz_u_period = pImage->horz_u_period; - info.horz_v_period = pImage->horz_v_period; - info.vert_y_period = pImage->vert_y_period; - info.vert_u_period = pImage->vert_u_period; - info.vert_v_period = pImage->vert_v_period; - memcpy(&info.comp_order, pImage->component_order, 32); - info.scanline_order = pImage->scanline_order; - WriteToClient(client, sizeof(xvImageFormatInfo), (char*)&info); - } - - return Success; -} - -static int -ProcXvMCGetDRInfo(ClientPtr client) -{ - xvmcGetDRInfoReply rep; - XvPortPtr pPort; - ScreenPtr pScreen; - XvMCScreenPtr pScreenPriv; - -#ifdef HAS_XVMCSHM - volatile CARD32 *patternP; -#endif - - REQUEST(xvmcGetDRInfoReq); - REQUEST_SIZE_MATCH(xvmcGetDRInfoReq); - - VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess); - - pScreen = pPort->pAdaptor->pScreen; - pScreenPriv = XVMC_GET_PRIVATE(pScreen); - - rep.type = X_Reply; - rep.sequenceNumber = client->sequence; - rep.major = pScreenPriv->major; - rep.minor = pScreenPriv->minor; - rep.patchLevel = pScreenPriv->patchLevel; - rep.nameLen = bytes_to_int32(strlen(pScreenPriv->clientDriverName) + 1); - rep.busIDLen = bytes_to_int32(strlen(pScreenPriv->busID) + 1); - - rep.length = rep.nameLen + rep.busIDLen; - rep.nameLen <<=2; - rep.busIDLen <<=2; - - /* - * Read back to the client what she has put in the shared memory - * segment she prepared for us. - */ - - rep.isLocal = 1; -#ifdef HAS_XVMCSHM - patternP = (CARD32 *)shmat( stuff->shmKey, NULL, SHM_RDONLY ); - if ( -1 != (long) patternP) { - volatile CARD32 *patternC = patternP; - int i; - CARD32 magic = stuff->magic; - - rep.isLocal = 1; - i = 1024 / sizeof(CARD32); - - while ( i-- ) { - if (*patternC++ != magic) { - rep.isLocal = 0; - break; - } - magic = ~magic; - } - shmdt( (char *)patternP ); - } -#endif /* HAS_XVMCSHM */ - - WriteToClient(client, sizeof(xvmcGetDRInfoReply), - (char*)&rep); - if (rep.length) { - WriteToClient(client, rep.nameLen, - pScreenPriv->clientDriverName); - WriteToClient(client, rep.busIDLen, - pScreenPriv->busID); - } - return Success; -} - - -int (*ProcXvMCVector[xvmcNumRequest])(ClientPtr) = { - ProcXvMCQueryVersion, - ProcXvMCListSurfaceTypes, - ProcXvMCCreateContext, - ProcXvMCDestroyContext, - ProcXvMCCreateSurface, - ProcXvMCDestroySurface, - ProcXvMCCreateSubpicture, - ProcXvMCDestroySubpicture, - ProcXvMCListSubpictureTypes, - ProcXvMCGetDRInfo -}; - -static int -ProcXvMCDispatch (ClientPtr client) -{ - REQUEST(xReq); - - if(stuff->data < xvmcNumRequest) - return (*ProcXvMCVector[stuff->data])(client); - else - return BadRequest; -} - -static int -SProcXvMCDispatch (ClientPtr client) -{ - /* We only support local */ - return BadImplementation; -} - -void -XvMCExtensionInit(void) -{ - ExtensionEntry *extEntry; - - if(XvMCScreenKey == NULL) /* nobody supports it */ - return; - - if(!(XvMCRTContext = CreateNewResourceType(XvMCDestroyContextRes, - "XvMCRTContext"))) - return; - - if(!(XvMCRTSurface = CreateNewResourceType(XvMCDestroySurfaceRes, - "XvMCRTSurface"))) - return; - - if(!(XvMCRTSubpicture = CreateNewResourceType(XvMCDestroySubpictureRes, - "XvMCRTSubpicture"))) - return; - - extEntry = AddExtension(XvMCName, XvMCNumEvents, XvMCNumErrors, - ProcXvMCDispatch, SProcXvMCDispatch, - NULL, StandardMinorOpcode); - - if(!extEntry) return; - - XvMCReqCode = extEntry->base; - XvMCEventBase = extEntry->eventBase; - XvMCErrorBase = extEntry->errorBase; -} - -static Bool -XvMCCloseScreen (int i, ScreenPtr pScreen) -{ - XvMCScreenPtr pScreenPriv = XVMC_GET_PRIVATE(pScreen); - - pScreen->CloseScreen = pScreenPriv->CloseScreen; - - xfree(pScreenPriv); - - return (*pScreen->CloseScreen)(i, pScreen); -} - - -int -XvMCScreenInit(ScreenPtr pScreen, int num, XvMCAdaptorPtr pAdapt) -{ - XvMCScreenPtr pScreenPriv; - - XvMCScreenKey = &XvMCScreenKeyIndex; - - if(!(pScreenPriv = xalloc(sizeof(XvMCScreenRec)))) - return BadAlloc; - - dixSetPrivate(&pScreen->devPrivates, XvMCScreenKey, pScreenPriv); - - pScreenPriv->CloseScreen = pScreen->CloseScreen; - pScreen->CloseScreen = XvMCCloseScreen; - - pScreenPriv->num_adaptors = num; - pScreenPriv->adaptors = pAdapt; - pScreenPriv->clientDriverName[0] = 0; - pScreenPriv->busID[0] = 0; - pScreenPriv->major = 0; - pScreenPriv->minor = 0; - pScreenPriv->patchLevel = 0; - - return Success; -} - -XvImagePtr XvMCFindXvImage(XvPortPtr pPort, CARD32 id) -{ - XvImagePtr pImage = NULL; - ScreenPtr pScreen = pPort->pAdaptor->pScreen; - XvMCScreenPtr pScreenPriv; - XvMCAdaptorPtr adaptor = NULL; - int i; - - if(XvMCScreenKey == NULL) return NULL; - - if(!(pScreenPriv = XVMC_GET_PRIVATE(pScreen))) - return NULL; - - for(i = 0; i < pScreenPriv->num_adaptors; i++) { - if(pPort->pAdaptor == pScreenPriv->adaptors[i].xv_adaptor) { - adaptor = &(pScreenPriv->adaptors[i]); - break; - } - } - - if(!adaptor) return NULL; - - for(i = 0; i < adaptor->num_subpictures; i++) { - if(adaptor->subpictures[i]->id == id) { - pImage = adaptor->subpictures[i]; - break; - } - } - - return pImage; -} - -int -xf86XvMCRegisterDRInfo(ScreenPtr pScreen, char *name, - char *busID, int major, int minor, - int patchLevel) -{ - XvMCScreenPtr pScreenPriv = XVMC_GET_PRIVATE(pScreen); - strncpy(pScreenPriv->clientDriverName, name, - DR_CLIENT_DRIVER_NAME_SIZE); - strncpy(pScreenPriv->busID, busID, DR_BUSID_SIZE); - pScreenPriv->major = major; - pScreenPriv->minor = minor; - pScreenPriv->patchLevel = patchLevel; - pScreenPriv->clientDriverName[DR_CLIENT_DRIVER_NAME_SIZE-1] = 0; - pScreenPriv->busID[DR_BUSID_SIZE-1] = 0; - return Success; -} - + +#ifdef HAVE_DIX_CONFIG_H +#include +#endif + +#include + +#include +#include +#include "misc.h" +#include "os.h" +#include "dixstruct.h" +#include "resource.h" +#include "scrnintstr.h" +#include "extnsionst.h" +#include "servermd.h" +#include +#include "xvdix.h" +#include +#include +#include +#include "xvmcext.h" +#include "protocol-versions.h" + +#ifdef HAS_XVMCSHM +#include +#include +#include +#endif /* HAS_XVMCSHM */ + + + +#define DR_CLIENT_DRIVER_NAME_SIZE 48 +#define DR_BUSID_SIZE 48 + +static int XvMCScreenKeyIndex; +static DevPrivateKey XvMCScreenKey; + +unsigned long XvMCGeneration = 0; + +int XvMCReqCode; +int XvMCEventBase; +int XvMCErrorBase; + +unsigned long XvMCRTContext; +unsigned long XvMCRTSurface; +unsigned long XvMCRTSubpicture; + +typedef struct { + int num_adaptors; + XvMCAdaptorPtr adaptors; + CloseScreenProcPtr CloseScreen; + char clientDriverName[DR_CLIENT_DRIVER_NAME_SIZE]; + char busID[DR_BUSID_SIZE]; + int major; + int minor; + int patchLevel; +} XvMCScreenRec, *XvMCScreenPtr; + +#define XVMC_GET_PRIVATE(pScreen) \ + (XvMCScreenPtr)(dixLookupPrivate(&(pScreen)->devPrivates, XvMCScreenKey)) + + +static int +XvMCDestroyContextRes(pointer data, XID id) +{ + XvMCContextPtr pContext = (XvMCContextPtr)data; + + pContext->refcnt--; + + if(!pContext->refcnt) { + XvMCScreenPtr pScreenPriv = XVMC_GET_PRIVATE(pContext->pScreen); + (*pScreenPriv->adaptors[pContext->adapt_num].DestroyContext)(pContext); + free(pContext); + } + + return Success; +} + +static int +XvMCDestroySurfaceRes(pointer data, XID id) +{ + XvMCSurfacePtr pSurface = (XvMCSurfacePtr)data; + XvMCContextPtr pContext = pSurface->context; + XvMCScreenPtr pScreenPriv = XVMC_GET_PRIVATE(pContext->pScreen); + + (*pScreenPriv->adaptors[pContext->adapt_num].DestroySurface)(pSurface); + free(pSurface); + + XvMCDestroyContextRes((pointer)pContext, pContext->context_id); + + return Success; +} + + +static int +XvMCDestroySubpictureRes(pointer data, XID id) +{ + XvMCSubpicturePtr pSubpict = (XvMCSubpicturePtr)data; + XvMCContextPtr pContext = pSubpict->context; + XvMCScreenPtr pScreenPriv = XVMC_GET_PRIVATE(pContext->pScreen); + + (*pScreenPriv->adaptors[pContext->adapt_num].DestroySubpicture)(pSubpict); + free(pSubpict); + + XvMCDestroyContextRes((pointer)pContext, pContext->context_id); + + return Success; +} + +static int +ProcXvMCQueryVersion(ClientPtr client) +{ + xvmcQueryVersionReply rep; + /* REQUEST(xvmcQueryVersionReq); */ + REQUEST_SIZE_MATCH(xvmcQueryVersionReq); + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = 0; + rep.major = SERVER_XVMC_MAJOR_VERSION; + rep.minor = SERVER_XVMC_MINOR_VERSION; + WriteToClient(client, sizeof(xvmcQueryVersionReply), (char*)&rep); + return Success; +} + + +static int +ProcXvMCListSurfaceTypes(ClientPtr client) +{ + XvPortPtr pPort; + int i; + XvMCScreenPtr pScreenPriv; + xvmcListSurfaceTypesReply rep; + xvmcSurfaceInfo info; + XvMCAdaptorPtr adaptor = NULL; + XvMCSurfaceInfoPtr surface; + REQUEST(xvmcListSurfaceTypesReq); + REQUEST_SIZE_MATCH(xvmcListSurfaceTypesReq); + + VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess); + + if(XvMCScreenKey) { /* any adaptors at all */ + ScreenPtr pScreen = pPort->pAdaptor->pScreen; + if((pScreenPriv = XVMC_GET_PRIVATE(pScreen))) { /* any this screen */ + for(i = 0; i < pScreenPriv->num_adaptors; i++) { + if(pPort->pAdaptor == pScreenPriv->adaptors[i].xv_adaptor) { + adaptor = &(pScreenPriv->adaptors[i]); + break; + } + } + } + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.num = (adaptor) ? adaptor->num_surfaces : 0; + rep.length = bytes_to_int32(rep.num * sizeof(xvmcSurfaceInfo)); + + WriteToClient(client, sizeof(xvmcListSurfaceTypesReply), (char*)&rep); + + for(i = 0; i < rep.num; i++) { + surface = adaptor->surfaces[i]; + info.surface_type_id = surface->surface_type_id; + info.chroma_format = surface->chroma_format; + info.max_width = surface->max_width; + info.max_height = surface->max_height; + info.subpicture_max_width = surface->subpicture_max_width; + info.subpicture_max_height = surface->subpicture_max_height; + info.mc_type = surface->mc_type; + info.flags = surface->flags; + WriteToClient(client, sizeof(xvmcSurfaceInfo), (char*)&info); + } + + return Success; +} + +static int +ProcXvMCCreateContext(ClientPtr client) +{ + XvPortPtr pPort; + CARD32 *data = NULL; + int dwords = 0; + int i, result, adapt_num = -1; + ScreenPtr pScreen; + XvMCContextPtr pContext; + XvMCScreenPtr pScreenPriv; + XvMCAdaptorPtr adaptor = NULL; + XvMCSurfaceInfoPtr surface = NULL; + xvmcCreateContextReply rep; + REQUEST(xvmcCreateContextReq); + REQUEST_SIZE_MATCH(xvmcCreateContextReq); + + VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess); + + pScreen = pPort->pAdaptor->pScreen; + + if(XvMCScreenKey == NULL) /* no XvMC adaptors */ + return BadMatch; + + if(!(pScreenPriv = XVMC_GET_PRIVATE(pScreen))) /* none this screen */ + return BadMatch; + + for(i = 0; i < pScreenPriv->num_adaptors; i++) { + if(pPort->pAdaptor == pScreenPriv->adaptors[i].xv_adaptor) { + adaptor = &(pScreenPriv->adaptors[i]); + adapt_num = i; + break; + } + } + + if(adapt_num < 0) /* none this port */ + return BadMatch; + + for(i = 0; i < adaptor->num_surfaces; i++) { + if(adaptor->surfaces[i]->surface_type_id == stuff->surface_type_id) { + surface = adaptor->surfaces[i]; + break; + } + } + + /* adaptor doesn't support this suface_type_id */ + if(!surface) return BadMatch; + + + if((stuff->width > surface->max_width) || + (stuff->height > surface->max_height)) + return BadValue; + + if(!(pContext = malloc(sizeof(XvMCContextRec)))) { + return BadAlloc; + } + + + pContext->pScreen = pScreen; + pContext->adapt_num = adapt_num; + pContext->context_id = stuff->context_id; + pContext->surface_type_id = stuff->surface_type_id; + pContext->width = stuff->width; + pContext->height = stuff->height; + pContext->flags = stuff->flags; + pContext->refcnt = 1; + + result = (*adaptor->CreateContext)(pPort, pContext, &dwords, &data); + + if(result != Success) { + free(pContext); + return result; + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.width_actual = pContext->width; + rep.height_actual = pContext->height; + rep.flags_return = pContext->flags; + rep.length = dwords; + + WriteToClient(client, sizeof(xvmcCreateContextReply), (char*)&rep); + if(dwords) + WriteToClient(client, dwords << 2, (char*)data); + AddResource(pContext->context_id, XvMCRTContext, pContext); + + if(data) + free(data); + + return Success; +} + +static int +ProcXvMCDestroyContext(ClientPtr client) +{ + pointer val; + int rc; + REQUEST(xvmcDestroyContextReq); + REQUEST_SIZE_MATCH(xvmcDestroyContextReq); + + rc = dixLookupResourceByType(&val, stuff->context_id, XvMCRTContext, + client, DixDestroyAccess); + if (rc != Success) + return (rc == BadValue) ? XvMCBadContext + XvMCErrorBase : rc; + + FreeResource(stuff->context_id, RT_NONE); + + return Success; +} + +static int +ProcXvMCCreateSurface(ClientPtr client) +{ + CARD32 *data = NULL; + int dwords = 0; + int result; + XvMCContextPtr pContext; + XvMCSurfacePtr pSurface; + XvMCScreenPtr pScreenPriv; + xvmcCreateSurfaceReply rep; + REQUEST(xvmcCreateSurfaceReq); + REQUEST_SIZE_MATCH(xvmcCreateSurfaceReq); + + result = dixLookupResourceByType((pointer *)&pContext, stuff->context_id, + XvMCRTContext, client, DixUseAccess); + if (result != Success) + return (result == BadValue) ? XvMCBadContext + XvMCErrorBase : result; + + pScreenPriv = XVMC_GET_PRIVATE(pContext->pScreen); + + if(!(pSurface = malloc(sizeof(XvMCSurfaceRec)))) + return BadAlloc; + + pSurface->surface_id = stuff->surface_id; + pSurface->surface_type_id = pContext->surface_type_id; + pSurface->context = pContext; + + result = (*pScreenPriv->adaptors[pContext->adapt_num].CreateSurface)( + pSurface, &dwords, &data); + + if(result != Success) { + free(pSurface); + return result; + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.length = dwords; + + WriteToClient(client, sizeof(xvmcCreateSurfaceReply), (char*)&rep); + if(dwords) + WriteToClient(client, dwords << 2, (char*)data); + AddResource(pSurface->surface_id, XvMCRTSurface, pSurface); + + if(data) + free(data); + + pContext->refcnt++; + + return Success; +} + +static int +ProcXvMCDestroySurface(ClientPtr client) +{ + pointer val; + int rc; + REQUEST(xvmcDestroySurfaceReq); + REQUEST_SIZE_MATCH(xvmcDestroySurfaceReq); + + rc = dixLookupResourceByType(&val, stuff->surface_id, XvMCRTSurface, + client, DixDestroyAccess); + if (rc != Success) + return (rc == BadValue) ? XvMCBadSurface + XvMCErrorBase : rc; + + FreeResource(stuff->surface_id, RT_NONE); + + return Success; +} + +static int +ProcXvMCCreateSubpicture(ClientPtr client) +{ + Bool image_supported = FALSE; + CARD32 *data = NULL; + int i, result, dwords = 0; + XvMCContextPtr pContext; + XvMCSubpicturePtr pSubpicture; + XvMCScreenPtr pScreenPriv; + xvmcCreateSubpictureReply rep; + XvMCAdaptorPtr adaptor; + XvMCSurfaceInfoPtr surface = NULL; + REQUEST(xvmcCreateSubpictureReq); + REQUEST_SIZE_MATCH(xvmcCreateSubpictureReq); + + result = dixLookupResourceByType((pointer *)&pContext, stuff->context_id, + XvMCRTContext, client, DixUseAccess); + if (result != Success) + return (result == BadValue) ? XvMCBadContext + XvMCErrorBase : result; + + pScreenPriv = XVMC_GET_PRIVATE(pContext->pScreen); + + adaptor = &(pScreenPriv->adaptors[pContext->adapt_num]); + + /* find which surface this context supports */ + for(i = 0; i < adaptor->num_surfaces; i++) { + if(adaptor->surfaces[i]->surface_type_id == pContext->surface_type_id){ + surface = adaptor->surfaces[i]; + break; + } + } + + if(!surface) return BadMatch; + + /* make sure this surface supports that xvimage format */ + if(!surface->compatible_subpictures) return BadMatch; + + for(i = 0; i < surface->compatible_subpictures->num_xvimages; i++) { + if(surface->compatible_subpictures->xvimage_ids[i] == stuff->xvimage_id) { + image_supported = TRUE; + break; + } + } + + if(!image_supported) return BadMatch; + + /* make sure the size is OK */ + if((stuff->width > surface->subpicture_max_width) || + (stuff->height > surface->subpicture_max_height)) + return BadValue; + + if(!(pSubpicture = malloc(sizeof(XvMCSubpictureRec)))) + return BadAlloc; + + pSubpicture->subpicture_id = stuff->subpicture_id; + pSubpicture->xvimage_id = stuff->xvimage_id; + pSubpicture->width = stuff->width; + pSubpicture->height = stuff->height; + pSubpicture->num_palette_entries = 0; /* overwritten by DDX */ + pSubpicture->entry_bytes = 0; /* overwritten by DDX */ + pSubpicture->component_order[0] = 0; /* overwritten by DDX */ + pSubpicture->component_order[1] = 0; + pSubpicture->component_order[2] = 0; + pSubpicture->component_order[3] = 0; + pSubpicture->context = pContext; + + result = (*pScreenPriv->adaptors[pContext->adapt_num].CreateSubpicture)( + pSubpicture, &dwords, &data); + + if(result != Success) { + free(pSubpicture); + return result; + } + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.width_actual = pSubpicture->width; + rep.height_actual = pSubpicture->height; + rep.num_palette_entries = pSubpicture->num_palette_entries; + rep.entry_bytes = pSubpicture->entry_bytes; + rep.component_order[0] = pSubpicture->component_order[0]; + rep.component_order[1] = pSubpicture->component_order[1]; + rep.component_order[2] = pSubpicture->component_order[2]; + rep.component_order[3] = pSubpicture->component_order[3]; + rep.length = dwords; + + WriteToClient(client, sizeof(xvmcCreateSubpictureReply), (char*)&rep); + if(dwords) + WriteToClient(client, dwords << 2, (char*)data); + AddResource(pSubpicture->subpicture_id, XvMCRTSubpicture, pSubpicture); + + if(data) + free(data); + + pContext->refcnt++; + + return Success; +} + +static int +ProcXvMCDestroySubpicture(ClientPtr client) +{ + pointer val; + int rc; + REQUEST(xvmcDestroySubpictureReq); + REQUEST_SIZE_MATCH(xvmcDestroySubpictureReq); + + rc = dixLookupResourceByType(&val, stuff->subpicture_id, XvMCRTSubpicture, + client, DixDestroyAccess); + if (rc != Success) + return (rc == BadValue) ? XvMCBadSubpicture + XvMCErrorBase : rc; + + FreeResource(stuff->subpicture_id, RT_NONE); + + return Success; +} + + +static int +ProcXvMCListSubpictureTypes(ClientPtr client) +{ + XvPortPtr pPort; + xvmcListSubpictureTypesReply rep; + XvMCScreenPtr pScreenPriv; + ScreenPtr pScreen; + XvMCAdaptorPtr adaptor = NULL; + XvMCSurfaceInfoPtr surface = NULL; + xvImageFormatInfo info; + XvImagePtr pImage; + int i, j; + REQUEST(xvmcListSubpictureTypesReq); + REQUEST_SIZE_MATCH(xvmcListSubpictureTypesReq); + + VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess); + + pScreen = pPort->pAdaptor->pScreen; + + if(XvMCScreenKey == NULL) /* No XvMC adaptors */ + return BadMatch; + + if(!(pScreenPriv = XVMC_GET_PRIVATE(pScreen))) + return BadMatch; /* None this screen */ + + for(i = 0; i < pScreenPriv->num_adaptors; i++) { + if(pPort->pAdaptor == pScreenPriv->adaptors[i].xv_adaptor) { + adaptor = &(pScreenPriv->adaptors[i]); + break; + } + } + + if(!adaptor) return BadMatch; + + for(i = 0; i < adaptor->num_surfaces; i++) { + if(adaptor->surfaces[i]->surface_type_id == stuff->surface_type_id) { + surface = adaptor->surfaces[i]; + break; + } + } + + if(!surface) return BadMatch; + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.num = 0; + if(surface->compatible_subpictures) + rep.num = surface->compatible_subpictures->num_xvimages; + + rep.length = bytes_to_int32(rep.num * sizeof(xvImageFormatInfo)); + + WriteToClient(client, sizeof(xvmcListSubpictureTypesReply), (char*)&rep); + + for(i = 0; i < rep.num; i++) { + pImage = NULL; + for(j = 0; j < adaptor->num_subpictures; j++) { + if(surface->compatible_subpictures->xvimage_ids[i] == + adaptor->subpictures[j]->id) + { + pImage = adaptor->subpictures[j]; + break; + } + } + if(!pImage) return BadImplementation; + + info.id = pImage->id; + info.type = pImage->type; + info.byte_order = pImage->byte_order; + memcpy(&info.guid, pImage->guid, 16); + info.bpp = pImage->bits_per_pixel; + info.num_planes = pImage->num_planes; + info.depth = pImage->depth; + info.red_mask = pImage->red_mask; + info.green_mask = pImage->green_mask; + info.blue_mask = pImage->blue_mask; + info.format = pImage->format; + info.y_sample_bits = pImage->y_sample_bits; + info.u_sample_bits = pImage->u_sample_bits; + info.v_sample_bits = pImage->v_sample_bits; + info.horz_y_period = pImage->horz_y_period; + info.horz_u_period = pImage->horz_u_period; + info.horz_v_period = pImage->horz_v_period; + info.vert_y_period = pImage->vert_y_period; + info.vert_u_period = pImage->vert_u_period; + info.vert_v_period = pImage->vert_v_period; + memcpy(&info.comp_order, pImage->component_order, 32); + info.scanline_order = pImage->scanline_order; + WriteToClient(client, sizeof(xvImageFormatInfo), (char*)&info); + } + + return Success; +} + +static int +ProcXvMCGetDRInfo(ClientPtr client) +{ + xvmcGetDRInfoReply rep; + XvPortPtr pPort; + ScreenPtr pScreen; + XvMCScreenPtr pScreenPriv; + +#ifdef HAS_XVMCSHM + volatile CARD32 *patternP; +#endif + + REQUEST(xvmcGetDRInfoReq); + REQUEST_SIZE_MATCH(xvmcGetDRInfoReq); + + VALIDATE_XV_PORT(stuff->port, pPort, DixReadAccess); + + pScreen = pPort->pAdaptor->pScreen; + pScreenPriv = XVMC_GET_PRIVATE(pScreen); + + rep.type = X_Reply; + rep.sequenceNumber = client->sequence; + rep.major = pScreenPriv->major; + rep.minor = pScreenPriv->minor; + rep.patchLevel = pScreenPriv->patchLevel; + rep.nameLen = bytes_to_int32(strlen(pScreenPriv->clientDriverName) + 1); + rep.busIDLen = bytes_to_int32(strlen(pScreenPriv->busID) + 1); + + rep.length = rep.nameLen + rep.busIDLen; + rep.nameLen <<=2; + rep.busIDLen <<=2; + + /* + * Read back to the client what she has put in the shared memory + * segment she prepared for us. + */ + + rep.isLocal = 1; +#ifdef HAS_XVMCSHM + patternP = (CARD32 *)shmat( stuff->shmKey, NULL, SHM_RDONLY ); + if ( -1 != (long) patternP) { + volatile CARD32 *patternC = patternP; + int i; + CARD32 magic = stuff->magic; + + rep.isLocal = 1; + i = 1024 / sizeof(CARD32); + + while ( i-- ) { + if (*patternC++ != magic) { + rep.isLocal = 0; + break; + } + magic = ~magic; + } + shmdt( (char *)patternP ); + } +#endif /* HAS_XVMCSHM */ + + WriteToClient(client, sizeof(xvmcGetDRInfoReply), + (char*)&rep); + if (rep.length) { + WriteToClient(client, rep.nameLen, + pScreenPriv->clientDriverName); + WriteToClient(client, rep.busIDLen, + pScreenPriv->busID); + } + return Success; +} + + +int (*ProcXvMCVector[xvmcNumRequest])(ClientPtr) = { + ProcXvMCQueryVersion, + ProcXvMCListSurfaceTypes, + ProcXvMCCreateContext, + ProcXvMCDestroyContext, + ProcXvMCCreateSurface, + ProcXvMCDestroySurface, + ProcXvMCCreateSubpicture, + ProcXvMCDestroySubpicture, + ProcXvMCListSubpictureTypes, + ProcXvMCGetDRInfo +}; + +static int +ProcXvMCDispatch (ClientPtr client) +{ + REQUEST(xReq); + + if(stuff->data < xvmcNumRequest) + return (*ProcXvMCVector[stuff->data])(client); + else + return BadRequest; +} + +static int +SProcXvMCDispatch (ClientPtr client) +{ + /* We only support local */ + return BadImplementation; +} + +void +XvMCExtensionInit(void) +{ + ExtensionEntry *extEntry; + + if(XvMCScreenKey == NULL) /* nobody supports it */ + return; + + if(!(XvMCRTContext = CreateNewResourceType(XvMCDestroyContextRes, + "XvMCRTContext"))) + return; + + if(!(XvMCRTSurface = CreateNewResourceType(XvMCDestroySurfaceRes, + "XvMCRTSurface"))) + return; + + if(!(XvMCRTSubpicture = CreateNewResourceType(XvMCDestroySubpictureRes, + "XvMCRTSubpicture"))) + return; + + extEntry = AddExtension(XvMCName, XvMCNumEvents, XvMCNumErrors, + ProcXvMCDispatch, SProcXvMCDispatch, + NULL, StandardMinorOpcode); + + if(!extEntry) return; + + XvMCReqCode = extEntry->base; + XvMCEventBase = extEntry->eventBase; + XvMCErrorBase = extEntry->errorBase; +} + +static Bool +XvMCCloseScreen (int i, ScreenPtr pScreen) +{ + XvMCScreenPtr pScreenPriv = XVMC_GET_PRIVATE(pScreen); + + pScreen->CloseScreen = pScreenPriv->CloseScreen; + + free(pScreenPriv); + + return (*pScreen->CloseScreen)(i, pScreen); +} + + +int +XvMCScreenInit(ScreenPtr pScreen, int num, XvMCAdaptorPtr pAdapt) +{ + XvMCScreenPtr pScreenPriv; + + XvMCScreenKey = &XvMCScreenKeyIndex; + + if(!(pScreenPriv = malloc(sizeof(XvMCScreenRec)))) + return BadAlloc; + + dixSetPrivate(&pScreen->devPrivates, XvMCScreenKey, pScreenPriv); + + pScreenPriv->CloseScreen = pScreen->CloseScreen; + pScreen->CloseScreen = XvMCCloseScreen; + + pScreenPriv->num_adaptors = num; + pScreenPriv->adaptors = pAdapt; + pScreenPriv->clientDriverName[0] = 0; + pScreenPriv->busID[0] = 0; + pScreenPriv->major = 0; + pScreenPriv->minor = 0; + pScreenPriv->patchLevel = 0; + + return Success; +} + +XvImagePtr XvMCFindXvImage(XvPortPtr pPort, CARD32 id) +{ + XvImagePtr pImage = NULL; + ScreenPtr pScreen = pPort->pAdaptor->pScreen; + XvMCScreenPtr pScreenPriv; + XvMCAdaptorPtr adaptor = NULL; + int i; + + if(XvMCScreenKey == NULL) return NULL; + + if(!(pScreenPriv = XVMC_GET_PRIVATE(pScreen))) + return NULL; + + for(i = 0; i < pScreenPriv->num_adaptors; i++) { + if(pPort->pAdaptor == pScreenPriv->adaptors[i].xv_adaptor) { + adaptor = &(pScreenPriv->adaptors[i]); + break; + } + } + + if(!adaptor) return NULL; + + for(i = 0; i < adaptor->num_subpictures; i++) { + if(adaptor->subpictures[i]->id == id) { + pImage = adaptor->subpictures[i]; + break; + } + } + + return pImage; +} + +int +xf86XvMCRegisterDRInfo(ScreenPtr pScreen, char *name, + char *busID, int major, int minor, + int patchLevel) +{ + XvMCScreenPtr pScreenPriv = XVMC_GET_PRIVATE(pScreen); + strncpy(pScreenPriv->clientDriverName, name, + DR_CLIENT_DRIVER_NAME_SIZE); + strncpy(pScreenPriv->busID, busID, DR_BUSID_SIZE); + pScreenPriv->major = major; + pScreenPriv->minor = minor; + pScreenPriv->patchLevel = patchLevel; + pScreenPriv->clientDriverName[DR_CLIENT_DRIVER_NAME_SIZE-1] = 0; + pScreenPriv->busID[DR_BUSID_SIZE-1] = 0; + return Success; +} + -- cgit v1.2.3