#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 "colormapst.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
#include "swaprep.h"
void
LbxStallPropRequest(ClientPtr client,
PropertyPtr pProp)
{
xReq *req = (xReq *) client->requestBuffer;
register char n;
LbxQueryTagData(client, pProp->owner_pid,
pProp->tag_id, LbxTagTypeProperty);
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(ClientPtr client,
WindowPtr pWin,
Atom property,
Atom type,
int format,
int 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;
pProp = wUserProps(pWin);
while (pProp) {
if (pProp->propertyName == property)
break;
pProp = pProp->next;
}
if (!pProp) {
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 {
if ((format != pProp->format) && (mode != PropModeReplace))
return (BadMatch);
if ((pProp->type != type) && (mode != PropModeReplace))
return (BadMatch);
if ((mode != PropModeReplace) && pProp->tag_id && pProp->owner_pid) {
LbxStallPropRequest(client, pProp);
return (client->noClientException);
}
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) {
} 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(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(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(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 ((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;
}
n = (pProp->format >> 3) * pProp->size;
ind = stuff->longOffset << 2;
if (n < ind) {
client->errorValue = stuff->longOffset;
return BadValue;
}
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 = (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)) {
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;
}