shm.c revision 684baedf
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#define NEED_REPLIES 4205b261ecSmrg#define NEED_EVENTS 4305b261ecSmrg#include <X11/X.h> 4405b261ecSmrg#include <X11/Xproto.h> 4505b261ecSmrg#include "misc.h" 4605b261ecSmrg#include "os.h" 4705b261ecSmrg#include "dixstruct.h" 4805b261ecSmrg#include "resource.h" 4905b261ecSmrg#include "scrnintstr.h" 5005b261ecSmrg#include "windowstr.h" 5105b261ecSmrg#include "pixmapstr.h" 5205b261ecSmrg#include "gcstruct.h" 5305b261ecSmrg#include "extnsionst.h" 5405b261ecSmrg#include "servermd.h" 554642e01fSmrg#include "shmint.h" 564642e01fSmrg#include "xace.h" 5705b261ecSmrg#define _XSHM_SERVER_ 5805b261ecSmrg#include <X11/extensions/shmstr.h> 59684baedfSmrg#include <X11/extensions/shmproto.h> 6005b261ecSmrg#include <X11/Xfuncproto.h> 6105b261ecSmrg 624642e01fSmrg/* Needed for Solaris cross-zone shared memory extension */ 634642e01fSmrg#ifdef HAVE_SHMCTL64 644642e01fSmrg#include <sys/ipc_impl.h> 654642e01fSmrg#define SHMSTAT(id, buf) shmctl64(id, IPC_STAT64, buf) 664642e01fSmrg#define SHMSTAT_TYPE struct shmid_ds64 674642e01fSmrg#define SHMPERM_TYPE struct ipc_perm64 684642e01fSmrg#define SHM_PERM(buf) buf.shmx_perm 694642e01fSmrg#define SHM_SEGSZ(buf) buf.shmx_segsz 704642e01fSmrg#define SHMPERM_UID(p) p->ipcx_uid 714642e01fSmrg#define SHMPERM_CUID(p) p->ipcx_cuid 724642e01fSmrg#define SHMPERM_GID(p) p->ipcx_gid 734642e01fSmrg#define SHMPERM_CGID(p) p->ipcx_cgid 744642e01fSmrg#define SHMPERM_MODE(p) p->ipcx_mode 754642e01fSmrg#define SHMPERM_ZONEID(p) p->ipcx_zoneid 764642e01fSmrg#else 774642e01fSmrg#define SHMSTAT(id, buf) shmctl(id, IPC_STAT, buf) 784642e01fSmrg#define SHMSTAT_TYPE struct shmid_ds 794642e01fSmrg#define SHMPERM_TYPE struct ipc_perm 804642e01fSmrg#define SHM_PERM(buf) buf.shm_perm 814642e01fSmrg#define SHM_SEGSZ(buf) buf.shm_segsz 824642e01fSmrg#define SHMPERM_UID(p) p->uid 834642e01fSmrg#define SHMPERM_CUID(p) p->cuid 844642e01fSmrg#define SHMPERM_GID(p) p->gid 854642e01fSmrg#define SHMPERM_CGID(p) p->cgid 864642e01fSmrg#define SHMPERM_MODE(p) p->mode 874642e01fSmrg#endif 884642e01fSmrg 8905b261ecSmrg#ifdef PANORAMIX 9005b261ecSmrg#include "panoramiX.h" 9105b261ecSmrg#include "panoramiXsrv.h" 9205b261ecSmrg#endif 9305b261ecSmrg 9405b261ecSmrg#include "modinit.h" 9505b261ecSmrg 9605b261ecSmrgtypedef struct _ShmDesc { 9705b261ecSmrg struct _ShmDesc *next; 9805b261ecSmrg int shmid; 9905b261ecSmrg int refcnt; 10005b261ecSmrg char *addr; 10105b261ecSmrg Bool writable; 10205b261ecSmrg unsigned long size; 10305b261ecSmrg} ShmDescRec, *ShmDescPtr; 10405b261ecSmrg 10505b261ecSmrgstatic PixmapPtr fbShmCreatePixmap(XSHM_CREATE_PIXMAP_ARGS); 10605b261ecSmrgstatic int ShmDetachSegment( 10705b261ecSmrg pointer /* value */, 10805b261ecSmrg XID /* shmseg */ 10905b261ecSmrg ); 11005b261ecSmrgstatic void ShmResetProc( 11105b261ecSmrg ExtensionEntry * /* extEntry */ 11205b261ecSmrg ); 11305b261ecSmrgstatic void SShmCompletionEvent( 11405b261ecSmrg xShmCompletionEvent * /* from */, 11505b261ecSmrg xShmCompletionEvent * /* to */ 11605b261ecSmrg ); 11705b261ecSmrg 11805b261ecSmrgstatic Bool ShmDestroyPixmap (PixmapPtr pPixmap); 11905b261ecSmrg 12005b261ecSmrgstatic DISPATCH_PROC(ProcShmAttach); 12105b261ecSmrgstatic DISPATCH_PROC(ProcShmCreatePixmap); 12205b261ecSmrgstatic DISPATCH_PROC(ProcShmDetach); 12305b261ecSmrgstatic DISPATCH_PROC(ProcShmDispatch); 12405b261ecSmrgstatic DISPATCH_PROC(ProcShmGetImage); 12505b261ecSmrgstatic DISPATCH_PROC(ProcShmPutImage); 12605b261ecSmrgstatic DISPATCH_PROC(ProcShmQueryVersion); 12705b261ecSmrgstatic DISPATCH_PROC(SProcShmAttach); 12805b261ecSmrgstatic DISPATCH_PROC(SProcShmCreatePixmap); 12905b261ecSmrgstatic DISPATCH_PROC(SProcShmDetach); 13005b261ecSmrgstatic DISPATCH_PROC(SProcShmDispatch); 13105b261ecSmrgstatic DISPATCH_PROC(SProcShmGetImage); 13205b261ecSmrgstatic DISPATCH_PROC(SProcShmPutImage); 13305b261ecSmrgstatic DISPATCH_PROC(SProcShmQueryVersion); 13405b261ecSmrg 13505b261ecSmrgstatic unsigned char ShmReqCode; 13605b261ecSmrg_X_EXPORT int ShmCompletionCode; 13705b261ecSmrg_X_EXPORT int BadShmSegCode; 13805b261ecSmrg_X_EXPORT RESTYPE ShmSegType; 13905b261ecSmrgstatic ShmDescPtr Shmsegs; 14005b261ecSmrgstatic Bool sharedPixmaps; 14105b261ecSmrgstatic ShmFuncsPtr shmFuncs[MAXSCREENS]; 14205b261ecSmrgstatic DestroyPixmapProcPtr destroyPixmap[MAXSCREENS]; 1434642e01fSmrgstatic int shmPixmapPrivateIndex; 1444642e01fSmrgstatic DevPrivateKey shmPixmapPrivate = &shmPixmapPrivateIndex; 1454642e01fSmrgstatic ShmFuncs miFuncs = {NULL, NULL}; 1464642e01fSmrgstatic ShmFuncs fbFuncs = {fbShmCreatePixmap, NULL}; 14705b261ecSmrg 14805b261ecSmrg#define VERIFY_SHMSEG(shmseg,shmdesc,client) \ 14905b261ecSmrg{ \ 15005b261ecSmrg shmdesc = (ShmDescPtr)LookupIDByType(shmseg, ShmSegType); \ 15105b261ecSmrg if (!shmdesc) \ 15205b261ecSmrg { \ 15305b261ecSmrg client->errorValue = shmseg; \ 15405b261ecSmrg return BadShmSegCode; \ 15505b261ecSmrg } \ 15605b261ecSmrg} 15705b261ecSmrg 15805b261ecSmrg#define VERIFY_SHMPTR(shmseg,offset,needwrite,shmdesc,client) \ 15905b261ecSmrg{ \ 16005b261ecSmrg VERIFY_SHMSEG(shmseg, shmdesc, client); \ 16105b261ecSmrg if ((offset & 3) || (offset > shmdesc->size)) \ 16205b261ecSmrg { \ 16305b261ecSmrg client->errorValue = offset; \ 16405b261ecSmrg return BadValue; \ 16505b261ecSmrg } \ 16605b261ecSmrg if (needwrite && !shmdesc->writable) \ 16705b261ecSmrg return BadAccess; \ 16805b261ecSmrg} 16905b261ecSmrg 17005b261ecSmrg#define VERIFY_SHMSIZE(shmdesc,offset,len,client) \ 17105b261ecSmrg{ \ 17205b261ecSmrg if ((offset + len) > shmdesc->size) \ 17305b261ecSmrg { \ 17405b261ecSmrg return BadAccess; \ 17505b261ecSmrg } \ 17605b261ecSmrg} 17705b261ecSmrg 17805b261ecSmrg 17905b261ecSmrg#if defined(__FreeBSD__) || defined(__NetBSD__) || defined(__OpenBSD__) || defined(__CYGWIN__) || defined(__DragonFly__) 18005b261ecSmrg#include <sys/signal.h> 18105b261ecSmrg 18205b261ecSmrgstatic Bool badSysCall = FALSE; 18305b261ecSmrg 18405b261ecSmrgstatic void 1854642e01fSmrgSigSysHandler(int signo) 18605b261ecSmrg{ 18705b261ecSmrg badSysCall = TRUE; 18805b261ecSmrg} 18905b261ecSmrg 1904642e01fSmrgstatic Bool CheckForShmSyscall(void) 19105b261ecSmrg{ 19205b261ecSmrg void (*oldHandler)(); 19305b261ecSmrg int shmid = -1; 19405b261ecSmrg 19505b261ecSmrg /* If no SHM support in the kernel, the bad syscall will generate SIGSYS */ 19605b261ecSmrg oldHandler = signal(SIGSYS, SigSysHandler); 19705b261ecSmrg 19805b261ecSmrg badSysCall = FALSE; 19905b261ecSmrg shmid = shmget(IPC_PRIVATE, 4096, IPC_CREAT); 20005b261ecSmrg 20105b261ecSmrg if (shmid != -1) 20205b261ecSmrg { 20305b261ecSmrg /* Successful allocation - clean up */ 20405b261ecSmrg shmctl(shmid, IPC_RMID, (struct shmid_ds *)NULL); 20505b261ecSmrg } 20605b261ecSmrg else 20705b261ecSmrg { 20805b261ecSmrg /* Allocation failed */ 20905b261ecSmrg badSysCall = TRUE; 21005b261ecSmrg } 21105b261ecSmrg signal(SIGSYS, oldHandler); 21205b261ecSmrg return(!badSysCall); 21305b261ecSmrg} 21405b261ecSmrg 21505b261ecSmrg#define MUST_CHECK_FOR_SHM_SYSCALL 21605b261ecSmrg 21705b261ecSmrg#endif 21805b261ecSmrg 21905b261ecSmrgvoid 22005b261ecSmrgShmExtensionInit(INITARGS) 22105b261ecSmrg{ 22205b261ecSmrg ExtensionEntry *extEntry; 22305b261ecSmrg int i; 22405b261ecSmrg 22505b261ecSmrg#ifdef MUST_CHECK_FOR_SHM_SYSCALL 22605b261ecSmrg if (!CheckForShmSyscall()) 22705b261ecSmrg { 22805b261ecSmrg ErrorF("MIT-SHM extension disabled due to lack of kernel support\n"); 22905b261ecSmrg return; 23005b261ecSmrg } 23105b261ecSmrg#endif 23205b261ecSmrg 23305b261ecSmrg sharedPixmaps = xFalse; 23405b261ecSmrg { 23505b261ecSmrg sharedPixmaps = xTrue; 23605b261ecSmrg for (i = 0; i < screenInfo.numScreens; i++) 23705b261ecSmrg { 23805b261ecSmrg if (!shmFuncs[i]) 23905b261ecSmrg shmFuncs[i] = &miFuncs; 24005b261ecSmrg if (!shmFuncs[i]->CreatePixmap) 24105b261ecSmrg sharedPixmaps = xFalse; 24205b261ecSmrg } 24305b261ecSmrg if (sharedPixmaps) 24405b261ecSmrg for (i = 0; i < screenInfo.numScreens; i++) 24505b261ecSmrg { 24605b261ecSmrg destroyPixmap[i] = screenInfo.screens[i]->DestroyPixmap; 24705b261ecSmrg screenInfo.screens[i]->DestroyPixmap = ShmDestroyPixmap; 24805b261ecSmrg } 24905b261ecSmrg } 25005b261ecSmrg ShmSegType = CreateNewResourceType(ShmDetachSegment); 25105b261ecSmrg if (ShmSegType && 25205b261ecSmrg (extEntry = AddExtension(SHMNAME, ShmNumberEvents, ShmNumberErrors, 25305b261ecSmrg ProcShmDispatch, SProcShmDispatch, 25405b261ecSmrg ShmResetProc, StandardMinorOpcode))) 25505b261ecSmrg { 25605b261ecSmrg ShmReqCode = (unsigned char)extEntry->base; 25705b261ecSmrg ShmCompletionCode = extEntry->eventBase; 25805b261ecSmrg BadShmSegCode = extEntry->errorBase; 25905b261ecSmrg EventSwapVector[ShmCompletionCode] = (EventSwapPtr) SShmCompletionEvent; 26005b261ecSmrg } 26105b261ecSmrg} 26205b261ecSmrg 26305b261ecSmrg/*ARGSUSED*/ 26405b261ecSmrgstatic void 2654642e01fSmrgShmResetProc(ExtensionEntry *extEntry) 26605b261ecSmrg{ 26705b261ecSmrg int i; 26805b261ecSmrg 26905b261ecSmrg for (i = 0; i < MAXSCREENS; i++) 27005b261ecSmrg { 27105b261ecSmrg shmFuncs[i] = (ShmFuncsPtr)NULL; 27205b261ecSmrg } 27305b261ecSmrg} 27405b261ecSmrg 2754642e01fSmrg_X_EXPORT void 2764642e01fSmrgShmRegisterFuncs(ScreenPtr pScreen, ShmFuncsPtr funcs) 27705b261ecSmrg{ 27805b261ecSmrg shmFuncs[pScreen->myNum] = funcs; 27905b261ecSmrg} 28005b261ecSmrg 28105b261ecSmrgstatic Bool 28205b261ecSmrgShmDestroyPixmap (PixmapPtr pPixmap) 28305b261ecSmrg{ 28405b261ecSmrg ScreenPtr pScreen = pPixmap->drawable.pScreen; 28505b261ecSmrg Bool ret; 28605b261ecSmrg if (pPixmap->refcnt == 1) 28705b261ecSmrg { 28805b261ecSmrg ShmDescPtr shmdesc; 2894642e01fSmrg shmdesc = (ShmDescPtr)dixLookupPrivate(&pPixmap->devPrivates, 2904642e01fSmrg shmPixmapPrivate); 29105b261ecSmrg if (shmdesc) 29205b261ecSmrg ShmDetachSegment ((pointer) shmdesc, pPixmap->drawable.id); 29305b261ecSmrg } 29405b261ecSmrg 29505b261ecSmrg pScreen->DestroyPixmap = destroyPixmap[pScreen->myNum]; 29605b261ecSmrg ret = (*pScreen->DestroyPixmap) (pPixmap); 29705b261ecSmrg destroyPixmap[pScreen->myNum] = pScreen->DestroyPixmap; 29805b261ecSmrg pScreen->DestroyPixmap = ShmDestroyPixmap; 29905b261ecSmrg return ret; 30005b261ecSmrg} 30105b261ecSmrg 3024642e01fSmrg_X_EXPORT void 3034642e01fSmrgShmRegisterFbFuncs(ScreenPtr pScreen) 30405b261ecSmrg{ 30505b261ecSmrg shmFuncs[pScreen->myNum] = &fbFuncs; 30605b261ecSmrg} 30705b261ecSmrg 30805b261ecSmrgstatic int 3094642e01fSmrgProcShmQueryVersion(ClientPtr client) 31005b261ecSmrg{ 31105b261ecSmrg xShmQueryVersionReply rep; 3124642e01fSmrg int n; 31305b261ecSmrg 31405b261ecSmrg REQUEST_SIZE_MATCH(xShmQueryVersionReq); 31505b261ecSmrg rep.type = X_Reply; 31605b261ecSmrg rep.length = 0; 31705b261ecSmrg rep.sequenceNumber = client->sequence; 31805b261ecSmrg rep.sharedPixmaps = sharedPixmaps; 3194642e01fSmrg rep.pixmapFormat = sharedPixmaps ? ZPixmap : 0; 32005b261ecSmrg rep.majorVersion = SHM_MAJOR_VERSION; 32105b261ecSmrg rep.minorVersion = SHM_MINOR_VERSION; 32205b261ecSmrg rep.uid = geteuid(); 32305b261ecSmrg rep.gid = getegid(); 32405b261ecSmrg if (client->swapped) { 32505b261ecSmrg swaps(&rep.sequenceNumber, n); 32605b261ecSmrg swapl(&rep.length, n); 32705b261ecSmrg swaps(&rep.majorVersion, n); 32805b261ecSmrg swaps(&rep.minorVersion, n); 32905b261ecSmrg swaps(&rep.uid, n); 33005b261ecSmrg swaps(&rep.gid, n); 33105b261ecSmrg } 33205b261ecSmrg WriteToClient(client, sizeof(xShmQueryVersionReply), (char *)&rep); 33305b261ecSmrg return (client->noClientException); 33405b261ecSmrg} 33505b261ecSmrg 33605b261ecSmrg/* 33705b261ecSmrg * Simulate the access() system call for a shared memory segement, 33805b261ecSmrg * using the credentials from the client if available 33905b261ecSmrg */ 34005b261ecSmrgstatic int 3414642e01fSmrgshm_access(ClientPtr client, SHMPERM_TYPE *perm, int readonly) 34205b261ecSmrg{ 34305b261ecSmrg int uid, gid; 34405b261ecSmrg mode_t mask; 3454642e01fSmrg int uidset = 0, gidset = 0; 3464642e01fSmrg LocalClientCredRec *lcc; 3474642e01fSmrg 3484642e01fSmrg if (GetLocalClientCreds(client, &lcc) != -1) { 34905b261ecSmrg 3504642e01fSmrg if (lcc->fieldsSet & LCC_UID_SET) { 3514642e01fSmrg uid = lcc->euid; 3524642e01fSmrg uidset = 1; 3534642e01fSmrg } 3544642e01fSmrg if (lcc->fieldsSet & LCC_GID_SET) { 3554642e01fSmrg gid = lcc->egid; 3564642e01fSmrg gidset = 1; 3574642e01fSmrg } 3584642e01fSmrg 3594642e01fSmrg#if defined(HAVE_GETZONEID) && defined(SHMPERM_ZONEID) 3604642e01fSmrg if ( ((lcc->fieldsSet & LCC_ZID_SET) == 0) || (lcc->zoneid == -1) 3614642e01fSmrg || (lcc->zoneid != SHMPERM_ZONEID(perm))) { 3624642e01fSmrg uidset = 0; 3634642e01fSmrg gidset = 0; 36405b261ecSmrg } 3654642e01fSmrg#endif 3664642e01fSmrg FreeLocalClientCreds(lcc); 3674642e01fSmrg 3684642e01fSmrg if (uidset) { 3694642e01fSmrg /* User id 0 always gets access */ 3704642e01fSmrg if (uid == 0) { 3714642e01fSmrg return 0; 3724642e01fSmrg } 3734642e01fSmrg /* Check the owner */ 3744642e01fSmrg if (SHMPERM_UID(perm) == uid || SHMPERM_CUID(perm) == uid) { 3754642e01fSmrg mask = S_IRUSR; 3764642e01fSmrg if (!readonly) { 3774642e01fSmrg mask |= S_IWUSR; 3784642e01fSmrg } 3794642e01fSmrg return (SHMPERM_MODE(perm) & mask) == mask ? 0 : -1; 38005b261ecSmrg } 38105b261ecSmrg } 3824642e01fSmrg 3834642e01fSmrg if (gidset) { 3844642e01fSmrg /* Check the group */ 3854642e01fSmrg if (SHMPERM_GID(perm) == gid || SHMPERM_CGID(perm) == gid) { 3864642e01fSmrg mask = S_IRGRP; 3874642e01fSmrg if (!readonly) { 3884642e01fSmrg mask |= S_IWGRP; 3894642e01fSmrg } 3904642e01fSmrg return (SHMPERM_MODE(perm) & mask) == mask ? 0 : -1; 39105b261ecSmrg } 39205b261ecSmrg } 39305b261ecSmrg } 39405b261ecSmrg /* Otherwise, check everyone else */ 39505b261ecSmrg mask = S_IROTH; 39605b261ecSmrg if (!readonly) { 39705b261ecSmrg mask |= S_IWOTH; 39805b261ecSmrg } 3994642e01fSmrg return (SHMPERM_MODE(perm) & mask) == mask ? 0 : -1; 40005b261ecSmrg} 40105b261ecSmrg 40205b261ecSmrgstatic int 4034642e01fSmrgProcShmAttach(ClientPtr client) 40405b261ecSmrg{ 4054642e01fSmrg SHMSTAT_TYPE buf; 40605b261ecSmrg ShmDescPtr shmdesc; 40705b261ecSmrg REQUEST(xShmAttachReq); 40805b261ecSmrg 40905b261ecSmrg REQUEST_SIZE_MATCH(xShmAttachReq); 41005b261ecSmrg LEGAL_NEW_RESOURCE(stuff->shmseg, client); 41105b261ecSmrg if ((stuff->readOnly != xTrue) && (stuff->readOnly != xFalse)) 41205b261ecSmrg { 41305b261ecSmrg client->errorValue = stuff->readOnly; 41405b261ecSmrg return(BadValue); 41505b261ecSmrg } 41605b261ecSmrg for (shmdesc = Shmsegs; 41705b261ecSmrg shmdesc && (shmdesc->shmid != stuff->shmid); 41805b261ecSmrg shmdesc = shmdesc->next) 41905b261ecSmrg ; 42005b261ecSmrg if (shmdesc) 42105b261ecSmrg { 42205b261ecSmrg if (!stuff->readOnly && !shmdesc->writable) 42305b261ecSmrg return BadAccess; 42405b261ecSmrg shmdesc->refcnt++; 42505b261ecSmrg } 42605b261ecSmrg else 42705b261ecSmrg { 42805b261ecSmrg shmdesc = (ShmDescPtr) xalloc(sizeof(ShmDescRec)); 42905b261ecSmrg if (!shmdesc) 43005b261ecSmrg return BadAlloc; 43105b261ecSmrg shmdesc->addr = shmat(stuff->shmid, 0, 43205b261ecSmrg stuff->readOnly ? SHM_RDONLY : 0); 43305b261ecSmrg if ((shmdesc->addr == ((char *)-1)) || 4344642e01fSmrg SHMSTAT(stuff->shmid, &buf)) 43505b261ecSmrg { 43605b261ecSmrg xfree(shmdesc); 43705b261ecSmrg return BadAccess; 43805b261ecSmrg } 43905b261ecSmrg 44005b261ecSmrg /* The attach was performed with root privs. We must 44105b261ecSmrg * do manual checking of access rights for the credentials 44205b261ecSmrg * of the client */ 44305b261ecSmrg 4444642e01fSmrg if (shm_access(client, &(SHM_PERM(buf)), stuff->readOnly) == -1) { 44505b261ecSmrg shmdt(shmdesc->addr); 44605b261ecSmrg xfree(shmdesc); 44705b261ecSmrg return BadAccess; 44805b261ecSmrg } 44905b261ecSmrg 45005b261ecSmrg shmdesc->shmid = stuff->shmid; 45105b261ecSmrg shmdesc->refcnt = 1; 45205b261ecSmrg shmdesc->writable = !stuff->readOnly; 4534642e01fSmrg shmdesc->size = SHM_SEGSZ(buf); 45405b261ecSmrg shmdesc->next = Shmsegs; 45505b261ecSmrg Shmsegs = shmdesc; 45605b261ecSmrg } 45705b261ecSmrg if (!AddResource(stuff->shmseg, ShmSegType, (pointer)shmdesc)) 45805b261ecSmrg return BadAlloc; 45905b261ecSmrg return(client->noClientException); 46005b261ecSmrg} 46105b261ecSmrg 46205b261ecSmrg/*ARGSUSED*/ 46305b261ecSmrgstatic int 4644642e01fSmrgShmDetachSegment(pointer value, /* must conform to DeleteType */ 4654642e01fSmrg XID shmseg) 46605b261ecSmrg{ 46705b261ecSmrg ShmDescPtr shmdesc = (ShmDescPtr)value; 46805b261ecSmrg ShmDescPtr *prev; 46905b261ecSmrg 47005b261ecSmrg if (--shmdesc->refcnt) 47105b261ecSmrg return TRUE; 47205b261ecSmrg shmdt(shmdesc->addr); 47305b261ecSmrg for (prev = &Shmsegs; *prev != shmdesc; prev = &(*prev)->next) 47405b261ecSmrg ; 47505b261ecSmrg *prev = shmdesc->next; 47605b261ecSmrg xfree(shmdesc); 47705b261ecSmrg return Success; 47805b261ecSmrg} 47905b261ecSmrg 48005b261ecSmrgstatic int 4814642e01fSmrgProcShmDetach(ClientPtr client) 48205b261ecSmrg{ 48305b261ecSmrg ShmDescPtr shmdesc; 48405b261ecSmrg REQUEST(xShmDetachReq); 48505b261ecSmrg 48605b261ecSmrg REQUEST_SIZE_MATCH(xShmDetachReq); 48705b261ecSmrg VERIFY_SHMSEG(stuff->shmseg, shmdesc, client); 48805b261ecSmrg FreeResource(stuff->shmseg, RT_NONE); 48905b261ecSmrg return(client->noClientException); 49005b261ecSmrg} 49105b261ecSmrg 4924642e01fSmrg/* 4934642e01fSmrg * If the given request doesn't exactly match PutImage's constraints, 4944642e01fSmrg * wrap the image in a scratch pixmap header and let CopyArea sort it out. 4954642e01fSmrg */ 49605b261ecSmrgstatic void 4974642e01fSmrgdoShmPutImage(DrawablePtr dst, GCPtr pGC, 4984642e01fSmrg int depth, unsigned int format, 4994642e01fSmrg int w, int h, int sx, int sy, int sw, int sh, int dx, int dy, 5004642e01fSmrg char *data) 50105b261ecSmrg{ 5024642e01fSmrg PixmapPtr pPixmap; 5034642e01fSmrg 5044642e01fSmrg pPixmap = GetScratchPixmapHeader(dst->pScreen, w, h, depth, 5054642e01fSmrg BitsPerPixel(depth), 5064642e01fSmrg PixmapBytePad(w, depth), 5074642e01fSmrg data); 5084642e01fSmrg if (!pPixmap) 50905b261ecSmrg return; 5104642e01fSmrg pGC->ops->CopyArea((DrawablePtr)pPixmap, dst, pGC, sx, sy, sw, sh, dx, dy); 5114642e01fSmrg FreeScratchPixmapHeader(pPixmap); 51205b261ecSmrg} 51305b261ecSmrg 51405b261ecSmrg#ifdef PANORAMIX 51505b261ecSmrgstatic int 5164642e01fSmrgProcPanoramiXShmPutImage(ClientPtr client) 51705b261ecSmrg{ 51805b261ecSmrg int j, result = 0, orig_x, orig_y; 51905b261ecSmrg PanoramiXRes *draw, *gc; 52005b261ecSmrg Bool sendEvent, isRoot; 52105b261ecSmrg 52205b261ecSmrg REQUEST(xShmPutImageReq); 52305b261ecSmrg REQUEST_SIZE_MATCH(xShmPutImageReq); 52405b261ecSmrg 52505b261ecSmrg if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( 52605b261ecSmrg client, stuff->drawable, XRC_DRAWABLE, DixWriteAccess))) 52705b261ecSmrg return BadDrawable; 52805b261ecSmrg 52905b261ecSmrg if(!(gc = (PanoramiXRes *)SecurityLookupIDByType( 53005b261ecSmrg client, stuff->gc, XRT_GC, DixReadAccess))) 53105b261ecSmrg return BadGC; 53205b261ecSmrg 53305b261ecSmrg isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; 53405b261ecSmrg 53505b261ecSmrg orig_x = stuff->dstX; 53605b261ecSmrg orig_y = stuff->dstY; 53705b261ecSmrg sendEvent = stuff->sendEvent; 53805b261ecSmrg stuff->sendEvent = 0; 53905b261ecSmrg FOR_NSCREENS(j) { 54005b261ecSmrg if(!j) stuff->sendEvent = sendEvent; 54105b261ecSmrg stuff->drawable = draw->info[j].id; 54205b261ecSmrg stuff->gc = gc->info[j].id; 54305b261ecSmrg if (isRoot) { 54405b261ecSmrg stuff->dstX = orig_x - panoramiXdataPtr[j].x; 54505b261ecSmrg stuff->dstY = orig_y - panoramiXdataPtr[j].y; 54605b261ecSmrg } 54705b261ecSmrg result = ProcShmPutImage(client); 54805b261ecSmrg if(result != client->noClientException) break; 54905b261ecSmrg } 55005b261ecSmrg return(result); 55105b261ecSmrg} 55205b261ecSmrg 55305b261ecSmrgstatic int 55405b261ecSmrgProcPanoramiXShmGetImage(ClientPtr client) 55505b261ecSmrg{ 55605b261ecSmrg PanoramiXRes *draw; 55705b261ecSmrg DrawablePtr drawables[MAXSCREENS]; 55805b261ecSmrg DrawablePtr pDraw; 55905b261ecSmrg xShmGetImageReply xgi; 56005b261ecSmrg ShmDescPtr shmdesc; 56105b261ecSmrg int i, x, y, w, h, format, rc; 56205b261ecSmrg Mask plane = 0, planemask; 56305b261ecSmrg long lenPer = 0, length, widthBytesLine; 56405b261ecSmrg Bool isRoot; 56505b261ecSmrg 56605b261ecSmrg REQUEST(xShmGetImageReq); 56705b261ecSmrg 56805b261ecSmrg REQUEST_SIZE_MATCH(xShmGetImageReq); 56905b261ecSmrg 57005b261ecSmrg if ((stuff->format != XYPixmap) && (stuff->format != ZPixmap)) { 57105b261ecSmrg client->errorValue = stuff->format; 57205b261ecSmrg return(BadValue); 57305b261ecSmrg } 57405b261ecSmrg 57505b261ecSmrg if(!(draw = (PanoramiXRes *)SecurityLookupIDByClass( 57605b261ecSmrg client, stuff->drawable, XRC_DRAWABLE, DixWriteAccess))) 57705b261ecSmrg return BadDrawable; 57805b261ecSmrg 57905b261ecSmrg if (draw->type == XRT_PIXMAP) 58005b261ecSmrg return ProcShmGetImage(client); 58105b261ecSmrg 58205b261ecSmrg rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0, 5834642e01fSmrg DixReadAccess); 58405b261ecSmrg if (rc != Success) 58505b261ecSmrg return rc; 58605b261ecSmrg 58705b261ecSmrg VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); 58805b261ecSmrg 58905b261ecSmrg x = stuff->x; 59005b261ecSmrg y = stuff->y; 59105b261ecSmrg w = stuff->width; 59205b261ecSmrg h = stuff->height; 59305b261ecSmrg format = stuff->format; 59405b261ecSmrg planemask = stuff->planeMask; 59505b261ecSmrg 59605b261ecSmrg isRoot = (draw->type == XRT_WINDOW) && draw->u.win.root; 59705b261ecSmrg 59805b261ecSmrg if(isRoot) { 59905b261ecSmrg if( /* check for being onscreen */ 60005b261ecSmrg x < 0 || x + w > PanoramiXPixWidth || 60105b261ecSmrg y < 0 || y + h > PanoramiXPixHeight ) 60205b261ecSmrg return(BadMatch); 60305b261ecSmrg } else { 60405b261ecSmrg if( /* check for being onscreen */ 60505b261ecSmrg panoramiXdataPtr[0].x + pDraw->x + x < 0 || 60605b261ecSmrg panoramiXdataPtr[0].x + pDraw->x + x + w > PanoramiXPixWidth || 60705b261ecSmrg panoramiXdataPtr[0].y + pDraw->y + y < 0 || 60805b261ecSmrg panoramiXdataPtr[0].y + pDraw->y + y + h > PanoramiXPixHeight || 60905b261ecSmrg /* check for being inside of border */ 61005b261ecSmrg x < - wBorderWidth((WindowPtr)pDraw) || 61105b261ecSmrg x + w > wBorderWidth((WindowPtr)pDraw) + (int)pDraw->width || 61205b261ecSmrg y < -wBorderWidth((WindowPtr)pDraw) || 61305b261ecSmrg y + h > wBorderWidth ((WindowPtr)pDraw) + (int)pDraw->height) 61405b261ecSmrg return(BadMatch); 61505b261ecSmrg } 61605b261ecSmrg 61705b261ecSmrg drawables[0] = pDraw; 61805b261ecSmrg for(i = 1; i < PanoramiXNumScreens; i++) { 61905b261ecSmrg rc = dixLookupDrawable(drawables+i, draw->info[i].id, client, 0, 6204642e01fSmrg DixReadAccess); 62105b261ecSmrg if (rc != Success) 62205b261ecSmrg return rc; 62305b261ecSmrg } 62405b261ecSmrg 62505b261ecSmrg xgi.visual = wVisual(((WindowPtr)pDraw)); 62605b261ecSmrg xgi.type = X_Reply; 62705b261ecSmrg xgi.length = 0; 62805b261ecSmrg xgi.sequenceNumber = client->sequence; 62905b261ecSmrg xgi.depth = pDraw->depth; 63005b261ecSmrg 63105b261ecSmrg if(format == ZPixmap) { 63205b261ecSmrg widthBytesLine = PixmapBytePad(w, pDraw->depth); 63305b261ecSmrg length = widthBytesLine * h; 63405b261ecSmrg } else { 63505b261ecSmrg widthBytesLine = PixmapBytePad(w, 1); 63605b261ecSmrg lenPer = widthBytesLine * h; 63705b261ecSmrg plane = ((Mask)1) << (pDraw->depth - 1); 63805b261ecSmrg length = lenPer * Ones(planemask & (plane | (plane - 1))); 63905b261ecSmrg } 64005b261ecSmrg 64105b261ecSmrg VERIFY_SHMSIZE(shmdesc, stuff->offset, length, client); 64205b261ecSmrg xgi.size = length; 64305b261ecSmrg 64405b261ecSmrg if (length == 0) {/* nothing to do */ } 64505b261ecSmrg else if (format == ZPixmap) { 64605b261ecSmrg XineramaGetImageData(drawables, x, y, w, h, format, planemask, 64705b261ecSmrg shmdesc->addr + stuff->offset, 64805b261ecSmrg widthBytesLine, isRoot); 64905b261ecSmrg } else { 65005b261ecSmrg 65105b261ecSmrg length = stuff->offset; 65205b261ecSmrg for (; plane; plane >>= 1) { 65305b261ecSmrg if (planemask & plane) { 65405b261ecSmrg XineramaGetImageData(drawables, x, y, w, h, 65505b261ecSmrg format, plane, shmdesc->addr + length, 65605b261ecSmrg widthBytesLine, isRoot); 65705b261ecSmrg length += lenPer; 65805b261ecSmrg } 65905b261ecSmrg } 66005b261ecSmrg } 66105b261ecSmrg 66205b261ecSmrg if (client->swapped) { 6634642e01fSmrg int n; 66405b261ecSmrg swaps(&xgi.sequenceNumber, n); 66505b261ecSmrg swapl(&xgi.length, n); 66605b261ecSmrg swapl(&xgi.visual, n); 66705b261ecSmrg swapl(&xgi.size, n); 66805b261ecSmrg } 66905b261ecSmrg WriteToClient(client, sizeof(xShmGetImageReply), (char *)&xgi); 67005b261ecSmrg 67105b261ecSmrg return(client->noClientException); 67205b261ecSmrg} 67305b261ecSmrg 67405b261ecSmrgstatic int 6754642e01fSmrgProcPanoramiXShmCreatePixmap(ClientPtr client) 67605b261ecSmrg{ 67705b261ecSmrg ScreenPtr pScreen = NULL; 67805b261ecSmrg PixmapPtr pMap = NULL; 67905b261ecSmrg DrawablePtr pDraw; 68005b261ecSmrg DepthPtr pDepth; 68105b261ecSmrg int i, j, result, rc; 68205b261ecSmrg ShmDescPtr shmdesc; 68305b261ecSmrg REQUEST(xShmCreatePixmapReq); 68405b261ecSmrg unsigned int width, height, depth; 68505b261ecSmrg unsigned long size; 68605b261ecSmrg PanoramiXRes *newPix; 68705b261ecSmrg 68805b261ecSmrg REQUEST_SIZE_MATCH(xShmCreatePixmapReq); 68905b261ecSmrg client->errorValue = stuff->pid; 69005b261ecSmrg if (!sharedPixmaps) 69105b261ecSmrg return BadImplementation; 69205b261ecSmrg LEGAL_NEW_RESOURCE(stuff->pid, client); 69305b261ecSmrg rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY, 6944642e01fSmrg DixGetAttrAccess); 69505b261ecSmrg if (rc != Success) 69605b261ecSmrg return rc; 69705b261ecSmrg 69805b261ecSmrg VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); 69905b261ecSmrg 70005b261ecSmrg width = stuff->width; 70105b261ecSmrg height = stuff->height; 70205b261ecSmrg depth = stuff->depth; 70305b261ecSmrg if (!width || !height || !depth) 70405b261ecSmrg { 70505b261ecSmrg client->errorValue = 0; 70605b261ecSmrg return BadValue; 70705b261ecSmrg } 70805b261ecSmrg if (width > 32767 || height > 32767) 70905b261ecSmrg return BadAlloc; 71005b261ecSmrg 71105b261ecSmrg if (stuff->depth != 1) 71205b261ecSmrg { 71305b261ecSmrg pDepth = pDraw->pScreen->allowedDepths; 71405b261ecSmrg for (i=0; i<pDraw->pScreen->numDepths; i++, pDepth++) 71505b261ecSmrg if (pDepth->depth == stuff->depth) 71605b261ecSmrg goto CreatePmap; 71705b261ecSmrg client->errorValue = stuff->depth; 71805b261ecSmrg return BadValue; 71905b261ecSmrg } 72005b261ecSmrg 72105b261ecSmrgCreatePmap: 72205b261ecSmrg size = PixmapBytePad(width, depth) * height; 72305b261ecSmrg if (sizeof(size) == 4 && BitsPerPixel(depth) > 8) { 72405b261ecSmrg if (size < width * height) 72505b261ecSmrg return BadAlloc; 72605b261ecSmrg } 72705b261ecSmrg /* thankfully, offset is unsigned */ 72805b261ecSmrg if (stuff->offset + size < size) 72905b261ecSmrg return BadAlloc; 73005b261ecSmrg 73105b261ecSmrg VERIFY_SHMSIZE(shmdesc, stuff->offset, size, client); 73205b261ecSmrg 73305b261ecSmrg if(!(newPix = (PanoramiXRes *) xalloc(sizeof(PanoramiXRes)))) 73405b261ecSmrg return BadAlloc; 73505b261ecSmrg 73605b261ecSmrg newPix->type = XRT_PIXMAP; 73705b261ecSmrg newPix->u.pix.shared = TRUE; 73805b261ecSmrg newPix->info[0].id = stuff->pid; 73905b261ecSmrg for(j = 1; j < PanoramiXNumScreens; j++) 74005b261ecSmrg newPix->info[j].id = FakeClientID(client->index); 74105b261ecSmrg 74205b261ecSmrg result = (client->noClientException); 74305b261ecSmrg 74405b261ecSmrg FOR_NSCREENS(j) { 74505b261ecSmrg pScreen = screenInfo.screens[j]; 74605b261ecSmrg 74705b261ecSmrg pMap = (*shmFuncs[j]->CreatePixmap)(pScreen, 74805b261ecSmrg stuff->width, stuff->height, stuff->depth, 74905b261ecSmrg shmdesc->addr + stuff->offset); 75005b261ecSmrg 75105b261ecSmrg if (pMap) { 7524642e01fSmrg dixSetPrivate(&pMap->devPrivates, shmPixmapPrivate, shmdesc); 75305b261ecSmrg shmdesc->refcnt++; 75405b261ecSmrg pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER; 75505b261ecSmrg pMap->drawable.id = newPix->info[j].id; 75605b261ecSmrg if (!AddResource(newPix->info[j].id, RT_PIXMAP, (pointer)pMap)) { 75705b261ecSmrg (*pScreen->DestroyPixmap)(pMap); 75805b261ecSmrg result = BadAlloc; 75905b261ecSmrg break; 76005b261ecSmrg } 76105b261ecSmrg } else { 76205b261ecSmrg result = BadAlloc; 76305b261ecSmrg break; 76405b261ecSmrg } 76505b261ecSmrg } 76605b261ecSmrg 76705b261ecSmrg if(result == BadAlloc) { 76805b261ecSmrg while(j--) { 76905b261ecSmrg (*pScreen->DestroyPixmap)(pMap); 77005b261ecSmrg FreeResource(newPix->info[j].id, RT_NONE); 77105b261ecSmrg } 77205b261ecSmrg xfree(newPix); 77305b261ecSmrg } else 77405b261ecSmrg AddResource(stuff->pid, XRT_PIXMAP, newPix); 77505b261ecSmrg 77605b261ecSmrg return result; 77705b261ecSmrg} 77805b261ecSmrg 77905b261ecSmrg#endif 78005b261ecSmrg 78105b261ecSmrgstatic int 7824642e01fSmrgProcShmPutImage(ClientPtr client) 78305b261ecSmrg{ 78405b261ecSmrg GCPtr pGC; 78505b261ecSmrg DrawablePtr pDraw; 78605b261ecSmrg long length; 78705b261ecSmrg ShmDescPtr shmdesc; 78805b261ecSmrg REQUEST(xShmPutImageReq); 78905b261ecSmrg 79005b261ecSmrg REQUEST_SIZE_MATCH(xShmPutImageReq); 7914642e01fSmrg VALIDATE_DRAWABLE_AND_GC(stuff->drawable, pDraw, DixWriteAccess); 79205b261ecSmrg VERIFY_SHMPTR(stuff->shmseg, stuff->offset, FALSE, shmdesc, client); 79305b261ecSmrg if ((stuff->sendEvent != xTrue) && (stuff->sendEvent != xFalse)) 79405b261ecSmrg return BadValue; 79505b261ecSmrg if (stuff->format == XYBitmap) 79605b261ecSmrg { 79705b261ecSmrg if (stuff->depth != 1) 79805b261ecSmrg return BadMatch; 79905b261ecSmrg length = PixmapBytePad(stuff->totalWidth, 1); 80005b261ecSmrg } 80105b261ecSmrg else if (stuff->format == XYPixmap) 80205b261ecSmrg { 80305b261ecSmrg if (pDraw->depth != stuff->depth) 80405b261ecSmrg return BadMatch; 80505b261ecSmrg length = PixmapBytePad(stuff->totalWidth, 1); 80605b261ecSmrg length *= stuff->depth; 80705b261ecSmrg } 80805b261ecSmrg else if (stuff->format == ZPixmap) 80905b261ecSmrg { 81005b261ecSmrg if (pDraw->depth != stuff->depth) 81105b261ecSmrg return BadMatch; 81205b261ecSmrg length = PixmapBytePad(stuff->totalWidth, stuff->depth); 81305b261ecSmrg } 81405b261ecSmrg else 81505b261ecSmrg { 81605b261ecSmrg client->errorValue = stuff->format; 81705b261ecSmrg return BadValue; 81805b261ecSmrg } 81905b261ecSmrg 82005b261ecSmrg /* 82105b261ecSmrg * There's a potential integer overflow in this check: 82205b261ecSmrg * VERIFY_SHMSIZE(shmdesc, stuff->offset, length * stuff->totalHeight, 82305b261ecSmrg * client); 82405b261ecSmrg * the version below ought to avoid it 82505b261ecSmrg */ 82605b261ecSmrg if (stuff->totalHeight != 0 && 82705b261ecSmrg length > (shmdesc->size - stuff->offset)/stuff->totalHeight) { 82805b261ecSmrg client->errorValue = stuff->totalWidth; 82905b261ecSmrg return BadValue; 83005b261ecSmrg } 83105b261ecSmrg if (stuff->srcX > stuff->totalWidth) 83205b261ecSmrg { 83305b261ecSmrg client->errorValue = stuff->srcX; 83405b261ecSmrg return BadValue; 83505b261ecSmrg } 83605b261ecSmrg if (stuff->srcY > stuff->totalHeight) 83705b261ecSmrg { 83805b261ecSmrg client->errorValue = stuff->srcY; 83905b261ecSmrg return BadValue; 84005b261ecSmrg } 84105b261ecSmrg if ((stuff->srcX + stuff->srcWidth) > stuff->totalWidth) 84205b261ecSmrg { 84305b261ecSmrg client->errorValue = stuff->srcWidth; 84405b261ecSmrg return BadValue; 84505b261ecSmrg } 84605b261ecSmrg if ((stuff->srcY + stuff->srcHeight) > stuff->totalHeight) 84705b261ecSmrg { 84805b261ecSmrg client->errorValue = stuff->srcHeight; 84905b261ecSmrg return BadValue; 85005b261ecSmrg } 85105b261ecSmrg 85205b261ecSmrg if ((((stuff->format == ZPixmap) && (stuff->srcX == 0)) || 85305b261ecSmrg ((stuff->format != ZPixmap) && 85405b261ecSmrg (stuff->srcX < screenInfo.bitmapScanlinePad) && 85505b261ecSmrg ((stuff->format == XYBitmap) || 85605b261ecSmrg ((stuff->srcY == 0) && 85705b261ecSmrg (stuff->srcHeight == stuff->totalHeight))))) && 85805b261ecSmrg ((stuff->srcX + stuff->srcWidth) == stuff->totalWidth)) 85905b261ecSmrg (*pGC->ops->PutImage) (pDraw, pGC, stuff->depth, 86005b261ecSmrg stuff->dstX, stuff->dstY, 86105b261ecSmrg stuff->totalWidth, stuff->srcHeight, 86205b261ecSmrg stuff->srcX, stuff->format, 86305b261ecSmrg shmdesc->addr + stuff->offset + 86405b261ecSmrg (stuff->srcY * length)); 86505b261ecSmrg else 8664642e01fSmrg doShmPutImage(pDraw, pGC, stuff->depth, stuff->format, 8674642e01fSmrg stuff->totalWidth, stuff->totalHeight, 8684642e01fSmrg stuff->srcX, stuff->srcY, 8694642e01fSmrg stuff->srcWidth, stuff->srcHeight, 8704642e01fSmrg stuff->dstX, stuff->dstY, 8714642e01fSmrg shmdesc->addr + stuff->offset); 87205b261ecSmrg 87305b261ecSmrg if (stuff->sendEvent) 87405b261ecSmrg { 87505b261ecSmrg xShmCompletionEvent ev; 87605b261ecSmrg 87705b261ecSmrg ev.type = ShmCompletionCode; 87805b261ecSmrg ev.drawable = stuff->drawable; 87905b261ecSmrg ev.sequenceNumber = client->sequence; 88005b261ecSmrg ev.minorEvent = X_ShmPutImage; 88105b261ecSmrg ev.majorEvent = ShmReqCode; 88205b261ecSmrg ev.shmseg = stuff->shmseg; 88305b261ecSmrg ev.offset = stuff->offset; 88405b261ecSmrg WriteEventsToClient(client, 1, (xEvent *) &ev); 88505b261ecSmrg } 88605b261ecSmrg 88705b261ecSmrg return (client->noClientException); 88805b261ecSmrg} 88905b261ecSmrg 89005b261ecSmrg 89105b261ecSmrg 89205b261ecSmrgstatic int 8934642e01fSmrgProcShmGetImage(ClientPtr client) 89405b261ecSmrg{ 89505b261ecSmrg DrawablePtr pDraw; 89605b261ecSmrg long lenPer = 0, length; 89705b261ecSmrg Mask plane = 0; 89805b261ecSmrg xShmGetImageReply xgi; 89905b261ecSmrg ShmDescPtr shmdesc; 90005b261ecSmrg int n, rc; 90105b261ecSmrg 90205b261ecSmrg REQUEST(xShmGetImageReq); 90305b261ecSmrg 90405b261ecSmrg REQUEST_SIZE_MATCH(xShmGetImageReq); 90505b261ecSmrg if ((stuff->format != XYPixmap) && (stuff->format != ZPixmap)) 90605b261ecSmrg { 90705b261ecSmrg client->errorValue = stuff->format; 90805b261ecSmrg return(BadValue); 90905b261ecSmrg } 91005b261ecSmrg rc = dixLookupDrawable(&pDraw, stuff->drawable, client, 0, 9114642e01fSmrg DixReadAccess); 91205b261ecSmrg if (rc != Success) 91305b261ecSmrg return rc; 91405b261ecSmrg VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); 91505b261ecSmrg if (pDraw->type == DRAWABLE_WINDOW) 91605b261ecSmrg { 91705b261ecSmrg if( /* check for being viewable */ 91805b261ecSmrg !((WindowPtr) pDraw)->realized || 91905b261ecSmrg /* check for being on screen */ 92005b261ecSmrg pDraw->x + stuff->x < 0 || 92105b261ecSmrg pDraw->x + stuff->x + (int)stuff->width > pDraw->pScreen->width || 92205b261ecSmrg pDraw->y + stuff->y < 0 || 92305b261ecSmrg pDraw->y + stuff->y + (int)stuff->height > pDraw->pScreen->height || 92405b261ecSmrg /* check for being inside of border */ 92505b261ecSmrg stuff->x < - wBorderWidth((WindowPtr)pDraw) || 92605b261ecSmrg stuff->x + (int)stuff->width > 92705b261ecSmrg wBorderWidth((WindowPtr)pDraw) + (int)pDraw->width || 92805b261ecSmrg stuff->y < -wBorderWidth((WindowPtr)pDraw) || 92905b261ecSmrg stuff->y + (int)stuff->height > 93005b261ecSmrg wBorderWidth((WindowPtr)pDraw) + (int)pDraw->height 93105b261ecSmrg ) 93205b261ecSmrg return(BadMatch); 93305b261ecSmrg xgi.visual = wVisual(((WindowPtr)pDraw)); 93405b261ecSmrg } 93505b261ecSmrg else 93605b261ecSmrg { 93705b261ecSmrg if (stuff->x < 0 || 93805b261ecSmrg stuff->x+(int)stuff->width > pDraw->width || 93905b261ecSmrg stuff->y < 0 || 94005b261ecSmrg stuff->y+(int)stuff->height > pDraw->height 94105b261ecSmrg ) 94205b261ecSmrg return(BadMatch); 94305b261ecSmrg xgi.visual = None; 94405b261ecSmrg } 94505b261ecSmrg xgi.type = X_Reply; 94605b261ecSmrg xgi.length = 0; 94705b261ecSmrg xgi.sequenceNumber = client->sequence; 94805b261ecSmrg xgi.depth = pDraw->depth; 94905b261ecSmrg if(stuff->format == ZPixmap) 95005b261ecSmrg { 95105b261ecSmrg length = PixmapBytePad(stuff->width, pDraw->depth) * stuff->height; 95205b261ecSmrg } 95305b261ecSmrg else 95405b261ecSmrg { 95505b261ecSmrg lenPer = PixmapBytePad(stuff->width, 1) * stuff->height; 95605b261ecSmrg plane = ((Mask)1) << (pDraw->depth - 1); 95705b261ecSmrg /* only planes asked for */ 95805b261ecSmrg length = lenPer * Ones(stuff->planeMask & (plane | (plane - 1))); 95905b261ecSmrg } 96005b261ecSmrg 96105b261ecSmrg VERIFY_SHMSIZE(shmdesc, stuff->offset, length, client); 96205b261ecSmrg xgi.size = length; 96305b261ecSmrg 96405b261ecSmrg if (length == 0) 96505b261ecSmrg { 96605b261ecSmrg /* nothing to do */ 96705b261ecSmrg } 96805b261ecSmrg else if (stuff->format == ZPixmap) 96905b261ecSmrg { 97005b261ecSmrg (*pDraw->pScreen->GetImage)(pDraw, stuff->x, stuff->y, 97105b261ecSmrg stuff->width, stuff->height, 97205b261ecSmrg stuff->format, stuff->planeMask, 97305b261ecSmrg shmdesc->addr + stuff->offset); 97405b261ecSmrg } 97505b261ecSmrg else 97605b261ecSmrg { 97705b261ecSmrg 97805b261ecSmrg length = stuff->offset; 97905b261ecSmrg for (; plane; plane >>= 1) 98005b261ecSmrg { 98105b261ecSmrg if (stuff->planeMask & plane) 98205b261ecSmrg { 98305b261ecSmrg (*pDraw->pScreen->GetImage)(pDraw, 98405b261ecSmrg stuff->x, stuff->y, 98505b261ecSmrg stuff->width, stuff->height, 98605b261ecSmrg stuff->format, plane, 98705b261ecSmrg shmdesc->addr + length); 98805b261ecSmrg length += lenPer; 98905b261ecSmrg } 99005b261ecSmrg } 99105b261ecSmrg } 99205b261ecSmrg 99305b261ecSmrg if (client->swapped) { 99405b261ecSmrg swaps(&xgi.sequenceNumber, n); 99505b261ecSmrg swapl(&xgi.length, n); 99605b261ecSmrg swapl(&xgi.visual, n); 99705b261ecSmrg swapl(&xgi.size, n); 99805b261ecSmrg } 99905b261ecSmrg WriteToClient(client, sizeof(xShmGetImageReply), (char *)&xgi); 100005b261ecSmrg 100105b261ecSmrg return(client->noClientException); 100205b261ecSmrg} 100305b261ecSmrg 100405b261ecSmrgstatic PixmapPtr 10054642e01fSmrgfbShmCreatePixmap (ScreenPtr pScreen, 10064642e01fSmrg int width, int height, int depth, char *addr) 100705b261ecSmrg{ 10084642e01fSmrg PixmapPtr pPixmap; 100905b261ecSmrg 10104642e01fSmrg pPixmap = (*pScreen->CreatePixmap)(pScreen, 0, 0, pScreen->rootDepth, 0); 101105b261ecSmrg if (!pPixmap) 101205b261ecSmrg return NullPixmap; 101305b261ecSmrg 101405b261ecSmrg if (!(*pScreen->ModifyPixmapHeader)(pPixmap, width, height, depth, 101505b261ecSmrg BitsPerPixel(depth), PixmapBytePad(width, depth), (pointer)addr)) { 101605b261ecSmrg (*pScreen->DestroyPixmap)(pPixmap); 101705b261ecSmrg return NullPixmap; 101805b261ecSmrg } 101905b261ecSmrg return pPixmap; 102005b261ecSmrg} 102105b261ecSmrg 102205b261ecSmrgstatic int 10234642e01fSmrgProcShmCreatePixmap(ClientPtr client) 102405b261ecSmrg{ 102505b261ecSmrg PixmapPtr pMap; 102605b261ecSmrg DrawablePtr pDraw; 102705b261ecSmrg DepthPtr pDepth; 10284642e01fSmrg int i, rc; 102905b261ecSmrg ShmDescPtr shmdesc; 103005b261ecSmrg REQUEST(xShmCreatePixmapReq); 103105b261ecSmrg unsigned int width, height, depth; 103205b261ecSmrg unsigned long size; 103305b261ecSmrg 103405b261ecSmrg REQUEST_SIZE_MATCH(xShmCreatePixmapReq); 103505b261ecSmrg client->errorValue = stuff->pid; 103605b261ecSmrg if (!sharedPixmaps) 103705b261ecSmrg return BadImplementation; 103805b261ecSmrg LEGAL_NEW_RESOURCE(stuff->pid, client); 103905b261ecSmrg rc = dixLookupDrawable(&pDraw, stuff->drawable, client, M_ANY, 10404642e01fSmrg DixGetAttrAccess); 104105b261ecSmrg if (rc != Success) 104205b261ecSmrg return rc; 104305b261ecSmrg 104405b261ecSmrg VERIFY_SHMPTR(stuff->shmseg, stuff->offset, TRUE, shmdesc, client); 104505b261ecSmrg 104605b261ecSmrg width = stuff->width; 104705b261ecSmrg height = stuff->height; 104805b261ecSmrg depth = stuff->depth; 104905b261ecSmrg if (!width || !height || !depth) 105005b261ecSmrg { 105105b261ecSmrg client->errorValue = 0; 105205b261ecSmrg return BadValue; 105305b261ecSmrg } 105405b261ecSmrg if (width > 32767 || height > 32767) 105505b261ecSmrg return BadAlloc; 105605b261ecSmrg 105705b261ecSmrg if (stuff->depth != 1) 105805b261ecSmrg { 105905b261ecSmrg pDepth = pDraw->pScreen->allowedDepths; 106005b261ecSmrg for (i=0; i<pDraw->pScreen->numDepths; i++, pDepth++) 106105b261ecSmrg if (pDepth->depth == stuff->depth) 106205b261ecSmrg goto CreatePmap; 106305b261ecSmrg client->errorValue = stuff->depth; 106405b261ecSmrg return BadValue; 106505b261ecSmrg } 106605b261ecSmrg 106705b261ecSmrgCreatePmap: 106805b261ecSmrg size = PixmapBytePad(width, depth) * height; 106905b261ecSmrg if (sizeof(size) == 4 && BitsPerPixel(depth) > 8) { 107005b261ecSmrg if (size < width * height) 107105b261ecSmrg return BadAlloc; 107205b261ecSmrg } 107305b261ecSmrg /* thankfully, offset is unsigned */ 107405b261ecSmrg if (stuff->offset + size < size) 107505b261ecSmrg return BadAlloc; 107605b261ecSmrg 107705b261ecSmrg VERIFY_SHMSIZE(shmdesc, stuff->offset, size, client); 107805b261ecSmrg pMap = (*shmFuncs[pDraw->pScreen->myNum]->CreatePixmap)( 107905b261ecSmrg pDraw->pScreen, stuff->width, 108005b261ecSmrg stuff->height, stuff->depth, 108105b261ecSmrg shmdesc->addr + stuff->offset); 108205b261ecSmrg if (pMap) 108305b261ecSmrg { 10844642e01fSmrg rc = XaceHook(XACE_RESOURCE_ACCESS, client, stuff->pid, RT_PIXMAP, 10854642e01fSmrg pMap, RT_NONE, NULL, DixCreateAccess); 10864642e01fSmrg if (rc != Success) { 10874642e01fSmrg pDraw->pScreen->DestroyPixmap(pMap); 10884642e01fSmrg return rc; 10894642e01fSmrg } 10904642e01fSmrg dixSetPrivate(&pMap->devPrivates, shmPixmapPrivate, shmdesc); 109105b261ecSmrg shmdesc->refcnt++; 109205b261ecSmrg pMap->drawable.serialNumber = NEXT_SERIAL_NUMBER; 109305b261ecSmrg pMap->drawable.id = stuff->pid; 109405b261ecSmrg if (AddResource(stuff->pid, RT_PIXMAP, (pointer)pMap)) 109505b261ecSmrg { 109605b261ecSmrg return(client->noClientException); 109705b261ecSmrg } 10984642e01fSmrg pDraw->pScreen->DestroyPixmap(pMap); 109905b261ecSmrg } 110005b261ecSmrg return (BadAlloc); 110105b261ecSmrg} 110205b261ecSmrg 110305b261ecSmrgstatic int 11044642e01fSmrgProcShmDispatch (ClientPtr client) 110505b261ecSmrg{ 110605b261ecSmrg REQUEST(xReq); 110705b261ecSmrg switch (stuff->data) 110805b261ecSmrg { 110905b261ecSmrg case X_ShmQueryVersion: 111005b261ecSmrg return ProcShmQueryVersion(client); 111105b261ecSmrg case X_ShmAttach: 111205b261ecSmrg return ProcShmAttach(client); 111305b261ecSmrg case X_ShmDetach: 111405b261ecSmrg return ProcShmDetach(client); 111505b261ecSmrg case X_ShmPutImage: 111605b261ecSmrg#ifdef PANORAMIX 111705b261ecSmrg if ( !noPanoramiXExtension ) 111805b261ecSmrg return ProcPanoramiXShmPutImage(client); 111905b261ecSmrg#endif 112005b261ecSmrg return ProcShmPutImage(client); 112105b261ecSmrg case X_ShmGetImage: 112205b261ecSmrg#ifdef PANORAMIX 112305b261ecSmrg if ( !noPanoramiXExtension ) 112405b261ecSmrg return ProcPanoramiXShmGetImage(client); 112505b261ecSmrg#endif 112605b261ecSmrg return ProcShmGetImage(client); 112705b261ecSmrg case X_ShmCreatePixmap: 112805b261ecSmrg#ifdef PANORAMIX 112905b261ecSmrg if ( !noPanoramiXExtension ) 113005b261ecSmrg return ProcPanoramiXShmCreatePixmap(client); 113105b261ecSmrg#endif 113205b261ecSmrg return ProcShmCreatePixmap(client); 113305b261ecSmrg default: 113405b261ecSmrg return BadRequest; 113505b261ecSmrg } 113605b261ecSmrg} 113705b261ecSmrg 113805b261ecSmrgstatic void 11394642e01fSmrgSShmCompletionEvent(xShmCompletionEvent *from, xShmCompletionEvent *to) 114005b261ecSmrg{ 114105b261ecSmrg to->type = from->type; 114205b261ecSmrg cpswaps(from->sequenceNumber, to->sequenceNumber); 114305b261ecSmrg cpswapl(from->drawable, to->drawable); 114405b261ecSmrg cpswaps(from->minorEvent, to->minorEvent); 114505b261ecSmrg to->majorEvent = from->majorEvent; 114605b261ecSmrg cpswapl(from->shmseg, to->shmseg); 114705b261ecSmrg cpswapl(from->offset, to->offset); 114805b261ecSmrg} 114905b261ecSmrg 115005b261ecSmrgstatic int 11514642e01fSmrgSProcShmQueryVersion(ClientPtr client) 115205b261ecSmrg{ 11534642e01fSmrg int n; 115405b261ecSmrg REQUEST(xShmQueryVersionReq); 115505b261ecSmrg 115605b261ecSmrg swaps(&stuff->length, n); 115705b261ecSmrg return ProcShmQueryVersion(client); 115805b261ecSmrg} 115905b261ecSmrg 116005b261ecSmrgstatic int 11614642e01fSmrgSProcShmAttach(ClientPtr client) 116205b261ecSmrg{ 11634642e01fSmrg int n; 116405b261ecSmrg REQUEST(xShmAttachReq); 116505b261ecSmrg swaps(&stuff->length, n); 116605b261ecSmrg REQUEST_SIZE_MATCH(xShmAttachReq); 116705b261ecSmrg swapl(&stuff->shmseg, n); 116805b261ecSmrg swapl(&stuff->shmid, n); 116905b261ecSmrg return ProcShmAttach(client); 117005b261ecSmrg} 117105b261ecSmrg 117205b261ecSmrgstatic int 11734642e01fSmrgSProcShmDetach(ClientPtr client) 117405b261ecSmrg{ 11754642e01fSmrg int n; 117605b261ecSmrg REQUEST(xShmDetachReq); 117705b261ecSmrg swaps(&stuff->length, n); 117805b261ecSmrg REQUEST_SIZE_MATCH(xShmDetachReq); 117905b261ecSmrg swapl(&stuff->shmseg, n); 118005b261ecSmrg return ProcShmDetach(client); 118105b261ecSmrg} 118205b261ecSmrg 118305b261ecSmrgstatic int 11844642e01fSmrgSProcShmPutImage(ClientPtr client) 118505b261ecSmrg{ 11864642e01fSmrg int n; 118705b261ecSmrg REQUEST(xShmPutImageReq); 118805b261ecSmrg swaps(&stuff->length, n); 118905b261ecSmrg REQUEST_SIZE_MATCH(xShmPutImageReq); 119005b261ecSmrg swapl(&stuff->drawable, n); 119105b261ecSmrg swapl(&stuff->gc, n); 119205b261ecSmrg swaps(&stuff->totalWidth, n); 119305b261ecSmrg swaps(&stuff->totalHeight, n); 119405b261ecSmrg swaps(&stuff->srcX, n); 119505b261ecSmrg swaps(&stuff->srcY, n); 119605b261ecSmrg swaps(&stuff->srcWidth, n); 119705b261ecSmrg swaps(&stuff->srcHeight, n); 119805b261ecSmrg swaps(&stuff->dstX, n); 119905b261ecSmrg swaps(&stuff->dstY, n); 120005b261ecSmrg swapl(&stuff->shmseg, n); 120105b261ecSmrg swapl(&stuff->offset, n); 120205b261ecSmrg return ProcShmPutImage(client); 120305b261ecSmrg} 120405b261ecSmrg 120505b261ecSmrgstatic int 12064642e01fSmrgSProcShmGetImage(ClientPtr client) 120705b261ecSmrg{ 12084642e01fSmrg int n; 120905b261ecSmrg REQUEST(xShmGetImageReq); 121005b261ecSmrg swaps(&stuff->length, n); 121105b261ecSmrg REQUEST_SIZE_MATCH(xShmGetImageReq); 121205b261ecSmrg swapl(&stuff->drawable, n); 121305b261ecSmrg swaps(&stuff->x, n); 121405b261ecSmrg swaps(&stuff->y, n); 121505b261ecSmrg swaps(&stuff->width, n); 121605b261ecSmrg swaps(&stuff->height, n); 121705b261ecSmrg swapl(&stuff->planeMask, n); 121805b261ecSmrg swapl(&stuff->shmseg, n); 121905b261ecSmrg swapl(&stuff->offset, n); 122005b261ecSmrg return ProcShmGetImage(client); 122105b261ecSmrg} 122205b261ecSmrg 122305b261ecSmrgstatic int 12244642e01fSmrgSProcShmCreatePixmap(ClientPtr client) 122505b261ecSmrg{ 12264642e01fSmrg int n; 122705b261ecSmrg REQUEST(xShmCreatePixmapReq); 122805b261ecSmrg swaps(&stuff->length, n); 122905b261ecSmrg REQUEST_SIZE_MATCH(xShmCreatePixmapReq); 123005b261ecSmrg swapl(&stuff->pid, n); 123105b261ecSmrg swapl(&stuff->drawable, n); 123205b261ecSmrg swaps(&stuff->width, n); 123305b261ecSmrg swaps(&stuff->height, n); 123405b261ecSmrg swapl(&stuff->shmseg, n); 123505b261ecSmrg swapl(&stuff->offset, n); 123605b261ecSmrg return ProcShmCreatePixmap(client); 123705b261ecSmrg} 123805b261ecSmrg 123905b261ecSmrgstatic int 12404642e01fSmrgSProcShmDispatch (ClientPtr client) 124105b261ecSmrg{ 124205b261ecSmrg REQUEST(xReq); 124305b261ecSmrg switch (stuff->data) 124405b261ecSmrg { 124505b261ecSmrg case X_ShmQueryVersion: 124605b261ecSmrg return SProcShmQueryVersion(client); 124705b261ecSmrg case X_ShmAttach: 124805b261ecSmrg return SProcShmAttach(client); 124905b261ecSmrg case X_ShmDetach: 125005b261ecSmrg return SProcShmDetach(client); 125105b261ecSmrg case X_ShmPutImage: 125205b261ecSmrg return SProcShmPutImage(client); 125305b261ecSmrg case X_ShmGetImage: 125405b261ecSmrg return SProcShmGetImage(client); 125505b261ecSmrg case X_ShmCreatePixmap: 125605b261ecSmrg return SProcShmCreatePixmap(client); 125705b261ecSmrg default: 125805b261ecSmrg return BadRequest; 125905b261ecSmrg } 126005b261ecSmrg} 1261