shm.c revision 65b04b38
105b261ecSmrg/************************************************************
205b261ecSmrg
305b261ecSmrgCopyright 1989, 1998  The Open Group
405b261ecSmrg
505b261ecSmrgPermission to use, copy, modify, distribute, and sell this software and its
605b261ecSmrgdocumentation for any purpose is hereby granted without fee, provided that
705b261ecSmrgthe above copyright notice appear in all copies and that both that
805b261ecSmrgcopyright notice and this permission notice appear in supporting
905b261ecSmrgdocumentation.
1005b261ecSmrg
1105b261ecSmrgThe above copyright notice and this permission notice shall be included in
1205b261ecSmrgall copies or substantial portions of the Software.
1305b261ecSmrg
1405b261ecSmrgTHE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
1505b261ecSmrgIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
1605b261ecSmrgFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
1705b261ecSmrgOPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
1805b261ecSmrgAN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
1905b261ecSmrgCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
2005b261ecSmrg
2105b261ecSmrgExcept as contained in this notice, the name of The Open Group shall not be
2205b261ecSmrgused in advertising or otherwise to promote the sale, use or other dealings
2305b261ecSmrgin this Software without prior written authorization from The Open Group.
2405b261ecSmrg
2505b261ecSmrg********************************************************/
2605b261ecSmrg
2705b261ecSmrg/* THIS IS NOT AN X CONSORTIUM STANDARD OR AN X PROJECT TEAM SPECIFICATION */
2805b261ecSmrg
2905b261ecSmrg
3005b261ecSmrg#define SHM
3105b261ecSmrg
3205b261ecSmrg#ifdef HAVE_DIX_CONFIG_H
3305b261ecSmrg#include <dix-config.h>
3405b261ecSmrg#endif
3505b261ecSmrg
3605b261ecSmrg#include <sys/types.h>
3705b261ecSmrg#include <sys/ipc.h>
3805b261ecSmrg#include <sys/shm.h>
3905b261ecSmrg#include <unistd.h>
4005b261ecSmrg#include <sys/stat.h>
4105b261ecSmrg#include <X11/X.h>
4205b261ecSmrg#include <X11/Xproto.h>
4305b261ecSmrg#include "misc.h"
4405b261ecSmrg#include "os.h"
4505b261ecSmrg#include "dixstruct.h"
4605b261ecSmrg#include "resource.h"
4705b261ecSmrg#include "scrnintstr.h"
4805b261ecSmrg#include "windowstr.h"
4905b261ecSmrg#include "pixmapstr.h"
5005b261ecSmrg#include "gcstruct.h"
5105b261ecSmrg#include "extnsionst.h"
5205b261ecSmrg#include "servermd.h"
534642e01fSmrg#include "shmint.h"
544642e01fSmrg#include "xace.h"
55684baedfSmrg#include <X11/extensions/shmproto.h>
5605b261ecSmrg#include <X11/Xfuncproto.h>
574202a189Smrg#include "protocol-versions.h"
5805b261ecSmrg
594642e01fSmrg/* Needed for Solaris cross-zone shared memory extension */
604642e01fSmrg#ifdef HAVE_SHMCTL64
614642e01fSmrg#include <sys/ipc_impl.h>
624642e01fSmrg#define SHMSTAT(id, buf)	shmctl64(id, IPC_STAT64, buf)
634642e01fSmrg#define SHMSTAT_TYPE 		struct shmid_ds64
644642e01fSmrg#define SHMPERM_TYPE 		struct ipc_perm64
654642e01fSmrg#define SHM_PERM(buf) 		buf.shmx_perm
664642e01fSmrg#define SHM_SEGSZ(buf)		buf.shmx_segsz
674642e01fSmrg#define SHMPERM_UID(p)		p->ipcx_uid
684642e01fSmrg#define SHMPERM_CUID(p)		p->ipcx_cuid
694642e01fSmrg#define SHMPERM_GID(p)		p->ipcx_gid
704642e01fSmrg#define SHMPERM_CGID(p)		p->ipcx_cgid
714642e01fSmrg#define SHMPERM_MODE(p)		p->ipcx_mode
724642e01fSmrg#define SHMPERM_ZONEID(p)	p->ipcx_zoneid
734642e01fSmrg#else
744642e01fSmrg#define SHMSTAT(id, buf) 	shmctl(id, IPC_STAT, buf)
754642e01fSmrg#define SHMSTAT_TYPE 		struct shmid_ds
764642e01fSmrg#define SHMPERM_TYPE 		struct ipc_perm
774642e01fSmrg#define SHM_PERM(buf) 		buf.shm_perm
784642e01fSmrg#define SHM_SEGSZ(buf)		buf.shm_segsz
794642e01fSmrg#define SHMPERM_UID(p)		p->uid
804642e01fSmrg#define SHMPERM_CUID(p)		p->cuid
814642e01fSmrg#define SHMPERM_GID(p)		p->gid
824642e01fSmrg#define SHMPERM_CGID(p)		p->cgid
834642e01fSmrg#define SHMPERM_MODE(p)		p->mode
844642e01fSmrg#endif
854642e01fSmrg
8605b261ecSmrg#ifdef PANORAMIX
8705b261ecSmrg#include "panoramiX.h"
8805b261ecSmrg#include "panoramiXsrv.h"
8905b261ecSmrg#endif
9005b261ecSmrg
9105b261ecSmrg#include "modinit.h"
9205b261ecSmrg
9305b261ecSmrgtypedef struct _ShmDesc {
9405b261ecSmrg    struct _ShmDesc *next;
9505b261ecSmrg    int shmid;
9605b261ecSmrg    int refcnt;
9705b261ecSmrg    char *addr;
9805b261ecSmrg    Bool writable;
9905b261ecSmrg    unsigned long size;
10005b261ecSmrg} ShmDescRec, *ShmDescPtr;
10105b261ecSmrg
1024202a189Smrgtypedef struct _ShmScrPrivateRec {
1034202a189Smrg    CloseScreenProcPtr CloseScreen;
1044202a189Smrg    ShmFuncsPtr shmFuncs;
1054202a189Smrg    DestroyPixmapProcPtr destroyPixmap;
1064202a189Smrg} ShmScrPrivateRec;
1074202a189Smrg
10805b261ecSmrgstatic PixmapPtr fbShmCreatePixmap(XSHM_CREATE_PIXMAP_ARGS);
10905b261ecSmrgstatic int ShmDetachSegment(
11005b261ecSmrg    pointer		/* value */,
11105b261ecSmrg    XID			/* shmseg */
11205b261ecSmrg    );
11305b261ecSmrgstatic void ShmResetProc(
11405b261ecSmrg    ExtensionEntry *	/* extEntry */
11505b261ecSmrg    );
11605b261ecSmrgstatic void SShmCompletionEvent(
11705b261ecSmrg    xShmCompletionEvent * /* from */,
11805b261ecSmrg    xShmCompletionEvent * /* to */
11905b261ecSmrg    );
12005b261ecSmrg
12105b261ecSmrgstatic Bool ShmDestroyPixmap (PixmapPtr pPixmap);
12205b261ecSmrg
12305b261ecSmrg
12405b261ecSmrgstatic unsigned char ShmReqCode;
1254202a189Smrgint ShmCompletionCode;
1264202a189Smrgint BadShmSegCode;
1274202a189SmrgRESTYPE ShmSegType;
12805b261ecSmrgstatic ShmDescPtr Shmsegs;
12905b261ecSmrgstatic Bool sharedPixmaps;
1304202a189Smrgstatic DevPrivateKeyRec shmScrPrivateKeyRec;
1314202a189Smrg#define shmScrPrivateKey (&shmScrPrivateKeyRec)
1324202a189Smrgstatic DevPrivateKeyRec shmPixmapPrivateKeyRec;
1334202a189Smrg#define shmPixmapPrivateKey (&shmPixmapPrivateKeyRec)
1344642e01fSmrgstatic ShmFuncs miFuncs = {NULL, NULL};
1354642e01fSmrgstatic ShmFuncs fbFuncs = {fbShmCreatePixmap, NULL};
13605b261ecSmrg
1374202a189Smrg#define ShmGetScreenPriv(s) ((ShmScrPrivateRec *)dixLookupPrivate(&(s)->devPrivates, shmScrPrivateKey))
1384202a189Smrg
13905b261ecSmrg#define VERIFY_SHMSEG(shmseg,shmdesc,client) \
14005b261ecSmrg{ \
1414202a189Smrg    int rc; \
1424202a189Smrg    rc = dixLookupResourceByType((pointer *)&(shmdesc), shmseg, ShmSegType, \
1434202a189Smrg                                 client, DixReadAccess); \
1444202a189Smrg    if (rc != Success) \
1454202a189Smrg	return rc; \
14605b261ecSmrg}
14705b261ecSmrg
14805b261ecSmrg#define VERIFY_SHMPTR(shmseg,offset,needwrite,shmdesc,client) \
14905b261ecSmrg{ \
15005b261ecSmrg    VERIFY_SHMSEG(shmseg, shmdesc, client); \
15105b261ecSmrg    if ((offset & 3) || (offset > shmdesc->size)) \
15205b261ecSmrg    { \
15305b261ecSmrg	client->errorValue = offset; \
15405b261ecSmrg	return BadValue; \
15505b261ecSmrg    } \
15605b261ecSmrg    if (needwrite && !shmdesc->writable) \
15705b261ecSmrg	return BadAccess; \
15805b261ecSmrg}
15905b261ecSmrg
16005b261ecSmrg#define VERIFY_SHMSIZE(shmdesc,offset,len,client) \
16105b261ecSmrg{ \
16205b261ecSmrg    if ((offset + len) > shmdesc->size) \
16305b261ecSmrg    { \
16405b261ecSmrg	return BadAccess; \
16505b261ecSmrg    } \
16605b261ecSmrg}
16705b261ecSmrg
16805b261ecSmrg
16905b261ecSmrg#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__CYGWIN__) || defined(__DragonFly__)
17005b261ecSmrg#include <sys/signal.h>
17105b261ecSmrg
17205b261ecSmrgstatic Bool badSysCall = FALSE;
17305b261ecSmrg
17405b261ecSmrgstatic void
1754642e01fSmrgSigSysHandler(int signo)
17605b261ecSmrg{
17705b261ecSmrg    badSysCall = TRUE;
17805b261ecSmrg}
17905b261ecSmrg
1804642e01fSmrgstatic Bool CheckForShmSyscall(void)
18105b261ecSmrg{
18205b261ecSmrg    void (*oldHandler)();
18305b261ecSmrg    int shmid = -1;
18405b261ecSmrg
18505b261ecSmrg    /* If no SHM support in the kernel, the bad syscall will generate SIGSYS */
18605b261ecSmrg    oldHandler = signal(SIGSYS, SigSysHandler);
18705b261ecSmrg
18805b261ecSmrg    badSysCall = FALSE;
18905b261ecSmrg    shmid = shmget(IPC_PRIVATE, 4096, IPC_CREAT);
19005b261ecSmrg
19105b261ecSmrg    if (shmid != -1)
19205b261ecSmrg    {
19305b261ecSmrg        /* Successful allocation - clean up */
1944202a189Smrg	shmctl(shmid, IPC_RMID, NULL);
19505b261ecSmrg    }
19605b261ecSmrg    else
19705b261ecSmrg    {
19805b261ecSmrg        /* Allocation failed */
19905b261ecSmrg        badSysCall = TRUE;
20005b261ecSmrg    }
20105b261ecSmrg    signal(SIGSYS, oldHandler);
2024202a189Smrg    return !badSysCall;
20305b261ecSmrg}
20405b261ecSmrg
20505b261ecSmrg#define MUST_CHECK_FOR_SHM_SYSCALL
20605b261ecSmrg
20705b261ecSmrg#endif
20805b261ecSmrg
2094202a189Smrgstatic Bool
2104202a189SmrgShmCloseScreen(int i, ScreenPtr pScreen)
2114202a189Smrg{
2124202a189Smrg    ShmScrPrivateRec *screen_priv = ShmGetScreenPriv(pScreen);
2134202a189Smrg    pScreen->CloseScreen = screen_priv->CloseScreen;
2144202a189Smrg    dixSetPrivate(&pScreen->devPrivates, shmScrPrivateKey, NULL);
2154202a189Smrg    free(screen_priv);
2164202a189Smrg    return (*pScreen->CloseScreen) (i, pScreen);
2174202a189Smrg}
2184202a189Smrg
2194202a189Smrgstatic ShmScrPrivateRec *
2204202a189SmrgShmInitScreenPriv(ScreenPtr pScreen)
2214202a189Smrg{
2224202a189Smrg    ShmScrPrivateRec *screen_priv = ShmGetScreenPriv(pScreen);
2234202a189Smrg    if (!screen_priv)
2244202a189Smrg    {
2254202a189Smrg	screen_priv = calloc(1, sizeof (ShmScrPrivateRec));
2264202a189Smrg	screen_priv->CloseScreen = pScreen->CloseScreen;
2274202a189Smrg	dixSetPrivate(&pScreen->devPrivates, shmScrPrivateKey, screen_priv);
2284202a189Smrg	pScreen->CloseScreen = ShmCloseScreen;
2294202a189Smrg    }
2304202a189Smrg    return screen_priv;
2314202a189Smrg}
2324202a189Smrg
2334202a189Smrgstatic Bool
2344202a189SmrgShmRegisterPrivates(void)
2354202a189Smrg{
2364202a189Smrg    if (!dixRegisterPrivateKey(&shmScrPrivateKeyRec, PRIVATE_SCREEN, 0))
2374202a189Smrg	return FALSE;
2384202a189Smrg    if (!dixRegisterPrivateKey(&shmPixmapPrivateKeyRec, PRIVATE_PIXMAP, 0))
2394202a189Smrg	return FALSE;
2404202a189Smrg    return TRUE;
2414202a189Smrg}
2424202a189Smrg
24305b261ecSmrg/*ARGSUSED*/
24405b261ecSmrgstatic void
2454642e01fSmrgShmResetProc(ExtensionEntry *extEntry)
24605b261ecSmrg{
24705b261ecSmrg    int i;
2484202a189Smrg    for (i = 0; i < screenInfo.numScreens; i++)
2494202a189Smrg	ShmRegisterFuncs(screenInfo.screens[i], NULL);
25005b261ecSmrg}
25105b261ecSmrg
2524202a189Smrgvoid
2534642e01fSmrgShmRegisterFuncs(ScreenPtr pScreen, ShmFuncsPtr funcs)
25405b261ecSmrg{
2554202a189Smrg    if (!ShmRegisterPrivates())
2564202a189Smrg	return;
2574202a189Smrg    ShmInitScreenPriv(pScreen)->shmFuncs = funcs;
25805b261ecSmrg}
25905b261ecSmrg
26005b261ecSmrgstatic Bool
26105b261ecSmrgShmDestroyPixmap (PixmapPtr pPixmap)
26205b261ecSmrg{
26305b261ecSmrg    ScreenPtr	    pScreen = pPixmap->drawable.pScreen;
2644202a189Smrg    ShmScrPrivateRec *screen_priv = ShmGetScreenPriv(pScreen);
26505b261ecSmrg    Bool	    ret;
26605b261ecSmrg    if (pPixmap->refcnt == 1)
26705b261ecSmrg    {
26805b261ecSmrg	ShmDescPtr  shmdesc;
2694642e01fSmrg	shmdesc = (ShmDescPtr)dixLookupPrivate(&pPixmap->devPrivates,
2704202a189Smrg					       shmPixmapPrivateKey);
27105b261ecSmrg	if (shmdesc)
27205b261ecSmrg	    ShmDetachSegment ((pointer) shmdesc, pPixmap->drawable.id);
27305b261ecSmrg    }
27405b261ecSmrg
2754202a189Smrg    pScreen->DestroyPixmap = screen_priv->destroyPixmap;
27605b261ecSmrg    ret = (*pScreen->DestroyPixmap) (pPixmap);
2774202a189Smrg    screen_priv->destroyPixmap = pScreen->DestroyPixmap;
27805b261ecSmrg    pScreen->DestroyPixmap = ShmDestroyPixmap;
27905b261ecSmrg    return ret;
28005b261ecSmrg}
28105b261ecSmrg
2824202a189Smrgvoid
2834642e01fSmrgShmRegisterFbFuncs(ScreenPtr pScreen)
28405b261ecSmrg{
2854202a189Smrg    ShmRegisterFuncs(pScreen, &fbFuncs);
28605b261ecSmrg}
28705b261ecSmrg
28805b261ecSmrgstatic int
2894642e01fSmrgProcShmQueryVersion(ClientPtr client)
29005b261ecSmrg{
29105b261ecSmrg    xShmQueryVersionReply rep;
2924642e01fSmrg    int n;
29305b261ecSmrg
29405b261ecSmrg    REQUEST_SIZE_MATCH(xShmQueryVersionReq);
2954202a189Smrg    memset(&rep, 0, sizeof(xShmQueryVersionReply));
29605b261ecSmrg    rep.type = X_Reply;
29705b261ecSmrg    rep.length = 0;
29805b261ecSmrg    rep.sequenceNumber = client->sequence;
29905b261ecSmrg    rep.sharedPixmaps = sharedPixmaps;
3004642e01fSmrg    rep.pixmapFormat = sharedPixmaps ? ZPixmap : 0;
3014202a189Smrg    rep.majorVersion = SERVER_SHM_MAJOR_VERSION;
3024202a189Smrg    rep.minorVersion = SERVER_SHM_MINOR_VERSION;
30305b261ecSmrg    rep.uid = geteuid();
30405b261ecSmrg    rep.gid = getegid();
30505b261ecSmrg    if (client->swapped) {
30605b261ecSmrg    	swaps(&rep.sequenceNumber, n);
30705b261ecSmrg    	swapl(&rep.length, n);
30805b261ecSmrg	swaps(&rep.majorVersion, n);
30905b261ecSmrg	swaps(&rep.minorVersion, n);
31005b261ecSmrg	swaps(&rep.uid, n);
31105b261ecSmrg	swaps(&rep.gid, n);
31205b261ecSmrg    }
31305b261ecSmrg    WriteToClient(client, sizeof(xShmQueryVersionReply), (char *)&rep);
3144202a189Smrg    return Success;
31505b261ecSmrg}
31605b261ecSmrg
31705b261ecSmrg/*
31805b261ecSmrg * Simulate the access() system call for a shared memory segement,
31905b261ecSmrg * using the credentials from the client if available
32005b261ecSmrg */
32105b261ecSmrgstatic int
3224642e01fSmrgshm_access(ClientPtr client, SHMPERM_TYPE *perm, int readonly)
32305b261ecSmrg{
32405b261ecSmrg    int uid, gid;
32505b261ecSmrg    mode_t mask;
3264642e01fSmrg    int uidset = 0, gidset = 0;
3274642e01fSmrg    LocalClientCredRec *lcc;
3284642e01fSmrg
3294642e01fSmrg    if (GetLocalClientCreds(client, &lcc) != -1) {
33005b261ecSmrg
3314642e01fSmrg	if (lcc->fieldsSet & LCC_UID_SET) {
3324642e01fSmrg	    uid = lcc->euid;
3334642e01fSmrg	    uidset = 1;
3344642e01fSmrg	}
3354642e01fSmrg	if (lcc->fieldsSet & LCC_GID_SET) {
3364642e01fSmrg	    gid = lcc->egid;
3374642e01fSmrg	    gidset = 1;
3384642e01fSmrg	}
3394642e01fSmrg
3404642e01fSmrg#if defined(HAVE_GETZONEID) && defined(SHMPERM_ZONEID)
3414642e01fSmrg	if ( ((lcc->fieldsSet & LCC_ZID_SET) == 0) || (lcc->zoneid == -1)
3424642e01fSmrg	     || (lcc->zoneid != SHMPERM_ZONEID(perm))) {
3434642e01fSmrg		uidset = 0;
3444642e01fSmrg		gidset = 0;
34505b261ecSmrg	}
3464642e01fSmrg#endif
3474642e01fSmrg	FreeLocalClientCreds(lcc);
3484642e01fSmrg
3494642e01fSmrg	if (uidset) {
3504642e01fSmrg	    /* User id 0 always gets access */
3514642e01fSmrg	    if (uid == 0) {
3524642e01fSmrg		return 0;
3534642e01fSmrg	    }
3544642e01fSmrg	    /* Check the owner */
3554642e01fSmrg	    if (SHMPERM_UID(perm) == uid || SHMPERM_CUID(perm) == uid) {
3564642e01fSmrg		mask = S_IRUSR;
3574642e01fSmrg		if (!readonly) {
3584642e01fSmrg		    mask |= S_IWUSR;
3594642e01fSmrg		}
3604642e01fSmrg		return (SHMPERM_MODE(perm) & mask) == mask ? 0 : -1;
36105b261ecSmrg	    }
36205b261ecSmrg	}
3634642e01fSmrg
3644642e01fSmrg	if (gidset) {
3654642e01fSmrg	    /* Check the group */
3664642e01fSmrg	    if (SHMPERM_GID(perm) == gid || SHMPERM_CGID(perm) == gid) {
3674642e01fSmrg		mask = S_IRGRP;
3684642e01fSmrg		if (!readonly) {
3694642e01fSmrg		    mask |= S_IWGRP;
3704642e01fSmrg		}
3714642e01fSmrg		return (SHMPERM_MODE(perm) & mask) == mask ? 0 : -1;
37205b261ecSmrg	    }
37305b261ecSmrg	}
37405b261ecSmrg    }
37505b261ecSmrg    /* Otherwise, check everyone else */
37605b261ecSmrg    mask = S_IROTH;
37705b261ecSmrg    if (!readonly) {
37805b261ecSmrg	mask |= S_IWOTH;
37905b261ecSmrg    }
3804642e01fSmrg    return (SHMPERM_MODE(perm) & mask) == mask ? 0 : -1;
38105b261ecSmrg}
38205b261ecSmrg
38305b261ecSmrgstatic int
3844642e01fSmrgProcShmAttach(ClientPtr client)
38505b261ecSmrg{
3864642e01fSmrg    SHMSTAT_TYPE buf;
38705b261ecSmrg    ShmDescPtr shmdesc;
38805b261ecSmrg    REQUEST(xShmAttachReq);
38905b261ecSmrg
39005b261ecSmrg    REQUEST_SIZE_MATCH(xShmAttachReq);
39105b261ecSmrg    LEGAL_NEW_RESOURCE(stuff->shmseg, client);
39205b261ecSmrg    if ((stuff->readOnly != xTrue) && (stuff->readOnly != xFalse))
39305b261ecSmrg    {
39405b261ecSmrg	client->errorValue = stuff->readOnly;
3954202a189Smrg        return BadValue;
39605b261ecSmrg    }
39705b261ecSmrg    for (shmdesc = Shmsegs;
39805b261ecSmrg	 shmdesc && (shmdesc->shmid != stuff->shmid);
39905b261ecSmrg	 shmdesc = shmdesc->next)
40005b261ecSmrg	;
40105b261ecSmrg    if (shmdesc)
40205b261ecSmrg    {
40305b261ecSmrg	if (!stuff->readOnly && !shmdesc->writable)
40405b261ecSmrg	    return BadAccess;
40505b261ecSmrg	shmdesc->refcnt++;
40605b261ecSmrg    }
40705b261ecSmrg    else
40805b261ecSmrg    {
4094202a189Smrg	shmdesc = malloc(sizeof(ShmDescRec));
41005b261ecSmrg	if (!shmdesc)
41105b261ecSmrg	    return BadAlloc;
41205b261ecSmrg	shmdesc->addr = shmat(stuff->shmid, 0,
41305b261ecSmrg			      stuff->readOnly ? SHM_RDONLY : 0);
41405b261ecSmrg	if ((shmdesc->addr == ((char *)-1)) ||
4154642e01fSmrg	    SHMSTAT(stuff->shmid, &buf))
41605b261ecSmrg	{
4174202a189Smrg	    free(shmdesc);
41805b261ecSmrg	    return BadAccess;
41905b261ecSmrg	}
42005b261ecSmrg
42105b261ecSmrg	/* The attach was performed with root privs. We must
42205b261ecSmrg	 * do manual checking of access rights for the credentials
42305b261ecSmrg	 * of the client */
42405b261ecSmrg
4254642e01fSmrg	if (shm_access(client, &(SHM_PERM(buf)), stuff->readOnly) == -1) {
42605b261ecSmrg	    shmdt(shmdesc->addr);
4274202a189Smrg	    free(shmdesc);
42805b261ecSmrg	    return BadAccess;
42905b261ecSmrg	}
43005b261ecSmrg
43105b261ecSmrg	shmdesc->shmid = stuff->shmid;
43205b261ecSmrg	shmdesc->refcnt = 1;
43305b261ecSmrg	shmdesc->writable = !stuff->readOnly;
4344642e01fSmrg	shmdesc->size = SHM_SEGSZ(buf);
43505b261ecSmrg	shmdesc->next = Shmsegs;
43605b261ecSmrg	Shmsegs = shmdesc;
43705b261ecSmrg    }
43805b261ecSmrg    if (!AddResource(stuff->shmseg, ShmSegType, (pointer)shmdesc))
43905b261ecSmrg	return BadAlloc;
4404202a189Smrg    return Success;
44105b261ecSmrg}
44205b261ecSmrg
44305b261ecSmrg/*ARGSUSED*/
44405b261ecSmrgstatic int
4454642e01fSmrgShmDetachSegment(pointer value, /* must conform to DeleteType */
4464642e01fSmrg		 XID shmseg)
44705b261ecSmrg{
44805b261ecSmrg    ShmDescPtr shmdesc = (ShmDescPtr)value;
44905b261ecSmrg    ShmDescPtr *prev;
45005b261ecSmrg
45105b261ecSmrg    if (--shmdesc->refcnt)
45205b261ecSmrg	return TRUE;
45305b261ecSmrg    shmdt(shmdesc->addr);
45405b261ecSmrg    for (prev = &Shmsegs; *prev != shmdesc; prev = &(*prev)->next)
45505b261ecSmrg	;
45605b261ecSmrg    *prev = shmdesc->next;
4574202a189Smrg    free(shmdesc);
45805b261ecSmrg    return Success;
45905b261ecSmrg}
46005b261ecSmrg
46105b261ecSmrgstatic int
4624642e01fSmrgProcShmDetach(ClientPtr client)
46305b261ecSmrg{
46405b261ecSmrg    ShmDescPtr shmdesc;
46505b261ecSmrg    REQUEST(xShmDetachReq);
46605b261ecSmrg
46705b261ecSmrg    REQUEST_SIZE_MATCH(xShmDetachReq);
46805b261ecSmrg    VERIFY_SHMSEG(stuff->shmseg, shmdesc, client);
46905b261ecSmrg    FreeResource(stuff->shmseg, RT_NONE);
4704202a189Smrg    return Success;
47105b261ecSmrg}
47205b261ecSmrg
4734642e01fSmrg/*
4744642e01fSmrg * If the given request doesn't exactly match PutImage's constraints,
4754642e01fSmrg * wrap the image in a scratch pixmap header and let CopyArea sort it out.
4764642e01fSmrg */
47705b261ecSmrgstatic void
4784642e01fSmrgdoShmPutImage(DrawablePtr dst, GCPtr pGC,
4794642e01fSmrg	      int depth, unsigned int format,
4804642e01fSmrg	      int w, int h, int sx, int sy, int sw, int sh, int dx, int dy,
4814642e01fSmrg	      char *data)
48205b261ecSmrg{
4834642e01fSmrg    PixmapPtr pPixmap;
4844202a189Smrg
4854202a189Smrg    if (format == ZPixmap || depth == 1) {
4864202a189Smrg	pPixmap = GetScratchPixmapHeader(dst->pScreen, w, h, depth,
4874202a189Smrg					 BitsPerPixel(depth),
4884202a189Smrg					 PixmapBytePad(w, depth),
4894202a189Smrg					 data);
4904202a189Smrg	if (!pPixmap)
4914202a189Smrg	    return;
4924202a189Smrg	pGC->ops->CopyArea((DrawablePtr)pPixmap, dst, pGC, sx, sy, sw, sh, dx, dy);
4934202a189Smrg	FreeScratchPixmapHeader(pPixmap);
4944202a189Smrg    } else {
4954202a189Smrg	GCPtr putGC = GetScratchGC(depth, dst->pScreen);
4964202a189Smrg
4974202a189Smrg	if (!putGC)
4984202a189Smrg	    return;
4994202a189Smrg
5004202a189Smrg	pPixmap = (*dst->pScreen->CreatePixmap)(dst->pScreen, sw, sh, depth,
5014202a189Smrg						CREATE_PIXMAP_USAGE_SCRATCH);
5024202a189Smrg	if (!pPixmap) {
5034202a189Smrg	    FreeScratchGC(putGC);
5044202a189Smrg	    return;
5054202a189Smrg	}
5064202a189Smrg	ValidateGC(&pPixmap->drawable, putGC);
5074202a189Smrg	(*putGC->ops->PutImage)(&pPixmap->drawable, putGC, depth, -sx, -sy, w, h, 0,
5084202a189Smrg				(format == XYPixmap) ? XYPixmap : ZPixmap, data);
5094202a189Smrg	FreeScratchGC(putGC);
5104202a189Smrg	if (format == XYBitmap)
5114202a189Smrg	    (void)(*pGC->ops->CopyPlane)(&pPixmap->drawable, dst, pGC, 0, 0, sw, sh,
5124202a189Smrg					 dx, dy, 1L);
5134202a189Smrg	else
5144202a189Smrg	    (void)(*pGC->ops->CopyArea)(&pPixmap->drawable, dst, pGC, 0, 0, sw, sh,
5154202a189Smrg					dx, dy);
5164202a189Smrg	(*pPixmap->drawable.pScreen->DestroyPixmap)(pPixmap);
5174202a189Smrg    }
51805b261ecSmrg}
51905b261ecSmrg
52065b04b38Smrgstatic int
52165b04b38SmrgProcShmPutImage(ClientPtr client)
52205b261ecSmrg{
52365b04b38Smrg    GCPtr pGC;
52465b04b38Smrg    DrawablePtr pDraw;
52565b04b38Smrg    long length;
52665b04b38Smrg    ShmDescPtr shmdesc;
52705b261ecSmrg    REQUEST(xShmPutImageReq);
52865b04b38Smrg
52905b261ecSmrg    REQUEST_SIZE_MATCH(xShmPutImageReq);
53065b04b38Smrg    VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess);
53165b04b38Smrg    VERIFY_SHMPTR(stuff->shmseg, stuff->offset, FALSE, shmdesc, client);
53265b04b38Smrg    if ((stuff->sendEvent != xTrue) && (stuff->sendEvent != xFalse))
53365b04b38Smrg	return BadValue;
53465b04b38Smrg    if (stuff->format == XYBitmap)
53565b04b38Smrg    {
53665b04b38Smrg        if (stuff->depth != 1)
53765b04b38Smrg            return BadMatch;
53865b04b38Smrg        length = PixmapBytePad(stuff->totalWidth, 1);
53965b04b38Smrg    }
54065b04b38Smrg    else if (stuff->format == XYPixmap)
54165b04b38Smrg    {
54265b04b38Smrg        if (pDraw->depth != stuff->depth)
54365b04b38Smrg            return BadMatch;
54465b04b38Smrg        length = PixmapBytePad(stuff->totalWidth, 1);
54565b04b38Smrg	length *= stuff->depth;
54665b04b38Smrg    }
54765b04b38Smrg    else if (stuff->format == ZPixmap)
54865b04b38Smrg    {
54965b04b38Smrg        if (pDraw->depth != stuff->depth)
55065b04b38Smrg            return BadMatch;
55165b04b38Smrg        length = PixmapBytePad(stuff->totalWidth, stuff->depth);
55265b04b38Smrg    }
55365b04b38Smrg    else
55465b04b38Smrg    {
55565b04b38Smrg	client->errorValue = stuff->format;
55665b04b38Smrg        return BadValue;
55765b04b38Smrg    }
55805b261ecSmrg
55965b04b38Smrg    /*
56065b04b38Smrg     * There's a potential integer overflow in this check:
56165b04b38Smrg     * VERIFY_SHMSIZE(shmdesc, stuff->offset, length * stuff->totalHeight,
56265b04b38Smrg     *                client);
56365b04b38Smrg     * the version below ought to avoid it
56465b04b38Smrg     */
56565b04b38Smrg    if (stuff->totalHeight != 0 &&
56665b04b38Smrg	length > (shmdesc->size - stuff->offset)/stuff->totalHeight) {
56765b04b38Smrg	client->errorValue = stuff->totalWidth;
56865b04b38Smrg	return BadValue;
56965b04b38Smrg    }
57065b04b38Smrg    if (stuff->srcX > stuff->totalWidth)
57165b04b38Smrg    {
57265b04b38Smrg	client->errorValue = stuff->srcX;
57365b04b38Smrg	return BadValue;
57465b04b38Smrg    }
57565b04b38Smrg    if (stuff->srcY > stuff->totalHeight)
57665b04b38Smrg    {
57765b04b38Smrg	client->errorValue = stuff->srcY;
57865b04b38Smrg	return BadValue;
57965b04b38Smrg    }
58065b04b38Smrg    if ((stuff->srcX + stuff->srcWidth) > stuff->totalWidth)
58165b04b38Smrg    {
58265b04b38Smrg	client->errorValue = stuff->srcWidth;
58365b04b38Smrg	return BadValue;
58465b04b38Smrg    }
58565b04b38Smrg    if ((stuff->srcY + stuff->srcHeight) > stuff->totalHeight)
58665b04b38Smrg    {
58765b04b38Smrg	client->errorValue = stuff->srcHeight;
58865b04b38Smrg	return BadValue;
58965b04b38Smrg    }
59005b261ecSmrg
59165b04b38Smrg    if ((((stuff->format == ZPixmap) && (stuff->srcX == 0)) ||
59265b04b38Smrg	 ((stuff->format != ZPixmap) &&
59365b04b38Smrg	  (stuff->srcX < screenInfo.bitmapScanlinePad) &&
59465b04b38Smrg	  ((stuff->format == XYBitmap) ||
59565b04b38Smrg	   ((stuff->srcY == 0) &&
59665b04b38Smrg	    (stuff->srcHeight == stuff->totalHeight))))) &&
59765b04b38Smrg	((stuff->srcX + stuff->srcWidth) == stuff->totalWidth))
59865b04b38Smrg	(*pGC->ops->PutImage) (pDraw, pGC, stuff->depth,
59965b04b38Smrg			       stuff->dstX, stuff->dstY,
60065b04b38Smrg			       stuff->totalWidth, stuff->srcHeight,
60165b04b38Smrg			       stuff->srcX, stuff->format,
60265b04b38Smrg			       shmdesc->addr + stuff->offset +
60365b04b38Smrg			       (stuff->srcY * length));
60465b04b38Smrg    else
60565b04b38Smrg	doShmPutImage(pDraw, pGC, stuff->depth, stuff->format,
60665b04b38Smrg		      stuff->totalWidth, stuff->totalHeight,
60765b04b38Smrg		      stuff->srcX, stuff->srcY,
60865b04b38Smrg		      stuff->srcWidth, stuff->srcHeight,
60965b04b38Smrg		      stuff->dstX, stuff->dstY,
61065b04b38Smrg                      shmdesc->addr + stuff->offset);
61105b261ecSmrg
61265b04b38Smrg    if (stuff->sendEvent)
61365b04b38Smrg    {
61465b04b38Smrg	xShmCompletionEvent ev;
61505b261ecSmrg
61665b04b38Smrg	ev.type = ShmCompletionCode;
61765b04b38Smrg	ev.drawable = stuff->drawable;
61865b04b38Smrg	ev.minorEvent = X_ShmPutImage;
61965b04b38Smrg	ev.majorEvent = ShmReqCode;
62065b04b38Smrg	ev.shmseg = stuff->shmseg;
62165b04b38Smrg	ev.offset = stuff->offset;
62265b04b38Smrg	WriteEventsToClient(client, 1, (xEvent *) &ev);
62305b261ecSmrg    }
62465b04b38Smrg
62565b04b38Smrg    return Success;
62605b261ecSmrg}
62705b261ecSmrg
62865b04b38Smrgstatic int
62965b04b38SmrgProcShmGetImage(ClientPtr client)
63005b261ecSmrg{
63165b04b38Smrg    DrawablePtr		pDraw;
63265b04b38Smrg    long		lenPer = 0, length;
63365b04b38Smrg    Mask		plane = 0;
63405b261ecSmrg    xShmGetImageReply	xgi;
63505b261ecSmrg    ShmDescPtr		shmdesc;
63665b04b38Smrg    int			n, rc;
63705b261ecSmrg
63805b261ecSmrg    REQUEST(xShmGetImageReq);
63905b261ecSmrg
64005b261ecSmrg    REQUEST_SIZE_MATCH(xShmGetImageReq);
64165b04b38Smrg    if ((stuff->format != XYPixmap) && (stuff->format != ZPixmap))
64265b04b38Smrg    {
64305b261ecSmrg	client->errorValue = stuff->format;
6444202a189Smrg        return BadValue;
64505b261ecSmrg    }
64605b261ecSmrg    rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0,
6474642e01fSmrg			   DixReadAccess);
64805b261ecSmrg    if (rc != Success)
64905b261ecSmrg	return rc;
65005b261ecSmrg    VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client);
65165b04b38Smrg    if (pDraw->type == DRAWABLE_WINDOW)
65265b04b38Smrg    {
65365b04b38Smrg      if( /* check for being viewable */
65465b04b38Smrg	 !((WindowPtr) pDraw)->realized ||
65565b04b38Smrg	  /* check for being on screen */
65665b04b38Smrg         pDraw->x + stuff->x < 0 ||
65765b04b38Smrg         pDraw->x + stuff->x + (int)stuff->width > pDraw->pScreen->width ||
65865b04b38Smrg         pDraw->y + stuff->y < 0 ||
65965b04b38Smrg         pDraw->y + stuff->y + (int)stuff->height > pDraw->pScreen->height ||
66065b04b38Smrg          /* check for being inside of border */
66165b04b38Smrg         stuff->x < - wBorderWidth((WindowPtr)pDraw) ||
66265b04b38Smrg         stuff->x + (int)stuff->width >
66365b04b38Smrg		wBorderWidth((WindowPtr)pDraw) + (int)pDraw->width ||
66465b04b38Smrg         stuff->y < -wBorderWidth((WindowPtr)pDraw) ||
66565b04b38Smrg         stuff->y + (int)stuff->height >
66665b04b38Smrg		wBorderWidth((WindowPtr)pDraw) + (int)pDraw->height
66765b04b38Smrg        )
6684202a189Smrg	    return BadMatch;
66965b04b38Smrg	xgi.visual = wVisual(((WindowPtr)pDraw));
67065b04b38Smrg    }
67165b04b38Smrg    else
67265b04b38Smrg    {
67365b04b38Smrg	if (stuff->x < 0 ||
67465b04b38Smrg	    stuff->x+(int)stuff->width > pDraw->width ||
67565b04b38Smrg	    stuff->y < 0 ||
67665b04b38Smrg	    stuff->y+(int)stuff->height > pDraw->height
67765b04b38Smrg	    )
6784202a189Smrg	    return BadMatch;
67965b04b38Smrg	xgi.visual = None;
68005b261ecSmrg    }
68165b04b38Smrg    xgi.type = X_Reply;
68265b04b38Smrg    xgi.length = 0;
68365b04b38Smrg    xgi.sequenceNumber = client->sequence;
68465b04b38Smrg    xgi.depth = pDraw->depth;
68565b04b38Smrg    if(stuff->format == ZPixmap)
68665b04b38Smrg    {
68765b04b38Smrg	length = PixmapBytePad(stuff->width, pDraw->depth) * stuff->height;
68865b04b38Smrg    }
68965b04b38Smrg    else
69065b04b38Smrg    {
69165b04b38Smrg	lenPer = PixmapBytePad(stuff->width, 1) * stuff->height;
69265b04b38Smrg	plane = ((Mask)1) << (pDraw->depth - 1);
69365b04b38Smrg	/* only planes asked for */
69465b04b38Smrg	length = lenPer * Ones(stuff->planeMask & (plane | (plane - 1)));
69565b04b38Smrg    }
69665b04b38Smrg
69765b04b38Smrg    VERIFY_SHMSIZE(shmdesc, stuff->offset, length, client);
69865b04b38Smrg    xgi.size = length;
69965b04b38Smrg
70065b04b38Smrg    if (length == 0)
70165b04b38Smrg    {
70265b04b38Smrg	/* nothing to do */
70365b04b38Smrg    }
70465b04b38Smrg    else if (stuff->format == ZPixmap)
70565b04b38Smrg    {
70665b04b38Smrg	(*pDraw->pScreen->GetImage)(pDraw, stuff->x, stuff->y,
70765b04b38Smrg				    stuff->width, stuff->height,
70865b04b38Smrg				    stuff->format, stuff->planeMask,
70965b04b38Smrg				    shmdesc->addr + stuff->offset);
71065b04b38Smrg    }
71165b04b38Smrg    else
71265b04b38Smrg    {
71365b04b38Smrg
71465b04b38Smrg	length = stuff->offset;
71565b04b38Smrg        for (; plane; plane >>= 1)
71665b04b38Smrg	{
71765b04b38Smrg	    if (stuff->planeMask & plane)
71865b04b38Smrg	    {
71965b04b38Smrg		(*pDraw->pScreen->GetImage)(pDraw,
72065b04b38Smrg					    stuff->x, stuff->y,
72165b04b38Smrg					    stuff->width, stuff->height,
72265b04b38Smrg					    stuff->format, plane,
72365b04b38Smrg					    shmdesc->addr + length);
72465b04b38Smrg		length += lenPer;
72565b04b38Smrg	    }
72665b04b38Smrg	}
72765b04b38Smrg    }
72865b04b38Smrg
72965b04b38Smrg    if (client->swapped) {
73065b04b38Smrg	swaps(&xgi.sequenceNumber, n);
73165b04b38Smrg	swapl(&xgi.length, n);
73265b04b38Smrg	swapl(&xgi.visual, n);
73365b04b38Smrg	swapl(&xgi.size, n);
73465b04b38Smrg    }
73565b04b38Smrg    WriteToClient(client, sizeof(xShmGetImageReply), (char *)&xgi);
73665b04b38Smrg
73765b04b38Smrg    return Success;
73865b04b38Smrg}
73965b04b38Smrg
74065b04b38Smrg#ifdef PANORAMIX
74165b04b38Smrgstatic int
74265b04b38SmrgProcPanoramiXShmPutImage(ClientPtr client)
74365b04b38Smrg{
74465b04b38Smrg    int			 j, result, orig_x, orig_y;
74565b04b38Smrg    PanoramiXRes	*draw, *gc;
74665b04b38Smrg    Bool		 sendEvent, isRoot;
74765b04b38Smrg
74865b04b38Smrg    REQUEST(xShmPutImageReq);
74965b04b38Smrg    REQUEST_SIZE_MATCH(xShmPutImageReq);
75065b04b38Smrg
75165b04b38Smrg    result = dixLookupResourceByClass((pointer *)&draw, stuff->drawable,
75265b04b38Smrg				      XRC_DRAWABLE, client, DixWriteAccess);
75365b04b38Smrg    if (result != Success)
75465b04b38Smrg        return (result == BadValue) ? BadDrawable : result;
75565b04b38Smrg
75665b04b38Smrg    result = dixLookupResourceByType((pointer *)&gc, stuff->gc,
75765b04b38Smrg				     XRT_GC, client, DixReadAccess);
75865b04b38Smrg    if (result != Success)
75965b04b38Smrg        return result;
76065b04b38Smrg
76165b04b38Smrg    isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
76265b04b38Smrg
76365b04b38Smrg    orig_x = stuff->dstX;
76465b04b38Smrg    orig_y = stuff->dstY;
76565b04b38Smrg    sendEvent = stuff->sendEvent;
76665b04b38Smrg    stuff->sendEvent = 0;
76765b04b38Smrg    FOR_NSCREENS(j) {
76865b04b38Smrg	if(!j) stuff->sendEvent = sendEvent;
76965b04b38Smrg	stuff->drawable = draw->info[j].id;
77065b04b38Smrg	stuff->gc = gc->info[j].id;
77165b04b38Smrg	if (isRoot) {
77265b04b38Smrg	    stuff->dstX = orig_x - screenInfo.screens[j]->x;
77365b04b38Smrg	    stuff->dstY = orig_y - screenInfo.screens[j]->y;
77465b04b38Smrg	}
77565b04b38Smrg	result = ProcShmPutImage(client);
77665b04b38Smrg	if(result != Success) break;
77765b04b38Smrg    }
77865b04b38Smrg    return result;
77965b04b38Smrg}
78065b04b38Smrg
78165b04b38Smrgstatic int
78265b04b38SmrgProcPanoramiXShmGetImage(ClientPtr client)
78365b04b38Smrg{
78465b04b38Smrg    PanoramiXRes	*draw;
78565b04b38Smrg    DrawablePtr 	*drawables;
78665b04b38Smrg    DrawablePtr 	pDraw;
78765b04b38Smrg    xShmGetImageReply	xgi;
78865b04b38Smrg    ShmDescPtr		shmdesc;
78965b04b38Smrg    int         	i, x, y, w, h, format, rc;
79065b04b38Smrg    Mask		plane = 0, planemask;
79165b04b38Smrg    long		lenPer = 0, length, widthBytesLine;
79265b04b38Smrg    Bool		isRoot;
79365b04b38Smrg
79465b04b38Smrg    REQUEST(xShmGetImageReq);
79565b04b38Smrg
79665b04b38Smrg    REQUEST_SIZE_MATCH(xShmGetImageReq);
79765b04b38Smrg
79865b04b38Smrg    if ((stuff->format != XYPixmap) && (stuff->format != ZPixmap)) {
79965b04b38Smrg	client->errorValue = stuff->format;
80065b04b38Smrg        return BadValue;
80165b04b38Smrg    }
80265b04b38Smrg
80365b04b38Smrg    rc = dixLookupResourceByClass((pointer *)&draw, stuff->drawable,
80465b04b38Smrg				  XRC_DRAWABLE, client, DixWriteAccess);
80565b04b38Smrg    if (rc != Success)
80665b04b38Smrg	return (rc == BadValue) ? BadDrawable : rc;
80765b04b38Smrg
80865b04b38Smrg    if (draw->type == XRT_PIXMAP)
80965b04b38Smrg	return ProcShmGetImage(client);
81065b04b38Smrg
81165b04b38Smrg    rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0,
81265b04b38Smrg			   DixReadAccess);
81365b04b38Smrg    if (rc != Success)
81465b04b38Smrg	return rc;
81565b04b38Smrg
81665b04b38Smrg    VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client);
81765b04b38Smrg
81865b04b38Smrg    x = stuff->x;
81965b04b38Smrg    y = stuff->y;
82065b04b38Smrg    w = stuff->width;
82165b04b38Smrg    h = stuff->height;
82265b04b38Smrg    format = stuff->format;
82365b04b38Smrg    planemask = stuff->planeMask;
82465b04b38Smrg
82565b04b38Smrg    isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root;
82665b04b38Smrg
82765b04b38Smrg    if(isRoot) {
82865b04b38Smrg      if( /* check for being onscreen */
82965b04b38Smrg	x < 0 || x + w > PanoramiXPixWidth ||
83065b04b38Smrg	y < 0 || y + h > PanoramiXPixHeight )
83165b04b38Smrg	    return BadMatch;
83265b04b38Smrg    } else {
83365b04b38Smrg      if( /* check for being onscreen */
83465b04b38Smrg	screenInfo.screens[0]->x + pDraw->x + x < 0 ||
83565b04b38Smrg	screenInfo.screens[0]->x + pDraw->x + x + w > PanoramiXPixWidth ||
83665b04b38Smrg	screenInfo.screens[0]->y + pDraw->y + y < 0 ||
83765b04b38Smrg	screenInfo.screens[0]->y + pDraw->y + y + h > PanoramiXPixHeight ||
83865b04b38Smrg	 /* check for being inside of border */
83965b04b38Smrg       	x < - wBorderWidth((WindowPtr)pDraw) ||
84065b04b38Smrg	x + w > wBorderWidth((WindowPtr)pDraw) + (int)pDraw->width ||
84165b04b38Smrg	y < -wBorderWidth((WindowPtr)pDraw) ||
84265b04b38Smrg	y + h > wBorderWidth ((WindowPtr)pDraw) + (int)pDraw->height)
84365b04b38Smrg	    return BadMatch;
84465b04b38Smrg    }
84565b04b38Smrg
8464202a189Smrg    drawables = calloc(PanoramiXNumScreens, sizeof(DrawablePtr));
8474202a189Smrg    if(!drawables)
8484202a189Smrg	return BadAlloc;
8494202a189Smrg
85005b261ecSmrg    drawables[0] = pDraw;
85105b261ecSmrg    for(i = 1; i < PanoramiXNumScreens; i++) {
85205b261ecSmrg	rc = dixLookupDrawable(drawables+i, draw->info[i].id, client, 0,
8534642e01fSmrg			       DixReadAccess);
85405b261ecSmrg	if (rc != Success)
8554202a189Smrg	{
8564202a189Smrg	    free(drawables);
85705b261ecSmrg	    return rc;
8584202a189Smrg	}
85905b261ecSmrg    }
86005b261ecSmrg
86105b261ecSmrg    xgi.visual = wVisual(((WindowPtr)pDraw));
86205b261ecSmrg    xgi.type = X_Reply;
86305b261ecSmrg    xgi.length = 0;
86405b261ecSmrg    xgi.sequenceNumber = client->sequence;
86505b261ecSmrg    xgi.depth = pDraw->depth;
86605b261ecSmrg
86705b261ecSmrg    if(format == ZPixmap) {
86805b261ecSmrg	widthBytesLine = PixmapBytePad(w, pDraw->depth);
86905b261ecSmrg	length = widthBytesLine * h;
87005b261ecSmrg    } else {
87105b261ecSmrg	widthBytesLine = PixmapBytePad(w, 1);
87205b261ecSmrg	lenPer = widthBytesLine * h;
87305b261ecSmrg	plane = ((Mask)1) << (pDraw->depth - 1);
87405b261ecSmrg	length = lenPer * Ones(planemask & (plane | (plane - 1)));
87505b261ecSmrg    }
87605b261ecSmrg
87705b261ecSmrg    VERIFY_SHMSIZE(shmdesc, stuff->offset, length, client);
87805b261ecSmrg    xgi.size = length;
87905b261ecSmrg
88005b261ecSmrg    if (length == 0) {/* nothing to do */ }
88105b261ecSmrg    else if (format == ZPixmap) {
88205b261ecSmrg	    XineramaGetImageData(drawables, x, y, w, h, format, planemask,
88305b261ecSmrg					shmdesc->addr + stuff->offset,
88405b261ecSmrg					widthBytesLine, isRoot);
88505b261ecSmrg    } else {
88605b261ecSmrg
88705b261ecSmrg	length = stuff->offset;
88805b261ecSmrg        for (; plane; plane >>= 1) {
88905b261ecSmrg	    if (planemask & plane) {
89005b261ecSmrg		XineramaGetImageData(drawables, x, y, w, h,
89105b261ecSmrg				     format, plane, shmdesc->addr + length,
89205b261ecSmrg				     widthBytesLine, isRoot);
89305b261ecSmrg		length += lenPer;
89405b261ecSmrg	    }
89505b261ecSmrg	}
89605b261ecSmrg    }
8974202a189Smrg    free(drawables);
89805b261ecSmrg
89905b261ecSmrg    if (client->swapped) {
9004642e01fSmrg	int n;
90105b261ecSmrg    	swaps(&xgi.sequenceNumber, n);
90205b261ecSmrg    	swapl(&xgi.length, n);
90305b261ecSmrg	swapl(&xgi.visual, n);
90405b261ecSmrg	swapl(&xgi.size, n);
90505b261ecSmrg    }
90605b261ecSmrg    WriteToClient(client, sizeof(xShmGetImageReply), (char *)&xgi);
90705b261ecSmrg
9084202a189Smrg    return Success;
90905b261ecSmrg}
91005b261ecSmrg
91105b261ecSmrgstatic int
9124642e01fSmrgProcPanoramiXShmCreatePixmap(ClientPtr client)
91305b261ecSmrg{
91405b261ecSmrg    ScreenPtr pScreen = NULL;
91505b261ecSmrg    PixmapPtr pMap = NULL;
91605b261ecSmrg    DrawablePtr pDraw;
91705b261ecSmrg    DepthPtr pDepth;
91805b261ecSmrg    int i, j, result, rc;
91905b261ecSmrg    ShmDescPtr shmdesc;
92005b261ecSmrg    REQUEST(xShmCreatePixmapReq);
92105b261ecSmrg    unsigned int width, height, depth;
92205b261ecSmrg    unsigned long size;
92305b261ecSmrg    PanoramiXRes *newPix;
92405b261ecSmrg
92505b261ecSmrg    REQUEST_SIZE_MATCH(xShmCreatePixmapReq);
92605b261ecSmrg    client->errorValue = stuff->pid;
92705b261ecSmrg    if (!sharedPixmaps)
92805b261ecSmrg	return BadImplementation;
92905b261ecSmrg    LEGAL_NEW_RESOURCE(stuff->pid, client);
93005b261ecSmrg    rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY,
9314642e01fSmrg			   DixGetAttrAccess);
93205b261ecSmrg    if (rc != Success)
93305b261ecSmrg	return rc;
93405b261ecSmrg
93505b261ecSmrg    VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client);
93605b261ecSmrg
93705b261ecSmrg    width = stuff->width;
93805b261ecSmrg    height = stuff->height;
93905b261ecSmrg    depth = stuff->depth;
94005b261ecSmrg    if (!width || !height || !depth)
94105b261ecSmrg    {
94205b261ecSmrg	client->errorValue = 0;
94305b261ecSmrg        return BadValue;
94405b261ecSmrg    }
94505b261ecSmrg    if (width > 32767 || height > 32767)
94605b261ecSmrg        return BadAlloc;
94705b261ecSmrg
94805b261ecSmrg    if (stuff->depth != 1)
94905b261ecSmrg    {
95005b261ecSmrg        pDepth = pDraw->pScreen->allowedDepths;
95105b261ecSmrg        for (i=0; i<pDraw->pScreen->numDepths; i++, pDepth++)
95205b261ecSmrg	   if (pDepth->depth == stuff->depth)
95305b261ecSmrg               goto CreatePmap;
95405b261ecSmrg	client->errorValue = stuff->depth;
95505b261ecSmrg        return BadValue;
95605b261ecSmrg    }
95705b261ecSmrg
95805b261ecSmrgCreatePmap:
95905b261ecSmrg    size = PixmapBytePad(width, depth) * height;
96005b261ecSmrg    if (sizeof(size) == 4 && BitsPerPixel(depth) > 8) {
96105b261ecSmrg        if (size < width * height)
96205b261ecSmrg            return BadAlloc;
96305b261ecSmrg    }
96405b261ecSmrg    /* thankfully, offset is unsigned */
96505b261ecSmrg    if (stuff->offset + size < size)
96605b261ecSmrg	return BadAlloc;
96705b261ecSmrg
96805b261ecSmrg    VERIFY_SHMSIZE(shmdesc, stuff->offset, size, client);
96905b261ecSmrg
9704202a189Smrg    if(!(newPix = malloc(sizeof(PanoramiXRes))))
97105b261ecSmrg	return BadAlloc;
97205b261ecSmrg
97305b261ecSmrg    newPix->type = XRT_PIXMAP;
97405b261ecSmrg    newPix->u.pix.shared = TRUE;
97505b261ecSmrg    newPix->info[0].id = stuff->pid;
97605b261ecSmrg    for(j = 1; j < PanoramiXNumScreens; j++)
97705b261ecSmrg	newPix->info[j].id = FakeClientID(client->index);
97805b261ecSmrg
9794202a189Smrg    result = Success;
98005b261ecSmrg
98105b261ecSmrg    FOR_NSCREENS(j) {
9824202a189Smrg	ShmScrPrivateRec *screen_priv;
98305b261ecSmrg	pScreen = screenInfo.screens[j];
98405b261ecSmrg
9854202a189Smrg	screen_priv = ShmGetScreenPriv(pScreen);
9864202a189Smrg	pMap = (*screen_priv->shmFuncs->CreatePixmap)(pScreen,
98705b261ecSmrg				stuff->width, stuff->height, stuff->depth,
98805b261ecSmrg				shmdesc->addr + stuff->offset);
98905b261ecSmrg
99005b261ecSmrg	if (pMap) {
9914202a189Smrg	    dixSetPrivate(&pMap->devPrivates, shmPixmapPrivateKey, shmdesc);
99205b261ecSmrg            shmdesc->refcnt++;
99305b261ecSmrg	    pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
99405b261ecSmrg	    pMap->drawable.id = newPix->info[j].id;
99505b261ecSmrg	    if (!AddResource(newPix->info[j].id, RT_PIXMAP, (pointer)pMap)) {
99605b261ecSmrg		(*pScreen->DestroyPixmap)(pMap);
99705b261ecSmrg		result = BadAlloc;
99805b261ecSmrg		break;
99905b261ecSmrg	    }
100005b261ecSmrg	} else {
100105b261ecSmrg	   result = BadAlloc;
100205b261ecSmrg	   break;
100305b261ecSmrg	}
100405b261ecSmrg    }
100505b261ecSmrg
100605b261ecSmrg    if(result == BadAlloc) {
100705b261ecSmrg	while(j--) {
100805b261ecSmrg	    (*pScreen->DestroyPixmap)(pMap);
100905b261ecSmrg	    FreeResource(newPix->info[j].id, RT_NONE);
101005b261ecSmrg	}
10114202a189Smrg	free(newPix);
101205b261ecSmrg    } else
101305b261ecSmrg	AddResource(stuff->pid, XRT_PIXMAP, newPix);
101405b261ecSmrg
101505b261ecSmrg    return result;
101605b261ecSmrg}
101705b261ecSmrg#endif
101805b261ecSmrg
101905b261ecSmrgstatic PixmapPtr
10204642e01fSmrgfbShmCreatePixmap (ScreenPtr pScreen,
10214642e01fSmrg		   int width, int height, int depth, char *addr)
102205b261ecSmrg{
10234642e01fSmrg    PixmapPtr pPixmap;
102405b261ecSmrg
10254642e01fSmrg    pPixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, pScreen->rootDepth, 0);
102605b261ecSmrg    if (!pPixmap)
102705b261ecSmrg	return NullPixmap;
102805b261ecSmrg
102905b261ecSmrg    if (!(*pScreen->ModifyPixmapHeader)(pPixmap, width, height, depth,
103005b261ecSmrg	    BitsPerPixel(depth), PixmapBytePad(width, depth), (pointer)addr)) {
103105b261ecSmrg	(*pScreen->DestroyPixmap)(pPixmap);
103205b261ecSmrg	return NullPixmap;
103305b261ecSmrg    }
103405b261ecSmrg    return pPixmap;
103505b261ecSmrg}
103605b261ecSmrg
103705b261ecSmrgstatic int
10384642e01fSmrgProcShmCreatePixmap(ClientPtr client)
103905b261ecSmrg{
104005b261ecSmrg    PixmapPtr pMap;
104105b261ecSmrg    DrawablePtr pDraw;
104205b261ecSmrg    DepthPtr pDepth;
10434642e01fSmrg    int i, rc;
104405b261ecSmrg    ShmDescPtr shmdesc;
10454202a189Smrg    ShmScrPrivateRec *screen_priv;
104605b261ecSmrg    REQUEST(xShmCreatePixmapReq);
104705b261ecSmrg    unsigned int width, height, depth;
104805b261ecSmrg    unsigned long size;
104905b261ecSmrg
105005b261ecSmrg    REQUEST_SIZE_MATCH(xShmCreatePixmapReq);
105105b261ecSmrg    client->errorValue = stuff->pid;
105205b261ecSmrg    if (!sharedPixmaps)
105305b261ecSmrg	return BadImplementation;
105405b261ecSmrg    LEGAL_NEW_RESOURCE(stuff->pid, client);
105505b261ecSmrg    rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY,
10564642e01fSmrg			   DixGetAttrAccess);
105705b261ecSmrg    if (rc != Success)
105805b261ecSmrg	return rc;
105905b261ecSmrg
106005b261ecSmrg    VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client);
106105b261ecSmrg
106205b261ecSmrg    width = stuff->width;
106305b261ecSmrg    height = stuff->height;
106405b261ecSmrg    depth = stuff->depth;
106505b261ecSmrg    if (!width || !height || !depth)
106605b261ecSmrg    {
106705b261ecSmrg	client->errorValue = 0;
106805b261ecSmrg        return BadValue;
106905b261ecSmrg    }
107005b261ecSmrg    if (width > 32767 || height > 32767)
107105b261ecSmrg	return BadAlloc;
107205b261ecSmrg
107305b261ecSmrg    if (stuff->depth != 1)
107405b261ecSmrg    {
107505b261ecSmrg        pDepth = pDraw->pScreen->allowedDepths;
107605b261ecSmrg        for (i=0; i<pDraw->pScreen->numDepths; i++, pDepth++)
107705b261ecSmrg	   if (pDepth->depth == stuff->depth)
107805b261ecSmrg               goto CreatePmap;
107905b261ecSmrg	client->errorValue = stuff->depth;
108005b261ecSmrg        return BadValue;
108105b261ecSmrg    }
108205b261ecSmrg
108305b261ecSmrgCreatePmap:
108405b261ecSmrg    size = PixmapBytePad(width, depth) * height;
108505b261ecSmrg    if (sizeof(size) == 4 && BitsPerPixel(depth) > 8) {
108605b261ecSmrg	if (size < width * height)
108705b261ecSmrg	    return BadAlloc;
108805b261ecSmrg    }
108905b261ecSmrg    /* thankfully, offset is unsigned */
109005b261ecSmrg    if (stuff->offset + size < size)
109105b261ecSmrg	return BadAlloc;
109205b261ecSmrg
109305b261ecSmrg    VERIFY_SHMSIZE(shmdesc, stuff->offset, size, client);
10944202a189Smrg    screen_priv = ShmGetScreenPriv(pDraw->pScreen);
10954202a189Smrg    pMap = (*screen_priv->shmFuncs->CreatePixmap)(
109605b261ecSmrg			    pDraw->pScreen, stuff->width,
109705b261ecSmrg			    stuff->height, stuff->depth,
109805b261ecSmrg			    shmdesc->addr + stuff->offset);
109905b261ecSmrg    if (pMap)
110005b261ecSmrg    {
11014642e01fSmrg	rc = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pid, RT_PIXMAP,
11024642e01fSmrg		      pMap, RT_NONE, NULL, DixCreateAccess);
11034642e01fSmrg	if (rc != Success) {
11044642e01fSmrg	    pDraw->pScreen->DestroyPixmap(pMap);
11054642e01fSmrg	    return rc;
11064642e01fSmrg	}
11074202a189Smrg	dixSetPrivate(&pMap->devPrivates, shmPixmapPrivateKey, shmdesc);
110805b261ecSmrg	shmdesc->refcnt++;
110905b261ecSmrg	pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER;
111005b261ecSmrg	pMap->drawable.id = stuff->pid;
111105b261ecSmrg	if (AddResource(stuff->pid, RT_PIXMAP, (pointer)pMap))
111205b261ecSmrg	{
11134202a189Smrg	    return Success;
111405b261ecSmrg	}
11154642e01fSmrg	pDraw->pScreen->DestroyPixmap(pMap);
111605b261ecSmrg    }
11174202a189Smrg    return BadAlloc;
111805b261ecSmrg}
111905b261ecSmrg
112005b261ecSmrgstatic int
11214642e01fSmrgProcShmDispatch (ClientPtr client)
112205b261ecSmrg{
112305b261ecSmrg    REQUEST(xReq);
112405b261ecSmrg    switch (stuff->data)
112505b261ecSmrg    {
112605b261ecSmrg    case X_ShmQueryVersion:
112705b261ecSmrg	return ProcShmQueryVersion(client);
112805b261ecSmrg    case X_ShmAttach:
112905b261ecSmrg	return ProcShmAttach(client);
113005b261ecSmrg    case X_ShmDetach:
113105b261ecSmrg	return ProcShmDetach(client);
113205b261ecSmrg    case X_ShmPutImage:
113305b261ecSmrg#ifdef PANORAMIX
113405b261ecSmrg        if ( !noPanoramiXExtension )
113505b261ecSmrg	   return ProcPanoramiXShmPutImage(client);
113605b261ecSmrg#endif
113705b261ecSmrg	return ProcShmPutImage(client);
113805b261ecSmrg    case X_ShmGetImage:
113905b261ecSmrg#ifdef PANORAMIX
114005b261ecSmrg        if ( !noPanoramiXExtension )
114105b261ecSmrg	   return ProcPanoramiXShmGetImage(client);
114205b261ecSmrg#endif
114305b261ecSmrg	return ProcShmGetImage(client);
114405b261ecSmrg    case X_ShmCreatePixmap:
114505b261ecSmrg#ifdef PANORAMIX
114605b261ecSmrg        if ( !noPanoramiXExtension )
114705b261ecSmrg	   return ProcPanoramiXShmCreatePixmap(client);
114805b261ecSmrg#endif
114905b261ecSmrg	   return ProcShmCreatePixmap(client);
115005b261ecSmrg    default:
115105b261ecSmrg	return BadRequest;
115205b261ecSmrg    }
115305b261ecSmrg}
115405b261ecSmrg
115505b261ecSmrgstatic void
11564642e01fSmrgSShmCompletionEvent(xShmCompletionEvent *from, xShmCompletionEvent *to)
115705b261ecSmrg{
115805b261ecSmrg    to->type = from->type;
115905b261ecSmrg    cpswaps(from->sequenceNumber, to->sequenceNumber);
116005b261ecSmrg    cpswapl(from->drawable, to->drawable);
116105b261ecSmrg    cpswaps(from->minorEvent, to->minorEvent);
116205b261ecSmrg    to->majorEvent = from->majorEvent;
116305b261ecSmrg    cpswapl(from->shmseg, to->shmseg);
116405b261ecSmrg    cpswapl(from->offset, to->offset);
116505b261ecSmrg}
116605b261ecSmrg
116705b261ecSmrgstatic int
11684642e01fSmrgSProcShmQueryVersion(ClientPtr client)
116905b261ecSmrg{
11704642e01fSmrg    int n;
117105b261ecSmrg    REQUEST(xShmQueryVersionReq);
117205b261ecSmrg
117305b261ecSmrg    swaps(&stuff->length, n);
117405b261ecSmrg    return ProcShmQueryVersion(client);
117505b261ecSmrg}
117605b261ecSmrg
117705b261ecSmrgstatic int
11784642e01fSmrgSProcShmAttach(ClientPtr client)
117905b261ecSmrg{
11804642e01fSmrg    int n;
118105b261ecSmrg    REQUEST(xShmAttachReq);
118205b261ecSmrg    swaps(&stuff->length, n);
118305b261ecSmrg    REQUEST_SIZE_MATCH(xShmAttachReq);
118405b261ecSmrg    swapl(&stuff->shmseg, n);
118505b261ecSmrg    swapl(&stuff->shmid, n);
118605b261ecSmrg    return ProcShmAttach(client);
118705b261ecSmrg}
118805b261ecSmrg
118905b261ecSmrgstatic int
11904642e01fSmrgSProcShmDetach(ClientPtr client)
119105b261ecSmrg{
11924642e01fSmrg    int n;
119305b261ecSmrg    REQUEST(xShmDetachReq);
119405b261ecSmrg    swaps(&stuff->length, n);
119505b261ecSmrg    REQUEST_SIZE_MATCH(xShmDetachReq);
119605b261ecSmrg    swapl(&stuff->shmseg, n);
119705b261ecSmrg    return ProcShmDetach(client);
119805b261ecSmrg}
119905b261ecSmrg
120005b261ecSmrgstatic int
12014642e01fSmrgSProcShmPutImage(ClientPtr client)
120205b261ecSmrg{
12034642e01fSmrg    int n;
120405b261ecSmrg    REQUEST(xShmPutImageReq);
120505b261ecSmrg    swaps(&stuff->length, n);
120605b261ecSmrg    REQUEST_SIZE_MATCH(xShmPutImageReq);
120705b261ecSmrg    swapl(&stuff->drawable, n);
120805b261ecSmrg    swapl(&stuff->gc, n);
120905b261ecSmrg    swaps(&stuff->totalWidth, n);
121005b261ecSmrg    swaps(&stuff->totalHeight, n);
121105b261ecSmrg    swaps(&stuff->srcX, n);
121205b261ecSmrg    swaps(&stuff->srcY, n);
121305b261ecSmrg    swaps(&stuff->srcWidth, n);
121405b261ecSmrg    swaps(&stuff->srcHeight, n);
121505b261ecSmrg    swaps(&stuff->dstX, n);
121605b261ecSmrg    swaps(&stuff->dstY, n);
121705b261ecSmrg    swapl(&stuff->shmseg, n);
121805b261ecSmrg    swapl(&stuff->offset, n);
121905b261ecSmrg    return ProcShmPutImage(client);
122005b261ecSmrg}
122105b261ecSmrg
122205b261ecSmrgstatic int
12234642e01fSmrgSProcShmGetImage(ClientPtr client)
122405b261ecSmrg{
12254642e01fSmrg    int n;
122605b261ecSmrg    REQUEST(xShmGetImageReq);
122705b261ecSmrg    swaps(&stuff->length, n);
122805b261ecSmrg    REQUEST_SIZE_MATCH(xShmGetImageReq);
122905b261ecSmrg    swapl(&stuff->drawable, n);
123005b261ecSmrg    swaps(&stuff->x, n);
123105b261ecSmrg    swaps(&stuff->y, n);
123205b261ecSmrg    swaps(&stuff->width, n);
123305b261ecSmrg    swaps(&stuff->height, n);
123405b261ecSmrg    swapl(&stuff->planeMask, n);
123505b261ecSmrg    swapl(&stuff->shmseg, n);
123605b261ecSmrg    swapl(&stuff->offset, n);
123705b261ecSmrg    return ProcShmGetImage(client);
123805b261ecSmrg}
123905b261ecSmrg
124005b261ecSmrgstatic int
12414642e01fSmrgSProcShmCreatePixmap(ClientPtr client)
124205b261ecSmrg{
12434642e01fSmrg    int n;
124405b261ecSmrg    REQUEST(xShmCreatePixmapReq);
124505b261ecSmrg    swaps(&stuff->length, n);
124605b261ecSmrg    REQUEST_SIZE_MATCH(xShmCreatePixmapReq);
124705b261ecSmrg    swapl(&stuff->pid, n);
124805b261ecSmrg    swapl(&stuff->drawable, n);
124905b261ecSmrg    swaps(&stuff->width, n);
125005b261ecSmrg    swaps(&stuff->height, n);
125105b261ecSmrg    swapl(&stuff->shmseg, n);
125205b261ecSmrg    swapl(&stuff->offset, n);
125305b261ecSmrg    return ProcShmCreatePixmap(client);
125405b261ecSmrg}
125505b261ecSmrg
125605b261ecSmrgstatic int
12574642e01fSmrgSProcShmDispatch (ClientPtr client)
125805b261ecSmrg{
125905b261ecSmrg    REQUEST(xReq);
126005b261ecSmrg    switch (stuff->data)
126105b261ecSmrg    {
126205b261ecSmrg    case X_ShmQueryVersion:
126305b261ecSmrg	return SProcShmQueryVersion(client);
126405b261ecSmrg    case X_ShmAttach:
126505b261ecSmrg	return SProcShmAttach(client);
126605b261ecSmrg    case X_ShmDetach:
126705b261ecSmrg	return SProcShmDetach(client);
126805b261ecSmrg    case X_ShmPutImage:
126905b261ecSmrg	return SProcShmPutImage(client);
127005b261ecSmrg    case X_ShmGetImage:
127105b261ecSmrg	return SProcShmGetImage(client);
127205b261ecSmrg    case X_ShmCreatePixmap:
127305b261ecSmrg	return SProcShmCreatePixmap(client);
127405b261ecSmrg    default:
127505b261ecSmrg	return BadRequest;
127605b261ecSmrg    }
127705b261ecSmrg}
127865b04b38Smrg
127965b04b38Smrgvoid
128065b04b38SmrgShmExtensionInit(INITARGS)
128165b04b38Smrg{
128265b04b38Smrg    ExtensionEntry *extEntry;
128365b04b38Smrg    int i;
128465b04b38Smrg
128565b04b38Smrg#ifdef MUST_CHECK_FOR_SHM_SYSCALL
128665b04b38Smrg    if (!CheckForShmSyscall())
128765b04b38Smrg    {
128865b04b38Smrg	ErrorF("MIT-SHM extension disabled due to lack of kernel support\n");
128965b04b38Smrg	return;
129065b04b38Smrg    }
129165b04b38Smrg#endif
129265b04b38Smrg
129365b04b38Smrg    if (!ShmRegisterPrivates())
129465b04b38Smrg	return;
129565b04b38Smrg
129665b04b38Smrg    sharedPixmaps = xFalse;
129765b04b38Smrg    {
129865b04b38Smrg      sharedPixmaps = xTrue;
129965b04b38Smrg      for (i = 0; i < screenInfo.numScreens; i++)
130065b04b38Smrg      {
130165b04b38Smrg	ShmScrPrivateRec *screen_priv = ShmInitScreenPriv(screenInfo.screens[i]);
130265b04b38Smrg	if (!screen_priv->shmFuncs)
130365b04b38Smrg	    screen_priv->shmFuncs = &miFuncs;
130465b04b38Smrg	if (!screen_priv->shmFuncs->CreatePixmap)
130565b04b38Smrg	    sharedPixmaps = xFalse;
130665b04b38Smrg      }
130765b04b38Smrg      if (sharedPixmaps)
130865b04b38Smrg	for (i = 0; i < screenInfo.numScreens; i++)
130965b04b38Smrg	{
131065b04b38Smrg	    ShmScrPrivateRec *screen_priv = ShmGetScreenPriv(screenInfo.screens[i]);
131165b04b38Smrg	    screen_priv->destroyPixmap = screenInfo.screens[i]->DestroyPixmap;
131265b04b38Smrg	    screenInfo.screens[i]->DestroyPixmap = ShmDestroyPixmap;
131365b04b38Smrg	}
131465b04b38Smrg    }
131565b04b38Smrg    ShmSegType = CreateNewResourceType(ShmDetachSegment, "ShmSeg");
131665b04b38Smrg    if (ShmSegType &&
131765b04b38Smrg	(extEntry = AddExtension(SHMNAME, ShmNumberEvents, ShmNumberErrors,
131865b04b38Smrg				 ProcShmDispatch, SProcShmDispatch,
131965b04b38Smrg				 ShmResetProc, StandardMinorOpcode)))
132065b04b38Smrg    {
132165b04b38Smrg	ShmReqCode = (unsigned char)extEntry->base;
132265b04b38Smrg	ShmCompletionCode = extEntry->eventBase;
132365b04b38Smrg	BadShmSegCode = extEntry->errorBase;
132465b04b38Smrg	SetResourceTypeErrorValue(ShmSegType, BadShmSegCode);
132565b04b38Smrg	EventSwapVector[ShmCompletionCode] = (EventSwapPtr) SShmCompletionEvent;
132665b04b38Smrg    }
132765b04b38Smrg}
1328