aboutsummaryrefslogtreecommitdiff
path: root/xorg-server/dix/property.c
diff options
context:
space:
mode:
authormarha <marha@users.sourceforge.net>2010-05-16 20:50:58 +0000
committermarha <marha@users.sourceforge.net>2010-05-16 20:50:58 +0000
commit1c94119ae26b94a60bb2c2b33494ed43c3b8a52f (patch)
treecfe0c736c95314edac7d9f1065be9c13026ed0c1 /xorg-server/dix/property.c
parent6b29aa4559aeb6f795caee047561654bfa0a1954 (diff)
downloadvcxsrv-1c94119ae26b94a60bb2c2b33494ed43c3b8a52f.tar.gz
vcxsrv-1c94119ae26b94a60bb2c2b33494ed43c3b8a52f.tar.bz2
vcxsrv-1c94119ae26b94a60bb2c2b33494ed43c3b8a52f.zip
svn merge -r588:HEAD ^/branches/released .
Diffstat (limited to 'xorg-server/dix/property.c')
-rw-r--r--xorg-server/dix/property.c1294
1 files changed, 645 insertions, 649 deletions
diff --git a/xorg-server/dix/property.c b/xorg-server/dix/property.c
index 9ec5dc6ae..7c4bd62d2 100644
--- a/xorg-server/dix/property.c
+++ b/xorg-server/dix/property.c
@@ -1,649 +1,645 @@
-/***********************************************************
-
-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 = xalloc(stuff->nAtoms * sizeof(PropertyPtr));
- saved = xalloc(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:
- xfree(saved);
- xfree(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 client->noClientException;
-}
-
-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 = xalloc(sizeof(PropertyRec));
- if (!pProp)
- return(BadAlloc);
- data = xalloc(totalSize);
- if (!data && len)
- {
- xfree(pProp);
- return(BadAlloc);
- }
- memcpy(data, value, totalSize);
- pProp->propertyName = property;
- pProp->type = type;
- pProp->format = format;
- pProp->data = data;
- pProp->size = len;
- pProp->devPrivates = NULL;
- rc = XaceHookPropertyAccess(pClient, pWin, &pProp,
- DixCreateAccess|DixWriteAccess);
- if (rc != Success) {
- xfree(data);
- xfree(pProp);
- 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 = xalloc(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 = xalloc((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 = xalloc(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)
- xfree(savedProp.data);
- }
- else
- {
- if (savedProp.data != pProp->data)
- xfree(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);
- dixFreePrivates(pProp->devPrivates);
- xfree(pProp->data);
- xfree(pProp);
- }
- return rc;
-}
-
-void
-DeleteAllWindowProperties(WindowPtr pWin)
-{
- PropertyPtr pProp, pNextProp;
-
- pProp = wUserProps (pWin);
- while (pProp)
- {
- deliverPropertyNotifyEvent(pWin, PropertyDelete, pProp->propertyName);
- pNextProp = pProp->next;
- dixFreePrivates(pProp->devPrivates);
- xfree(pProp->data);
- xfree(pProp);
- pProp = pNextProp;
- }
-}
-
-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(client->noClientException);
-}
-
-/*****************
- * 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;
- }
-
- dixFreePrivates(pProp->devPrivates);
- xfree(pProp->data);
- xfree(pProp);
- }
- return(client->noClientException);
-}
-
-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 = xalloc(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);
- }
- xfree(pAtoms);
- return(client->noClientException);
-}
-
-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);
- }
-
- result = DeleteProperty(client, pWin, stuff->property);
- if (client->noClientException != Success)
- return(client->noClientException);
- else
- return(result);
-}
+/***********************************************************
+
+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 = malloc(sizeof(PropertyRec));
+ if (!pProp)
+ return(BadAlloc);
+ data = malloc(totalSize);
+ if (!data && len)
+ {
+ free(pProp);
+ return(BadAlloc);
+ }
+ memcpy(data, value, totalSize);
+ pProp->propertyName = property;
+ pProp->type = type;
+ pProp->format = format;
+ pProp->data = data;
+ pProp->size = len;
+ pProp->devPrivates = NULL;
+ rc = XaceHookPropertyAccess(pClient, pWin, &pProp,
+ DixCreateAccess|DixWriteAccess);
+ if (rc != Success) {
+ free(data);
+ free(pProp);
+ 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);
+ dixFreePrivates(pProp->devPrivates);
+ free(pProp->data);
+ free(pProp);
+ }
+ return rc;
+}
+
+void
+DeleteAllWindowProperties(WindowPtr pWin)
+{
+ PropertyPtr pProp, pNextProp;
+
+ pProp = wUserProps (pWin);
+ while (pProp)
+ {
+ deliverPropertyNotifyEvent(pWin, PropertyDelete, pProp->propertyName);
+ pNextProp = pProp->next;
+ dixFreePrivates(pProp->devPrivates);
+ free(pProp->data);
+ free(pProp);
+ pProp = pNextProp;
+ }
+}
+
+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;
+ }
+
+ dixFreePrivates(pProp->devPrivates);
+ free(pProp->data);
+ free(pProp);
+ }
+ 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);
+}