645 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C
		
	
	
	
			
		
		
	
	
			645 lines
		
	
	
		
			18 KiB
		
	
	
	
		
			C
		
	
	
	
| /***********************************************************
 | |
| 
 | |
| Copyright 1987, 1998  The Open Group
 | |
| 
 | |
| Permission to use, copy, modify, distribute, and sell this software and its
 | |
| documentation for any purpose is hereby granted without fee, provided that
 | |
| the above copyright notice appear in all copies and that both that
 | |
| copyright notice and this permission notice appear in supporting
 | |
| documentation.
 | |
| 
 | |
| The above copyright notice and this permission notice shall be included in
 | |
| all copies or substantial portions of the Software.
 | |
| 
 | |
| THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 | |
| IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 | |
| FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
 | |
| OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
 | |
| AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
 | |
| CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
 | |
| 
 | |
| Except as contained in this notice, the name of The Open Group shall not be
 | |
| used in advertising or otherwise to promote the sale, use or other dealings
 | |
| in this Software without prior written authorization from The Open Group.
 | |
| 
 | |
| 
 | |
| Copyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts.
 | |
| 
 | |
|                         All Rights Reserved
 | |
| 
 | |
| Permission to use, copy, modify, and distribute this software and its 
 | |
| documentation for any purpose and without fee is hereby granted, 
 | |
| provided that the above copyright notice appear in all copies and that
 | |
| both that copyright notice and this permission notice appear in 
 | |
| supporting documentation, and that the name of Digital not be
 | |
| used in advertising or publicity pertaining to distribution of the
 | |
| software without specific, written prior permission.  
 | |
| 
 | |
| DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
 | |
| ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
 | |
| DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
 | |
| ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
 | |
| WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
 | |
| ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
 | |
| SOFTWARE.
 | |
| 
 | |
| ******************************************************************/
 | |
| 
 | |
| #ifdef HAVE_DIX_CONFIG_H
 | |
| #include <dix-config.h>
 | |
| #endif
 | |
| 
 | |
| #include <X11/X.h>
 | |
| #include <X11/Xproto.h>
 | |
| #include "windowstr.h"
 | |
| #include "propertyst.h"
 | |
| #include "dixstruct.h"
 | |
| #include "dispatch.h"
 | |
| #include "swaprep.h"
 | |
| #include "xace.h"
 | |
| 
 | |
| /*****************************************************************
 | |
|  * Property Stuff
 | |
|  *
 | |
|  *    dixLookupProperty, dixChangeProperty, DeleteProperty
 | |
|  *
 | |
|  *   Properties belong to windows.  The list of properties should not be
 | |
|  *   traversed directly.  Instead, use the three functions listed above.
 | |
|  *
 | |
|  *****************************************************************/
 | |
| 
 | |
| #ifdef notdef
 | |
| static void
 | |
| PrintPropertys(WindowPtr pWin)
 | |
| {
 | |
|     PropertyPtr pProp;
 | |
|     int j;
 | |
| 
 | |
|     pProp = pWin->userProps;
 | |
|     while (pProp)
 | |
|     {
 | |
|         ErrorF("[dix] %x %x\n", pProp->propertyName, pProp->type);
 | |
|         ErrorF("[dix] property format: %d\n", pProp->format);
 | |
|         ErrorF("[dix] property data: \n");
 | |
|         for (j=0; j<(pProp->format/8)*pProp->size; j++)
 | |
|            ErrorF("[dix] %c\n", pProp->data[j]);
 | |
|         pProp = pProp->next;
 | |
|     }
 | |
| }
 | |
| #endif
 | |
| 
 | |
| int
 | |
| dixLookupProperty(PropertyPtr *result, WindowPtr pWin, Atom propertyName,
 | |
| 		  ClientPtr client, Mask access_mode)
 | |
| {
 | |
|     PropertyPtr pProp;
 | |
|     int rc = BadMatch;
 | |
|     client->errorValue = propertyName;
 | |
| 
 | |
|     for (pProp = wUserProps(pWin); pProp; pProp = pProp->next)
 | |
| 	if (pProp->propertyName == propertyName)
 | |
| 	    break;
 | |
| 
 | |
|     if (pProp)
 | |
| 	rc = XaceHookPropertyAccess(client, pWin, &pProp, access_mode);
 | |
|     *result = pProp;
 | |
|     return rc;
 | |
| }
 | |
| 
 | |
| static void
 | |
| deliverPropertyNotifyEvent(WindowPtr pWin, int state, Atom atom)
 | |
| {
 | |
|     xEvent event;
 | |
| 
 | |
|     memset(&event, 0, sizeof(xEvent));
 | |
|     event.u.u.type = PropertyNotify;
 | |
|     event.u.property.window = pWin->drawable.id;
 | |
|     event.u.property.state = state;
 | |
|     event.u.property.atom = atom;
 | |
|     event.u.property.time = currentTime.milliseconds;
 | |
|     DeliverEvents(pWin, &event, 1, (WindowPtr)NULL);
 | |
| }
 | |
| 
 | |
| int
 | |
| ProcRotateProperties(ClientPtr client)
 | |
| {
 | |
|     int     i, j, delta, rc;
 | |
|     REQUEST(xRotatePropertiesReq);
 | |
|     WindowPtr pWin;
 | |
|     Atom * atoms;
 | |
|     PropertyPtr * props;               /* array of pointer */
 | |
|     PropertyPtr pProp, saved;
 | |
| 
 | |
|     REQUEST_FIXED_SIZE(xRotatePropertiesReq, stuff->nAtoms << 2);
 | |
|     UpdateCurrentTime();
 | |
|     rc = dixLookupWindow(&pWin, stuff->window, client, DixSetPropAccess);
 | |
|     if (rc != Success || stuff->nAtoms <= 0)
 | |
|         return rc;
 | |
| 
 | |
|     atoms = (Atom *) & stuff[1];
 | |
|     props = malloc(stuff->nAtoms * sizeof(PropertyPtr));
 | |
|     saved = malloc(stuff->nAtoms * sizeof(PropertyRec));
 | |
|     if (!props || !saved) {
 | |
| 	rc = BadAlloc;
 | |
| 	goto out;
 | |
|     }
 | |
| 
 | |
|     for (i = 0; i < stuff->nAtoms; i++)
 | |
|     {
 | |
|         if (!ValidAtom(atoms[i])) {
 | |
| 	    rc = BadAtom;
 | |
| 	    client->errorValue = atoms[i];
 | |
| 	    goto out;
 | |
|         }
 | |
|         for (j = i + 1; j < stuff->nAtoms; j++)
 | |
|             if (atoms[j] == atoms[i])
 | |
|             {
 | |
| 		rc = BadMatch;
 | |
| 		goto out;
 | |
|             }
 | |
| 
 | |
| 	rc = dixLookupProperty(&pProp, pWin, atoms[i], client,
 | |
| 			       DixReadAccess|DixWriteAccess);
 | |
| 	if (rc != Success)
 | |
| 	    goto out;
 | |
| 
 | |
|         props[i] = pProp;
 | |
| 	saved[i] = *pProp;
 | |
|     }
 | |
|     delta = stuff->nPositions;
 | |
| 
 | |
|     /* If the rotation is a complete 360 degrees, then moving the properties
 | |
| 	around and generating PropertyNotify events should be skipped. */
 | |
| 
 | |
|     if (abs(delta) % stuff->nAtoms)
 | |
|     {
 | |
| 	while (delta < 0)                  /* faster if abs value is small */
 | |
|             delta += stuff->nAtoms;
 | |
|     	for (i = 0; i < stuff->nAtoms; i++)
 | |
|  	{
 | |
| 	    j = (i + delta) % stuff->nAtoms;
 | |
| 	    deliverPropertyNotifyEvent(pWin, PropertyNewValue, atoms[i]);
 | |
| 
 | |
| 	    /* Preserve name and devPrivates */
 | |
| 	    props[j]->type = saved[i].type;
 | |
| 	    props[j]->format = saved[i].format;
 | |
| 	    props[j]->size = saved[i].size;
 | |
| 	    props[j]->data = saved[i].data;
 | |
| 	}
 | |
|     }
 | |
| out:
 | |
|     free(saved);
 | |
|     free(props);
 | |
|     return rc;
 | |
| }
 | |
| 
 | |
| int 
 | |
| ProcChangeProperty(ClientPtr client)
 | |
| {	      
 | |
|     WindowPtr pWin;
 | |
|     char format, mode;
 | |
|     unsigned long len;
 | |
|     int sizeInBytes, totalSize, err;
 | |
|     REQUEST(xChangePropertyReq);
 | |
| 
 | |
|     REQUEST_AT_LEAST_SIZE(xChangePropertyReq);
 | |
|     UpdateCurrentTime();
 | |
|     format = stuff->format;
 | |
|     mode = stuff->mode;
 | |
|     if ((mode != PropModeReplace) && (mode != PropModeAppend) &&
 | |
| 	(mode != PropModePrepend))
 | |
|     {
 | |
| 	client->errorValue = mode;
 | |
| 	return BadValue;
 | |
|     }
 | |
|     if ((format != 8) && (format != 16) && (format != 32))
 | |
|     {
 | |
| 	client->errorValue = format;
 | |
|         return BadValue;
 | |
|     }
 | |
|     len = stuff->nUnits;
 | |
|     if (len > bytes_to_int32(0xffffffff - sizeof(xChangePropertyReq)))
 | |
| 	return BadLength;
 | |
|     sizeInBytes = format>>3;
 | |
|     totalSize = len * sizeInBytes;
 | |
|     REQUEST_FIXED_SIZE(xChangePropertyReq, totalSize);
 | |
| 
 | |
|     err = dixLookupWindow(&pWin, stuff->window, client, DixSetPropAccess);
 | |
|     if (err != Success)
 | |
| 	return err;
 | |
|     if (!ValidAtom(stuff->property))
 | |
|     {
 | |
| 	client->errorValue = stuff->property;
 | |
| 	return BadAtom;
 | |
|     }
 | |
|     if (!ValidAtom(stuff->type))
 | |
|     {
 | |
| 	client->errorValue = stuff->type;
 | |
| 	return BadAtom;
 | |
|     }
 | |
| 
 | |
|     err = dixChangeWindowProperty(client, pWin, stuff->property, stuff->type,
 | |
| 				  (int)format, (int)mode, len, &stuff[1],
 | |
| 				  TRUE);
 | |
|     if (err != Success)
 | |
| 	return err;
 | |
|     else
 | |
| 	return Success;
 | |
| }
 | |
| 
 | |
| int
 | |
| dixChangeWindowProperty(ClientPtr pClient, WindowPtr pWin, Atom property,
 | |
| 			Atom type, int format, int mode, unsigned long len,
 | |
| 			pointer value, Bool sendevent)
 | |
| {
 | |
|     PropertyPtr pProp;
 | |
|     PropertyRec savedProp;
 | |
|     int sizeInBytes, totalSize, rc;
 | |
|     unsigned char *data;
 | |
|     Mask access_mode;
 | |
| 
 | |
|     sizeInBytes = format>>3;
 | |
|     totalSize = len * sizeInBytes;
 | |
|     access_mode = (mode == PropModeReplace) ? DixWriteAccess : DixBlendAccess;
 | |
| 
 | |
|     /* first see if property already exists */
 | |
|     rc = dixLookupProperty(&pProp, pWin, property, pClient, access_mode);
 | |
| 
 | |
|     if (rc == BadMatch)   /* just add to list */
 | |
|     {
 | |
| 	if (!pWin->optional && !MakeWindowOptional (pWin))
 | |
| 	    return BadAlloc;
 | |
| 	pProp = dixAllocateObjectWithPrivates(PropertyRec, PRIVATE_PROPERTY);
 | |
| 	if (!pProp)
 | |
| 	    return BadAlloc;
 | |
|         data = malloc(totalSize);
 | |
| 	if (!data && len)
 | |
| 	{
 | |
| 	    dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY);
 | |
| 	    return BadAlloc;
 | |
| 	}
 | |
|         memcpy(data, value, totalSize);
 | |
|         pProp->propertyName = property;
 | |
|         pProp->type = type;
 | |
|         pProp->format = format;
 | |
|         pProp->data = data;
 | |
| 	pProp->size = len;
 | |
| 	rc = XaceHookPropertyAccess(pClient, pWin, &pProp,
 | |
| 				    DixCreateAccess|DixWriteAccess);
 | |
| 	if (rc != Success) {
 | |
| 	    free(data);
 | |
| 	    dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY);
 | |
| 	    pClient->errorValue = property;
 | |
| 	    return rc;
 | |
| 	}
 | |
|         pProp->next = pWin->optional->userProps;
 | |
|         pWin->optional->userProps = pProp;
 | |
|     }
 | |
|     else if (rc == Success)
 | |
|     {
 | |
| 	/* To append or prepend to a property the request format and type
 | |
| 		must match those of the already defined property.  The
 | |
| 		existing format and type are irrelevant when using the mode
 | |
| 		"PropModeReplace" since they will be written over. */
 | |
| 
 | |
|         if ((format != pProp->format) && (mode != PropModeReplace))
 | |
| 	    return BadMatch;
 | |
|         if ((pProp->type != type) && (mode != PropModeReplace))
 | |
|             return BadMatch;
 | |
| 
 | |
| 	/* save the old values for later */
 | |
| 	savedProp = *pProp;
 | |
| 
 | |
|         if (mode == PropModeReplace)
 | |
|         {
 | |
| 	    data = malloc(totalSize);
 | |
| 	    if (!data && len)
 | |
| 		return BadAlloc;
 | |
| 	    memcpy(data, value, totalSize);
 | |
| 	    pProp->data = data;
 | |
| 	    pProp->size = len;
 | |
|     	    pProp->type = type;
 | |
| 	    pProp->format = format;
 | |
| 	}
 | |
| 	else if (len == 0)
 | |
| 	{
 | |
| 	    /* do nothing */
 | |
| 	}
 | |
|         else if (mode == PropModeAppend)
 | |
|         {
 | |
| 	    data = malloc((pProp->size + len) * sizeInBytes);
 | |
| 	    if (!data)
 | |
| 		return BadAlloc;
 | |
| 	    memcpy(data, pProp->data, pProp->size * sizeInBytes);
 | |
| 	    memcpy(data + pProp->size * sizeInBytes, value, totalSize);
 | |
|             pProp->data = data;
 | |
|             pProp->size += len;
 | |
| 	}
 | |
|         else if (mode == PropModePrepend)
 | |
|         {
 | |
|             data = malloc(sizeInBytes * (len + pProp->size));
 | |
| 	    if (!data)
 | |
| 		return BadAlloc;
 | |
|             memcpy(data + totalSize, pProp->data, pProp->size * sizeInBytes);
 | |
|             memcpy(data, value, totalSize);
 | |
|             pProp->data = data;
 | |
|             pProp->size += len;
 | |
| 	}
 | |
| 
 | |
| 	/* Allow security modules to check the new content */
 | |
| 	access_mode |= DixPostAccess;
 | |
| 	rc = XaceHookPropertyAccess(pClient, pWin, &pProp, access_mode);
 | |
| 	if (rc == Success)
 | |
| 	{
 | |
| 	    if (savedProp.data != pProp->data)
 | |
| 		free(savedProp.data);
 | |
| 	}
 | |
| 	else
 | |
| 	{
 | |
| 	    if (savedProp.data != pProp->data)
 | |
| 		free(pProp->data);
 | |
| 	    *pProp = savedProp;
 | |
| 	    return rc;
 | |
| 	}
 | |
|     }
 | |
|     else
 | |
| 	return rc;
 | |
| 
 | |
|     if (sendevent)
 | |
| 	deliverPropertyNotifyEvent(pWin, PropertyNewValue, pProp->propertyName);
 | |
| 
 | |
|     return Success;
 | |
| }
 | |
| 
 | |
| int
 | |
| ChangeWindowProperty(WindowPtr pWin, Atom property, Atom type, int format, 
 | |
| 		     int mode, unsigned long len, pointer value, 
 | |
| 		     Bool sendevent)
 | |
| {
 | |
|     return dixChangeWindowProperty(serverClient, pWin, property, type, format,
 | |
| 				   mode, len, value, sendevent);
 | |
| }
 | |
| 
 | |
| int
 | |
| DeleteProperty(ClientPtr client, WindowPtr pWin, Atom propName)
 | |
| {
 | |
|     PropertyPtr pProp, prevProp;
 | |
|     int rc;
 | |
| 
 | |
|     rc = dixLookupProperty(&pProp, pWin, propName, client, DixDestroyAccess);
 | |
|     if (rc == BadMatch)
 | |
| 	return Success; /* Succeed if property does not exist */
 | |
| 
 | |
|     if (rc == Success) {
 | |
| 	if (pWin->optional->userProps == pProp) {
 | |
| 	    /* Takes care of head */
 | |
|             if (!(pWin->optional->userProps = pProp->next))
 | |
| 		CheckWindowOptionalNeed (pWin);
 | |
| 	} else {
 | |
| 	    /* Need to traverse to find the previous element */
 | |
| 	    prevProp = pWin->optional->userProps;
 | |
| 	    while (prevProp->next != pProp)
 | |
| 		prevProp = prevProp->next;
 | |
| 	    prevProp->next = pProp->next;
 | |
| 	}
 | |
| 
 | |
| 	deliverPropertyNotifyEvent(pWin, PropertyDelete, pProp->propertyName);
 | |
| 	free(pProp->data);
 | |
| 	dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY);
 | |
|     }
 | |
|     return rc;
 | |
| }
 | |
| 
 | |
| void
 | |
| DeleteAllWindowProperties(WindowPtr pWin)
 | |
| {
 | |
|     PropertyPtr pProp, pNextProp;
 | |
| 
 | |
|     pProp = wUserProps (pWin);
 | |
|     while (pProp)
 | |
|     {
 | |
| 	deliverPropertyNotifyEvent(pWin, PropertyDelete, pProp->propertyName);
 | |
| 	pNextProp = pProp->next;
 | |
|         free(pProp->data);
 | |
| 	dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY);
 | |
| 	pProp = pNextProp;
 | |
|     }
 | |
| 
 | |
|     if (pWin->optional)
 | |
|         pWin->optional->userProps = NULL;
 | |
| }
 | |
| 
 | |
| static int
 | |
| NullPropertyReply(
 | |
|     ClientPtr client,
 | |
|     ATOM propertyType,
 | |
|     int format,
 | |
|     xGetPropertyReply *reply)
 | |
| {
 | |
|     reply->nItems = 0;
 | |
|     reply->length = 0;
 | |
|     reply->bytesAfter = 0;
 | |
|     reply->propertyType = propertyType;
 | |
|     reply->format = format;
 | |
|     WriteReplyToClient(client, sizeof(xGenericReply), reply);
 | |
|     return Success;
 | |
| }
 | |
| 
 | |
| /*****************
 | |
|  * GetProperty
 | |
|  *    If type Any is specified, returns the property from the specified
 | |
|  *    window regardless of its type.  If a type is specified, returns the
 | |
|  *    property only if its type equals the specified type.
 | |
|  *    If delete is True and a property is returned, the property is also
 | |
|  *    deleted from the window and a PropertyNotify event is generated on the
 | |
|  *    window.
 | |
|  *****************/
 | |
| 
 | |
| int
 | |
| ProcGetProperty(ClientPtr client)
 | |
| {
 | |
|     PropertyPtr pProp, prevProp;
 | |
|     unsigned long n, len, ind;
 | |
|     int rc;
 | |
|     WindowPtr pWin;
 | |
|     xGetPropertyReply reply;
 | |
|     Mask win_mode = DixGetPropAccess, prop_mode = DixReadAccess;
 | |
|     REQUEST(xGetPropertyReq);
 | |
| 
 | |
|     REQUEST_SIZE_MATCH(xGetPropertyReq);
 | |
|     if (stuff->delete) {
 | |
| 	UpdateCurrentTime();
 | |
| 	win_mode |= DixSetPropAccess;
 | |
| 	prop_mode |= DixDestroyAccess;
 | |
|     }
 | |
|     rc = dixLookupWindow(&pWin, stuff->window, client, win_mode);
 | |
|     if (rc != Success)
 | |
| 	return (rc == BadMatch) ? BadWindow : rc;
 | |
| 
 | |
|     if (!ValidAtom(stuff->property))
 | |
|     {
 | |
| 	client->errorValue = stuff->property;
 | |
| 	return BadAtom;
 | |
|     }
 | |
|     if ((stuff->delete != xTrue) && (stuff->delete != xFalse))
 | |
|     {
 | |
| 	client->errorValue = stuff->delete;
 | |
| 	return BadValue;
 | |
|     }
 | |
|     if ((stuff->type != AnyPropertyType) && !ValidAtom(stuff->type))
 | |
|     {
 | |
| 	client->errorValue = stuff->type;
 | |
| 	return BadAtom;
 | |
|     }
 | |
| 
 | |
|     memset(&reply, 0, sizeof(xGetPropertyReply));
 | |
|     reply.type = X_Reply;
 | |
|     reply.sequenceNumber = client->sequence;
 | |
| 
 | |
|     rc = dixLookupProperty(&pProp, pWin, stuff->property, client, prop_mode);
 | |
|     if (rc == BadMatch)
 | |
| 	return NullPropertyReply(client, None, 0, &reply);
 | |
|     else if (rc != Success)
 | |
| 	return rc;
 | |
| 
 | |
|     /* If the request type and actual type don't match. Return the
 | |
|     property information, but not the data. */
 | |
| 
 | |
|     if (((stuff->type != pProp->type) &&
 | |
| 	 (stuff->type != AnyPropertyType))
 | |
|        )
 | |
|     {
 | |
| 	reply.bytesAfter = pProp->size;
 | |
| 	reply.format = pProp->format;
 | |
| 	reply.length = 0;
 | |
| 	reply.nItems = 0;
 | |
| 	reply.propertyType = pProp->type;
 | |
| 	WriteReplyToClient(client, sizeof(xGenericReply), &reply);
 | |
| 	return Success;
 | |
|     }
 | |
| 
 | |
| /*
 | |
|  *  Return type, format, value to client
 | |
|  */
 | |
|     n = (pProp->format/8) * pProp->size; /* size (bytes) of prop */
 | |
|     ind = stuff->longOffset << 2;        
 | |
| 
 | |
|    /* If longOffset is invalid such that it causes "len" to
 | |
| 	    be negative, it's a value error. */
 | |
| 
 | |
|     if (n < ind)
 | |
|     {
 | |
| 	client->errorValue = stuff->longOffset;
 | |
| 	return BadValue;
 | |
|     }
 | |
| 
 | |
|     len = min(n - ind, 4 * stuff->longLength);
 | |
| 
 | |
|     reply.bytesAfter = n - (ind + len);
 | |
|     reply.format = pProp->format;
 | |
|     reply.length = bytes_to_int32(len);
 | |
|     reply.nItems = len / (pProp->format / 8 );
 | |
|     reply.propertyType = pProp->type;
 | |
| 
 | |
|     if (stuff->delete && (reply.bytesAfter == 0))
 | |
| 	deliverPropertyNotifyEvent(pWin, PropertyDelete, pProp->propertyName);
 | |
| 
 | |
|     WriteReplyToClient(client, sizeof(xGenericReply), &reply);
 | |
|     if (len)
 | |
|     {
 | |
| 	switch (reply.format) {
 | |
| 	case 32: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap32Write; break;
 | |
| 	case 16: client->pSwapReplyFunc = (ReplySwapPtr)CopySwap16Write; break;
 | |
| 	default: client->pSwapReplyFunc = (ReplySwapPtr)WriteToClient; break;
 | |
| 	}
 | |
| 	WriteSwappedDataToClient(client, len,
 | |
| 				 (char *)pProp->data + ind);
 | |
|     }
 | |
| 
 | |
|     if (stuff->delete && (reply.bytesAfter == 0)) {
 | |
| 	/* Delete the Property */
 | |
| 	if (pWin->optional->userProps == pProp) {
 | |
| 	    /* Takes care of head */
 | |
|             if (!(pWin->optional->userProps = pProp->next))
 | |
| 		CheckWindowOptionalNeed (pWin);
 | |
| 	} else {
 | |
| 	    /* Need to traverse to find the previous element */
 | |
| 	    prevProp = pWin->optional->userProps;
 | |
| 	    while (prevProp->next != pProp)
 | |
| 		prevProp = prevProp->next;
 | |
| 	    prevProp->next = pProp->next;
 | |
| 	}
 | |
| 
 | |
| 	free(pProp->data);
 | |
| 	dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY);
 | |
|     }
 | |
|     return Success;
 | |
| }
 | |
| 
 | |
| int
 | |
| ProcListProperties(ClientPtr client)
 | |
| {
 | |
|     Atom *pAtoms = NULL, *temppAtoms;
 | |
|     xListPropertiesReply xlpr;
 | |
|     int	rc, numProps = 0;
 | |
|     WindowPtr pWin;
 | |
|     PropertyPtr pProp, realProp;
 | |
|     REQUEST(xResourceReq);
 | |
| 
 | |
|     REQUEST_SIZE_MATCH(xResourceReq);
 | |
|     rc = dixLookupWindow(&pWin, stuff->id, client, DixListPropAccess);
 | |
|     if (rc != Success)
 | |
|         return rc;
 | |
| 
 | |
|     for (pProp = wUserProps(pWin); pProp; pProp = pProp->next)
 | |
| 	numProps++;
 | |
| 
 | |
|     if (numProps && !(pAtoms = malloc(numProps * sizeof(Atom))))
 | |
| 	return BadAlloc;
 | |
| 
 | |
|     numProps = 0;
 | |
|     temppAtoms = pAtoms;
 | |
|     for (pProp = wUserProps(pWin); pProp; pProp = pProp->next) {
 | |
| 	realProp = pProp;
 | |
| 	rc = XaceHookPropertyAccess(client, pWin, &realProp, DixGetAttrAccess);
 | |
| 	if (rc == Success && realProp == pProp) {
 | |
| 	    *temppAtoms++ = pProp->propertyName;
 | |
| 	    numProps++;
 | |
| 	}
 | |
|     }
 | |
| 
 | |
|     xlpr.type = X_Reply;
 | |
|     xlpr.nProperties = numProps;
 | |
|     xlpr.length = bytes_to_int32(numProps * sizeof(Atom));
 | |
|     xlpr.sequenceNumber = client->sequence;
 | |
|     WriteReplyToClient(client, sizeof(xGenericReply), &xlpr);
 | |
|     if (numProps)
 | |
|     {
 | |
|         client->pSwapReplyFunc = (ReplySwapPtr)Swap32Write;
 | |
|         WriteSwappedDataToClient(client, numProps * sizeof(Atom), pAtoms);
 | |
|     }
 | |
|     free(pAtoms);
 | |
|     return Success;
 | |
| }
 | |
| 
 | |
| int 
 | |
| ProcDeleteProperty(ClientPtr client)
 | |
| {
 | |
|     WindowPtr pWin;
 | |
|     REQUEST(xDeletePropertyReq);
 | |
|     int result;
 | |
|               
 | |
|     REQUEST_SIZE_MATCH(xDeletePropertyReq);
 | |
|     UpdateCurrentTime();
 | |
|     result = dixLookupWindow(&pWin, stuff->window, client, DixSetPropAccess);
 | |
|     if (result != Success)
 | |
|         return result;
 | |
|     if (!ValidAtom(stuff->property))
 | |
|     {
 | |
| 	client->errorValue = stuff->property;
 | |
| 	return BadAtom;
 | |
|     }
 | |
| 
 | |
|     return DeleteProperty(client, pWin, stuff->property);
 | |
| }
 |