summaryrefslogtreecommitdiff
path: root/lbx/lbxprop.c
diff options
context:
space:
mode:
Diffstat (limited to 'lbx/lbxprop.c')
-rw-r--r--lbx/lbxprop.c552
1 files changed, 552 insertions, 0 deletions
diff --git a/lbx/lbxprop.c b/lbx/lbxprop.c
new file mode 100644
index 000000000..b70fade72
--- /dev/null
+++ b/lbx/lbxprop.c
@@ -0,0 +1,552 @@
+/* $Xorg: lbxprop.c,v 1.4 2001/02/09 02:05:17 xorgcvs Exp $ */
+/*
+
+Copyright 1986, 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 1993 Network Computing Devices, Inc.
+ *
+ * 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, and that the name Network Computing Devices, Inc. not be
+ * used in advertising or publicity pertaining to distribution of this
+ * software without specific, written prior permission.
+ *
+ * THIS SOFTWARE IS PROVIDED `AS-IS'. NETWORK COMPUTING DEVICES, INC.,
+ * DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING WITHOUT
+ * LIMITATION ALL IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR A
+ * PARTICULAR PURPOSE, OR NONINFRINGEMENT. IN NO EVENT SHALL NETWORK
+ * COMPUTING DEVICES, INC., BE LIABLE FOR ANY DAMAGES WHATSOEVER, INCLUDING
+ * SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES, INCLUDING LOSS OF USE, DATA,
+ * OR PROFITS, EVEN IF ADVISED OF THE POSSIBILITY THEREOF, AND REGARDLESS OF
+ * WHETHER IN AN ACTION IN CONTRACT, TORT OR NEGLIGENCE, ARISING OUT OF OR IN
+ * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ *
+ */
+
+/* various bits of DIX-level mangling */
+
+#include <sys/types.h>
+#include <stdio.h>
+#define NEED_REPLIES
+#define NEED_EVENTS
+#include "X.h"
+#include "Xproto.h"
+#include "misc.h"
+#include "os.h"
+#include "dixstruct.h"
+#include "resource.h"
+#include "servermd.h"
+#include "propertyst.h"
+#include "windowstr.h"
+#define _XLBX_SERVER_
+#include "lbxstr.h"
+#include "lbxserve.h"
+#include "lbxtags.h"
+#include "Xfuncproto.h"
+#ifdef XCSECURITY
+#define _SECURITY_SERVER
+#include "extensions/security.h"
+#endif
+
+extern int (*ProcVector[256]) ();
+extern void (*ReplySwapVector[256]) ();
+extern void CopySwap16Write(), CopySwap32Write(), Swap32Write();
+
+void
+LbxStallPropRequest(client, pProp)
+ ClientPtr client;
+ PropertyPtr pProp;
+{
+ xReq *req = (xReq *) client->requestBuffer;
+ register char n;
+
+ LbxQueryTagData(client, pProp->owner_pid,
+ pProp->tag_id, LbxTagTypeProperty);
+
+ /*
+ * Before we reset the request, we must make sure
+ * it is in the client's byte order.
+ */
+
+ if (client->swapped) {
+ if (req->reqType == X_ChangeProperty) {
+ xChangePropertyReq *stuff = (xChangePropertyReq *) req;
+ swaps(&stuff->length, n);
+ swapl(&stuff->window, n);
+ swapl(&stuff->property, n);
+ swapl(&stuff->type, n);
+ swapl(&stuff->nUnits, n);
+ switch ( stuff->format ) {
+ case 16:
+ SwapRestS(stuff);
+ break;
+ case 32:
+ SwapRestL(stuff);
+ break;
+ }
+ } else if (req->reqType == X_GetProperty) {
+ xGetPropertyReq *stuff = (xGetPropertyReq *) req;
+ swaps(&stuff->length, n);
+ swapl(&stuff->window, n);
+ swapl(&stuff->property, n);
+ swapl(&stuff->type, n);
+ swapl(&stuff->longOffset, n);
+ swapl(&stuff->longLength, n);
+ } else if (req->data == X_LbxChangeProperty) {
+ xLbxChangePropertyReq *stuff = (xLbxChangePropertyReq *) req;
+ swaps(&stuff->length, n);
+ swapl(&stuff->window, n);
+ swapl(&stuff->property, n);
+ swapl(&stuff->type, n);
+ swapl(&stuff->nUnits, n);
+ } else if (req->data == X_LbxGetProperty) {
+ xLbxGetPropertyReq *stuff = (xLbxGetPropertyReq *) req;
+ swaps(&stuff->length, n);
+ swapl(&stuff->window, n);
+ swapl(&stuff->property, n);
+ swapl(&stuff->type, n);
+ swapl(&stuff->longOffset, n);
+ swapl(&stuff->longLength, n);
+ }
+ }
+ ResetCurrentRequest(client);
+ client->sequence--;
+ IgnoreClient(client);
+}
+
+int
+LbxChangeWindowProperty(client, pWin, property, type, format, mode, len,
+ have_data, value, sendevent, tag)
+ ClientPtr client;
+ WindowPtr pWin;
+ Atom property,
+ type;
+ int format,
+ mode;
+ unsigned long len;
+ Bool have_data;
+ pointer value;
+ Bool sendevent;
+ XID *tag;
+{
+ PropertyPtr pProp;
+ xEvent event;
+ int sizeInBytes;
+ int totalSize;
+ pointer data;
+
+ sizeInBytes = format >> 3;
+ totalSize = len * sizeInBytes;
+
+ /* first see if property already exists */
+
+ pProp = wUserProps(pWin);
+ while (pProp) {
+ if (pProp->propertyName == property)
+ break;
+ pProp = pProp->next;
+ }
+ if (!pProp) { /* just add to list */
+ if (!pWin->optional && !MakeWindowOptional(pWin))
+ return (BadAlloc);
+ pProp = (PropertyPtr) xalloc(sizeof(PropertyRec));
+ if (!pProp)
+ return (BadAlloc);
+ data = (pointer) xalloc(totalSize);
+ if (!data && len) {
+ xfree(pProp);
+ return (BadAlloc);
+ }
+ pProp->propertyName = property;
+ pProp->type = type;
+ pProp->format = format;
+ pProp->data = data;
+ if (have_data) {
+ if (len)
+ memmove((char *) data, (char *) value, totalSize);
+ pProp->tag_id = 0;
+ pProp->owner_pid = 0;
+ } else {
+ if (!TagSaveTag(LbxTagTypeProperty, totalSize,
+ (pointer)pProp, &pProp->tag_id)) {
+ xfree(pProp);
+ xfree(pProp->data);
+ return BadAlloc;
+ }
+ pProp->owner_pid = LbxProxyID(client);
+ TagMarkProxy(pProp->tag_id, pProp->owner_pid);
+ }
+ pProp->size = len;
+ pProp->next = pWin->optional->userProps;
+ pWin->optional->userProps = pProp;
+ } else {
+ /*
+ * 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);
+
+ /*
+ * if its a modify instead of replace, make sure we have the current
+ * value
+ */
+ if ((mode != PropModeReplace) && pProp->tag_id && pProp->owner_pid) {
+ LbxStallPropRequest(client, pProp);
+ return (client->noClientException);
+ }
+ /* make sure any old tag is flushed first */
+ if (pProp->tag_id)
+ TagDeleteTag(pProp->tag_id);
+ if (mode == PropModeReplace) {
+ if (totalSize != pProp->size * (pProp->format >> 3)) {
+ data = (pointer) xrealloc(pProp->data, totalSize);
+ if (!data && len)
+ return (BadAlloc);
+ pProp->data = data;
+ }
+ if (have_data) {
+ if (len)
+ memmove((char *) pProp->data, (char *) value, totalSize);
+ } else {
+ if (!TagSaveTag(LbxTagTypeProperty, totalSize,
+ (pointer)pProp, &pProp->tag_id)) {
+ xfree(pProp);
+ xfree(pProp->data);
+ return BadAlloc;
+ }
+ pProp->owner_pid = LbxProxyID(client);
+ TagMarkProxy(pProp->tag_id, pProp->owner_pid);
+ }
+ pProp->size = len;
+ pProp->type = type;
+ pProp->format = format;
+ } else if (len == 0) {
+ /* do nothing */
+ } else if (mode == PropModeAppend) {
+ data = (pointer) xrealloc(pProp->data,
+ sizeInBytes * (len + pProp->size));
+ if (!data)
+ return (BadAlloc);
+ pProp->data = data;
+ memmove(&((char *) data)[pProp->size * sizeInBytes],
+ (char *) value,
+ totalSize);
+ pProp->size += len;
+ } else if (mode == PropModePrepend) {
+ data = (pointer) xalloc(sizeInBytes * (len + pProp->size));
+ if (!data)
+ return (BadAlloc);
+ memmove(&((char *) data)[totalSize], (char *) pProp->data,
+ (int) (pProp->size * sizeInBytes));
+ memmove((char *) data, (char *) value, totalSize);
+ xfree(pProp->data);
+ pProp->data = data;
+ pProp->size += len;
+ }
+ }
+ if (sendevent) {
+ event.u.u.type = PropertyNotify;
+ event.u.property.window = pWin->drawable.id;
+ event.u.property.state = PropertyNewValue;
+ event.u.property.atom = pProp->propertyName;
+ event.u.property.time = currentTime.milliseconds;
+ DeliverEvents(pWin, &event, 1, (WindowPtr) NULL);
+ }
+ if (pProp->tag_id)
+ *tag = pProp->tag_id;
+ return (Success);
+}
+
+int
+LbxChangeProperty(client)
+ ClientPtr client;
+{
+ WindowPtr pWin;
+ char format,
+ mode;
+ unsigned long len;
+ int err;
+ int n;
+ XID newtag;
+ xLbxChangePropertyReply rep;
+ REQUEST(xLbxChangePropertyReq);
+
+ REQUEST_SIZE_MATCH(xLbxChangePropertyReq);
+ 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 > ((0xffffffff - sizeof(xChangePropertyReq)) >> 2))
+ return BadLength;
+
+ pWin = (WindowPtr) SecurityLookupWindow(stuff->window, client,
+ SecurityWriteAccess);
+ if (!pWin)
+ return (BadWindow);
+ if (!ValidAtom(stuff->property)) {
+ client->errorValue = stuff->property;
+ return (BadAtom);
+ }
+ if (!ValidAtom(stuff->type)) {
+ client->errorValue = stuff->type;
+ return (BadAtom);
+ }
+
+ rep.type = X_Reply;
+ rep.sequenceNumber = client->sequence;
+ rep.length = 0;
+ rep.pad = rep.pad0 = rep.pad1 = rep.pad2 = rep.pad3 = rep.pad4 = 0;
+ if (client->swapped) {
+ swaps(&rep.sequenceNumber, n);
+ }
+
+#ifdef XCSECURITY
+ switch (SecurityCheckPropertyAccess(client, pWin, stuff->property,
+ SecurityWriteAccess))
+ {
+ case SecurityErrorOperation:
+ client->errorValue = stuff->property;
+ return BadAtom;
+ case SecurityIgnoreOperation:
+ rep.tag = 0;
+ WriteToClient(client, sizeof(xLbxChangePropertyReply), (char *)&rep);
+ return client->noClientException;
+ }
+#endif
+
+ err = LbxChangeWindowProperty(client, pWin, stuff->property, stuff->type,
+ (int) format, (int) mode, len, FALSE, (pointer) &stuff[1],
+ TRUE, &newtag);
+ if (err)
+ return err;
+
+ rep.tag = newtag;
+
+ if (client->swapped) {
+ swapl(&rep.tag, n);
+ }
+ WriteToClient(client, sizeof(xLbxChangePropertyReply), (char *)&rep);
+
+ return client->noClientException;
+}
+
+static void
+LbxWriteGetpropReply(client, rep)
+ ClientPtr client;
+ xLbxGetPropertyReply *rep;
+{
+ int n;
+
+ if (client->swapped) {
+ swaps(&rep->sequenceNumber, n);
+ swapl(&rep->length, n);
+ swapl(&rep->propertyType, n);
+ swapl(&rep->bytesAfter, n);
+ swapl(&rep->nItems, n);
+ swapl(&rep->tag, n);
+ }
+ WriteToClient(client, sizeof(xLbxGetPropertyReply), (char *)rep);
+}
+
+int
+LbxGetProperty(client)
+ ClientPtr client;
+{
+ PropertyPtr pProp,
+ prevProp;
+ unsigned long n,
+ len,
+ ind;
+ WindowPtr pWin;
+ xLbxGetPropertyReply reply;
+ Bool send_data = FALSE;
+
+ REQUEST(xLbxGetPropertyReq);
+
+ REQUEST_SIZE_MATCH(xLbxGetPropertyReq);
+
+ reply.pad1 = 0;
+ reply.pad2 = 0;
+
+ if (stuff->delete)
+ UpdateCurrentTime();
+ pWin = (WindowPtr) SecurityLookupWindow(stuff->window, client,
+ SecurityReadAccess);
+ if (!pWin)
+ return (BadWindow);
+
+ 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);
+ }
+ pProp = wUserProps(pWin);
+ prevProp = (PropertyPtr) NULL;
+ while (pProp) {
+ if (pProp->propertyName == stuff->property)
+ break;
+ prevProp = pProp;
+ pProp = pProp->next;
+ }
+ reply.type = X_Reply;
+ reply.sequenceNumber = client->sequence;
+ if (!pProp) {
+ reply.nItems = 0;
+ reply.length = 0;
+ reply.bytesAfter = 0;
+ reply.propertyType = None;
+ reply.format = 0;
+ reply.tag = 0;
+ LbxWriteGetpropReply(client, &reply);
+ return client->noClientException;
+ }
+ /*
+ * 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;
+ reply.tag = 0;
+ LbxWriteGetpropReply(client, &reply);
+ return client->noClientException;
+ }
+ /*
+ * Return type, format, value to client
+ */
+ n = (pProp->format >> 3) * 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;
+ }
+
+ /* make sure we have the current value */
+ if (pProp->tag_id && pProp->owner_pid) {
+ LbxStallPropRequest(client, pProp);
+ return client->noClientException;
+ }
+
+ len = min(n - ind, stuff->longLength << 2);
+
+ reply.bytesAfter = n - (ind + len);
+ reply.format = pProp->format;
+ reply.propertyType = pProp->type;
+
+ if (!pProp->tag_id) {
+ if (n && (!stuff->delete || reply.bytesAfter)) {
+ TagSaveTag(LbxTagTypeProperty, n, (pointer)pProp, &pProp->tag_id);
+ pProp->owner_pid = 0;
+ }
+ send_data = TRUE;
+ } else
+ send_data = !TagProxyMarked(pProp->tag_id, LbxProxyID(client));
+ if (pProp->tag_id && send_data)
+ TagMarkProxy(pProp->tag_id, LbxProxyID(client));
+ reply.tag = pProp->tag_id;
+
+ if (!send_data)
+ len = 0;
+ else if (reply.tag) {
+ len = n;
+ ind = 0;
+ }
+ reply.nItems = len / (pProp->format >> 3);
+ reply.length = (len + 3) >> 2;
+
+ if (stuff->delete && (reply.bytesAfter == 0)) {
+ xEvent event;
+
+ event.u.u.type = PropertyNotify;
+ event.u.property.window = pWin->drawable.id;
+ event.u.property.state = PropertyDelete;
+ event.u.property.atom = pProp->propertyName;
+ event.u.property.time = currentTime.milliseconds;
+ DeliverEvents(pWin, &event, 1, (WindowPtr) NULL);
+ }
+ LbxWriteGetpropReply(client, &reply);
+ if (len) {
+ switch (reply.format) {
+ case 32:
+ client->pSwapReplyFunc = CopySwap32Write;
+ break;
+ case 16:
+ client->pSwapReplyFunc = CopySwap16Write;
+ break;
+ default:
+ client->pSwapReplyFunc = (void (*) ()) WriteToClient;
+ break;
+ }
+ WriteSwappedDataToClient(client, len,
+ (char *) pProp->data + ind);
+ }
+ if (stuff->delete && (reply.bytesAfter == 0)) {
+ if (pProp->tag_id)
+ TagDeleteTag(pProp->tag_id);
+ if (prevProp == (PropertyPtr) NULL) {
+ if (!(pWin->optional->userProps = pProp->next))
+ CheckWindowOptionalNeed(pWin);
+ } else
+ prevProp->next = pProp->next;
+ xfree(pProp->data);
+ xfree(pProp);
+ }
+ return client->noClientException;
+}