shm.c revision 45bb0b75
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 48545bb0b75Smrg if (format == ZPixmap || (format == XYPixmap && 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 result = BadAlloc; 99705b261ecSmrg break; 99805b261ecSmrg } 99905b261ecSmrg } else { 100005b261ecSmrg result = BadAlloc; 100105b261ecSmrg break; 100205b261ecSmrg } 100305b261ecSmrg } 100405b261ecSmrg 100505b261ecSmrg if(result == BadAlloc) { 100645bb0b75Smrg while(j--) 100705b261ecSmrg FreeResource(newPix->info[j].id, RT_NONE); 10084202a189Smrg free(newPix); 100905b261ecSmrg } else 101005b261ecSmrg AddResource(stuff->pid, XRT_PIXMAP, newPix); 101105b261ecSmrg 101205b261ecSmrg return result; 101305b261ecSmrg} 101405b261ecSmrg#endif 101505b261ecSmrg 101605b261ecSmrgstatic PixmapPtr 10174642e01fSmrgfbShmCreatePixmap (ScreenPtr pScreen, 10184642e01fSmrg int width, int height, int depth, char *addr) 101905b261ecSmrg{ 10204642e01fSmrg PixmapPtr pPixmap; 102105b261ecSmrg 10224642e01fSmrg pPixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, pScreen->rootDepth, 0); 102305b261ecSmrg if (!pPixmap) 102405b261ecSmrg return NullPixmap; 102505b261ecSmrg 102605b261ecSmrg if (!(*pScreen->ModifyPixmapHeader)(pPixmap, width, height, depth, 102705b261ecSmrg BitsPerPixel(depth), PixmapBytePad(width, depth), (pointer)addr)) { 102805b261ecSmrg (*pScreen->DestroyPixmap)(pPixmap); 102905b261ecSmrg return NullPixmap; 103005b261ecSmrg } 103105b261ecSmrg return pPixmap; 103205b261ecSmrg} 103305b261ecSmrg 103405b261ecSmrgstatic int 10354642e01fSmrgProcShmCreatePixmap(ClientPtr client) 103605b261ecSmrg{ 103705b261ecSmrg PixmapPtr pMap; 103805b261ecSmrg DrawablePtr pDraw; 103905b261ecSmrg DepthPtr pDepth; 10404642e01fSmrg int i, rc; 104105b261ecSmrg ShmDescPtr shmdesc; 10424202a189Smrg ShmScrPrivateRec *screen_priv; 104305b261ecSmrg REQUEST(xShmCreatePixmapReq); 104405b261ecSmrg unsigned int width, height, depth; 104505b261ecSmrg unsigned long size; 104605b261ecSmrg 104705b261ecSmrg REQUEST_SIZE_MATCH(xShmCreatePixmapReq); 104805b261ecSmrg client->errorValue = stuff->pid; 104905b261ecSmrg if (!sharedPixmaps) 105005b261ecSmrg return BadImplementation; 105105b261ecSmrg LEGAL_NEW_RESOURCE(stuff->pid, client); 105205b261ecSmrg rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY, 10534642e01fSmrg DixGetAttrAccess); 105405b261ecSmrg if (rc != Success) 105505b261ecSmrg return rc; 105605b261ecSmrg 105705b261ecSmrg VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); 105805b261ecSmrg 105905b261ecSmrg width = stuff->width; 106005b261ecSmrg height = stuff->height; 106105b261ecSmrg depth = stuff->depth; 106205b261ecSmrg if (!width || !height || !depth) 106305b261ecSmrg { 106405b261ecSmrg client->errorValue = 0; 106505b261ecSmrg return BadValue; 106605b261ecSmrg } 106705b261ecSmrg if (width > 32767 || height > 32767) 106805b261ecSmrg return BadAlloc; 106905b261ecSmrg 107005b261ecSmrg if (stuff->depth != 1) 107105b261ecSmrg { 107205b261ecSmrg pDepth = pDraw->pScreen->allowedDepths; 107305b261ecSmrg for (i=0; i<pDraw->pScreen->numDepths; i++, pDepth++) 107405b261ecSmrg if (pDepth->depth == stuff->depth) 107505b261ecSmrg goto CreatePmap; 107605b261ecSmrg client->errorValue = stuff->depth; 107705b261ecSmrg return BadValue; 107805b261ecSmrg } 107905b261ecSmrg 108005b261ecSmrgCreatePmap: 108105b261ecSmrg size = PixmapBytePad(width, depth) * height; 108205b261ecSmrg if (sizeof(size) == 4 && BitsPerPixel(depth) > 8) { 108305b261ecSmrg if (size < width * height) 108405b261ecSmrg return BadAlloc; 108505b261ecSmrg } 108605b261ecSmrg /* thankfully, offset is unsigned */ 108705b261ecSmrg if (stuff->offset + size < size) 108805b261ecSmrg return BadAlloc; 108905b261ecSmrg 109005b261ecSmrg VERIFY_SHMSIZE(shmdesc, stuff->offset, size, client); 10914202a189Smrg screen_priv = ShmGetScreenPriv(pDraw->pScreen); 10924202a189Smrg pMap = (*screen_priv->shmFuncs->CreatePixmap)( 109305b261ecSmrg pDraw->pScreen, stuff->width, 109405b261ecSmrg stuff->height, stuff->depth, 109505b261ecSmrg shmdesc->addr + stuff->offset); 109605b261ecSmrg if (pMap) 109705b261ecSmrg { 10984642e01fSmrg rc = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pid, RT_PIXMAP, 10994642e01fSmrg pMap, RT_NONE, NULL, DixCreateAccess); 11004642e01fSmrg if (rc != Success) { 11014642e01fSmrg pDraw->pScreen->DestroyPixmap(pMap); 11024642e01fSmrg return rc; 11034642e01fSmrg } 11044202a189Smrg dixSetPrivate(&pMap->devPrivates, shmPixmapPrivateKey, shmdesc); 110505b261ecSmrg shmdesc->refcnt++; 110605b261ecSmrg pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER; 110705b261ecSmrg pMap->drawable.id = stuff->pid; 110805b261ecSmrg if (AddResource(stuff->pid, RT_PIXMAP, (pointer)pMap)) 110905b261ecSmrg { 11104202a189Smrg return Success; 111105b261ecSmrg } 111205b261ecSmrg } 11134202a189Smrg return BadAlloc; 111405b261ecSmrg} 111505b261ecSmrg 111605b261ecSmrgstatic int 11174642e01fSmrgProcShmDispatch (ClientPtr client) 111805b261ecSmrg{ 111905b261ecSmrg REQUEST(xReq); 112005b261ecSmrg switch (stuff->data) 112105b261ecSmrg { 112205b261ecSmrg case X_ShmQueryVersion: 112305b261ecSmrg return ProcShmQueryVersion(client); 112405b261ecSmrg case X_ShmAttach: 112505b261ecSmrg return ProcShmAttach(client); 112605b261ecSmrg case X_ShmDetach: 112705b261ecSmrg return ProcShmDetach(client); 112805b261ecSmrg case X_ShmPutImage: 112905b261ecSmrg#ifdef PANORAMIX 113005b261ecSmrg if ( !noPanoramiXExtension ) 113105b261ecSmrg return ProcPanoramiXShmPutImage(client); 113205b261ecSmrg#endif 113305b261ecSmrg return ProcShmPutImage(client); 113405b261ecSmrg case X_ShmGetImage: 113505b261ecSmrg#ifdef PANORAMIX 113605b261ecSmrg if ( !noPanoramiXExtension ) 113705b261ecSmrg return ProcPanoramiXShmGetImage(client); 113805b261ecSmrg#endif 113905b261ecSmrg return ProcShmGetImage(client); 114005b261ecSmrg case X_ShmCreatePixmap: 114105b261ecSmrg#ifdef PANORAMIX 114205b261ecSmrg if ( !noPanoramiXExtension ) 114305b261ecSmrg return ProcPanoramiXShmCreatePixmap(client); 114405b261ecSmrg#endif 114505b261ecSmrg return ProcShmCreatePixmap(client); 114605b261ecSmrg default: 114705b261ecSmrg return BadRequest; 114805b261ecSmrg } 114905b261ecSmrg} 115005b261ecSmrg 115105b261ecSmrgstatic void 11524642e01fSmrgSShmCompletionEvent(xShmCompletionEvent *from, xShmCompletionEvent *to) 115305b261ecSmrg{ 115405b261ecSmrg to->type = from->type; 115505b261ecSmrg cpswaps(from->sequenceNumber, to->sequenceNumber); 115605b261ecSmrg cpswapl(from->drawable, to->drawable); 115705b261ecSmrg cpswaps(from->minorEvent, to->minorEvent); 115805b261ecSmrg to->majorEvent = from->majorEvent; 115905b261ecSmrg cpswapl(from->shmseg, to->shmseg); 116005b261ecSmrg cpswapl(from->offset, to->offset); 116105b261ecSmrg} 116205b261ecSmrg 116305b261ecSmrgstatic int 11644642e01fSmrgSProcShmQueryVersion(ClientPtr client) 116505b261ecSmrg{ 11664642e01fSmrg int n; 116705b261ecSmrg REQUEST(xShmQueryVersionReq); 116805b261ecSmrg 116905b261ecSmrg swaps(&stuff->length, n); 117005b261ecSmrg return ProcShmQueryVersion(client); 117105b261ecSmrg} 117205b261ecSmrg 117305b261ecSmrgstatic int 11744642e01fSmrgSProcShmAttach(ClientPtr client) 117505b261ecSmrg{ 11764642e01fSmrg int n; 117705b261ecSmrg REQUEST(xShmAttachReq); 117805b261ecSmrg swaps(&stuff->length, n); 117905b261ecSmrg REQUEST_SIZE_MATCH(xShmAttachReq); 118005b261ecSmrg swapl(&stuff->shmseg, n); 118105b261ecSmrg swapl(&stuff->shmid, n); 118205b261ecSmrg return ProcShmAttach(client); 118305b261ecSmrg} 118405b261ecSmrg 118505b261ecSmrgstatic int 11864642e01fSmrgSProcShmDetach(ClientPtr client) 118705b261ecSmrg{ 11884642e01fSmrg int n; 118905b261ecSmrg REQUEST(xShmDetachReq); 119005b261ecSmrg swaps(&stuff->length, n); 119105b261ecSmrg REQUEST_SIZE_MATCH(xShmDetachReq); 119205b261ecSmrg swapl(&stuff->shmseg, n); 119305b261ecSmrg return ProcShmDetach(client); 119405b261ecSmrg} 119505b261ecSmrg 119605b261ecSmrgstatic int 11974642e01fSmrgSProcShmPutImage(ClientPtr client) 119805b261ecSmrg{ 11994642e01fSmrg int n; 120005b261ecSmrg REQUEST(xShmPutImageReq); 120105b261ecSmrg swaps(&stuff->length, n); 120205b261ecSmrg REQUEST_SIZE_MATCH(xShmPutImageReq); 120305b261ecSmrg swapl(&stuff->drawable, n); 120405b261ecSmrg swapl(&stuff->gc, n); 120505b261ecSmrg swaps(&stuff->totalWidth, n); 120605b261ecSmrg swaps(&stuff->totalHeight, n); 120705b261ecSmrg swaps(&stuff->srcX, n); 120805b261ecSmrg swaps(&stuff->srcY, n); 120905b261ecSmrg swaps(&stuff->srcWidth, n); 121005b261ecSmrg swaps(&stuff->srcHeight, n); 121105b261ecSmrg swaps(&stuff->dstX, n); 121205b261ecSmrg swaps(&stuff->dstY, n); 121305b261ecSmrg swapl(&stuff->shmseg, n); 121405b261ecSmrg swapl(&stuff->offset, n); 121505b261ecSmrg return ProcShmPutImage(client); 121605b261ecSmrg} 121705b261ecSmrg 121805b261ecSmrgstatic int 12194642e01fSmrgSProcShmGetImage(ClientPtr client) 122005b261ecSmrg{ 12214642e01fSmrg int n; 122205b261ecSmrg REQUEST(xShmGetImageReq); 122305b261ecSmrg swaps(&stuff->length, n); 122405b261ecSmrg REQUEST_SIZE_MATCH(xShmGetImageReq); 122505b261ecSmrg swapl(&stuff->drawable, n); 122605b261ecSmrg swaps(&stuff->x, n); 122705b261ecSmrg swaps(&stuff->y, n); 122805b261ecSmrg swaps(&stuff->width, n); 122905b261ecSmrg swaps(&stuff->height, n); 123005b261ecSmrg swapl(&stuff->planeMask, n); 123105b261ecSmrg swapl(&stuff->shmseg, n); 123205b261ecSmrg swapl(&stuff->offset, n); 123305b261ecSmrg return ProcShmGetImage(client); 123405b261ecSmrg} 123505b261ecSmrg 123605b261ecSmrgstatic int 12374642e01fSmrgSProcShmCreatePixmap(ClientPtr client) 123805b261ecSmrg{ 12394642e01fSmrg int n; 124005b261ecSmrg REQUEST(xShmCreatePixmapReq); 124105b261ecSmrg swaps(&stuff->length, n); 124205b261ecSmrg REQUEST_SIZE_MATCH(xShmCreatePixmapReq); 124305b261ecSmrg swapl(&stuff->pid, n); 124405b261ecSmrg swapl(&stuff->drawable, n); 124505b261ecSmrg swaps(&stuff->width, n); 124605b261ecSmrg swaps(&stuff->height, n); 124705b261ecSmrg swapl(&stuff->shmseg, n); 124805b261ecSmrg swapl(&stuff->offset, n); 124905b261ecSmrg return ProcShmCreatePixmap(client); 125005b261ecSmrg} 125105b261ecSmrg 125205b261ecSmrgstatic int 12534642e01fSmrgSProcShmDispatch (ClientPtr client) 125405b261ecSmrg{ 125505b261ecSmrg REQUEST(xReq); 125605b261ecSmrg switch (stuff->data) 125705b261ecSmrg { 125805b261ecSmrg case X_ShmQueryVersion: 125905b261ecSmrg return SProcShmQueryVersion(client); 126005b261ecSmrg case X_ShmAttach: 126105b261ecSmrg return SProcShmAttach(client); 126205b261ecSmrg case X_ShmDetach: 126305b261ecSmrg return SProcShmDetach(client); 126405b261ecSmrg case X_ShmPutImage: 126505b261ecSmrg return SProcShmPutImage(client); 126605b261ecSmrg case X_ShmGetImage: 126705b261ecSmrg return SProcShmGetImage(client); 126805b261ecSmrg case X_ShmCreatePixmap: 126905b261ecSmrg return SProcShmCreatePixmap(client); 127005b261ecSmrg default: 127105b261ecSmrg return BadRequest; 127205b261ecSmrg } 127305b261ecSmrg} 127465b04b38Smrg 127565b04b38Smrgvoid 127665b04b38SmrgShmExtensionInit(INITARGS) 127765b04b38Smrg{ 127865b04b38Smrg ExtensionEntry *extEntry; 127965b04b38Smrg int i; 128065b04b38Smrg 128165b04b38Smrg#ifdef MUST_CHECK_FOR_SHM_SYSCALL 128265b04b38Smrg if (!CheckForShmSyscall()) 128365b04b38Smrg { 128465b04b38Smrg ErrorF("MIT-SHM extension disabled due to lack of kernel support\n"); 128565b04b38Smrg return; 128665b04b38Smrg } 128765b04b38Smrg#endif 128865b04b38Smrg 128965b04b38Smrg if (!ShmRegisterPrivates()) 129065b04b38Smrg return; 129165b04b38Smrg 129265b04b38Smrg sharedPixmaps = xFalse; 129365b04b38Smrg { 129465b04b38Smrg sharedPixmaps = xTrue; 129565b04b38Smrg for (i = 0; i < screenInfo.numScreens; i++) 129665b04b38Smrg { 129765b04b38Smrg ShmScrPrivateRec *screen_priv = ShmInitScreenPriv(screenInfo.screens[i]); 129865b04b38Smrg if (!screen_priv->shmFuncs) 129965b04b38Smrg screen_priv->shmFuncs = &miFuncs; 130065b04b38Smrg if (!screen_priv->shmFuncs->CreatePixmap) 130165b04b38Smrg sharedPixmaps = xFalse; 130265b04b38Smrg } 130365b04b38Smrg if (sharedPixmaps) 130465b04b38Smrg for (i = 0; i < screenInfo.numScreens; i++) 130565b04b38Smrg { 130665b04b38Smrg ShmScrPrivateRec *screen_priv = ShmGetScreenPriv(screenInfo.screens[i]); 130765b04b38Smrg screen_priv->destroyPixmap = screenInfo.screens[i]->DestroyPixmap; 130865b04b38Smrg screenInfo.screens[i]->DestroyPixmap = ShmDestroyPixmap; 130965b04b38Smrg } 131065b04b38Smrg } 131165b04b38Smrg ShmSegType = CreateNewResourceType(ShmDetachSegment, "ShmSeg"); 131265b04b38Smrg if (ShmSegType && 131365b04b38Smrg (extEntry = AddExtension(SHMNAME, ShmNumberEvents, ShmNumberErrors, 131465b04b38Smrg ProcShmDispatch, SProcShmDispatch, 131565b04b38Smrg ShmResetProc, StandardMinorOpcode))) 131665b04b38Smrg { 131765b04b38Smrg ShmReqCode = (unsigned char)extEntry->base; 131865b04b38Smrg ShmCompletionCode = extEntry->eventBase; 131965b04b38Smrg BadShmSegCode = extEntry->errorBase; 132065b04b38Smrg SetResourceTypeErrorValue(ShmSegType, BadShmSegCode); 132165b04b38Smrg EventSwapVector[ShmCompletionCode] = (EventSwapPtr) SShmCompletionEvent; 132265b04b38Smrg } 132365b04b38Smrg} 1324