105b261ecSmrg/*********************************************************** 205b261ecSmrg 305b261ecSmrgCopyright 1987, 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 2505b261ecSmrgCopyright 1987 by Digital Equipment Corporation, Maynard, Massachusetts. 2605b261ecSmrg 2705b261ecSmrg All Rights Reserved 2805b261ecSmrg 2935c4bbdfSmrgPermission to use, copy, modify, and distribute this software and its 3035c4bbdfSmrgdocumentation for any purpose and without fee is hereby granted, 3105b261ecSmrgprovided that the above copyright notice appear in all copies and that 3235c4bbdfSmrgboth that copyright notice and this permission notice appear in 3305b261ecSmrgsupporting documentation, and that the name of Digital not be 3405b261ecSmrgused in advertising or publicity pertaining to distribution of the 3535c4bbdfSmrgsoftware without specific, written prior permission. 3605b261ecSmrg 3705b261ecSmrgDIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING 3805b261ecSmrgALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL 3905b261ecSmrgDIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR 4005b261ecSmrgANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, 4105b261ecSmrgWHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, 4205b261ecSmrgARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS 4305b261ecSmrgSOFTWARE. 4405b261ecSmrg 4505b261ecSmrg******************************************************************/ 4605b261ecSmrg 4705b261ecSmrg#ifdef HAVE_DIX_CONFIG_H 4805b261ecSmrg#include <dix-config.h> 4905b261ecSmrg#endif 5005b261ecSmrg 5105b261ecSmrg#include <X11/X.h> 5205b261ecSmrg#include <X11/Xproto.h> 5305b261ecSmrg#include "windowstr.h" 5405b261ecSmrg#include "propertyst.h" 5505b261ecSmrg#include "dixstruct.h" 5605b261ecSmrg#include "dispatch.h" 5705b261ecSmrg#include "swaprep.h" 5805b261ecSmrg#include "xace.h" 5905b261ecSmrg 6005b261ecSmrg/***************************************************************** 6105b261ecSmrg * Property Stuff 6205b261ecSmrg * 634642e01fSmrg * dixLookupProperty, dixChangeProperty, DeleteProperty 6405b261ecSmrg * 654642e01fSmrg * Properties belong to windows. The list of properties should not be 664642e01fSmrg * traversed directly. Instead, use the three functions listed above. 6705b261ecSmrg * 6805b261ecSmrg *****************************************************************/ 6905b261ecSmrg 7005b261ecSmrg#ifdef notdef 7105b261ecSmrgstatic void 7205b261ecSmrgPrintPropertys(WindowPtr pWin) 7305b261ecSmrg{ 7405b261ecSmrg PropertyPtr pProp; 7505b261ecSmrg int j; 7605b261ecSmrg 7705b261ecSmrg pProp = pWin->userProps; 7835c4bbdfSmrg while (pProp) { 794642e01fSmrg ErrorF("[dix] %x %x\n", pProp->propertyName, pProp->type); 804642e01fSmrg ErrorF("[dix] property format: %d\n", pProp->format); 814642e01fSmrg ErrorF("[dix] property data: \n"); 8235c4bbdfSmrg for (j = 0; j < (pProp->format / 8) * pProp->size; j++) 8335c4bbdfSmrg ErrorF("[dix] %c\n", pProp->data[j]); 8405b261ecSmrg pProp = pProp->next; 8505b261ecSmrg } 8605b261ecSmrg} 8705b261ecSmrg#endif 8805b261ecSmrg 896747b715Smrgint 904642e01fSmrgdixLookupProperty(PropertyPtr *result, WindowPtr pWin, Atom propertyName, 9135c4bbdfSmrg ClientPtr client, Mask access_mode) 924642e01fSmrg{ 934642e01fSmrg PropertyPtr pProp; 944642e01fSmrg int rc = BadMatch; 9535c4bbdfSmrg 964642e01fSmrg client->errorValue = propertyName; 974642e01fSmrg 984642e01fSmrg for (pProp = wUserProps(pWin); pProp; pProp = pProp->next) 9935c4bbdfSmrg if (pProp->propertyName == propertyName) 10035c4bbdfSmrg break; 1014642e01fSmrg 1024642e01fSmrg if (pProp) 10335c4bbdfSmrg rc = XaceHookPropertyAccess(client, pWin, &pProp, access_mode); 1044642e01fSmrg *result = pProp; 1054642e01fSmrg return rc; 1064642e01fSmrg} 1074642e01fSmrg 1081b5d61b8SmrgCallbackListPtr PropertyStateCallback; 1091b5d61b8Smrg 11005b261ecSmrgstatic void 1111b5d61b8SmrgdeliverPropertyNotifyEvent(WindowPtr pWin, int state, PropertyPtr pProp) 11205b261ecSmrg{ 1131b5d61b8Smrg xEvent event; 1141b5d61b8Smrg PropertyStateRec rec = { 1151b5d61b8Smrg .win = pWin, 1161b5d61b8Smrg .prop = pProp, 1171b5d61b8Smrg .state = state 1181b5d61b8Smrg }; 1191b5d61b8Smrg UpdateCurrentTimeIf(); 1201b5d61b8Smrg event = (xEvent) { 12135c4bbdfSmrg .u.property.window = pWin->drawable.id, 12235c4bbdfSmrg .u.property.state = state, 1231b5d61b8Smrg .u.property.atom = pProp->propertyName, 1241b5d61b8Smrg .u.property.time = currentTime.milliseconds, 12535c4bbdfSmrg }; 12605b261ecSmrg event.u.u.type = PropertyNotify; 1271b5d61b8Smrg 1281b5d61b8Smrg CallCallbacks(&PropertyStateCallback, &rec); 12935c4bbdfSmrg DeliverEvents(pWin, &event, 1, (WindowPtr) NULL); 13005b261ecSmrg} 13105b261ecSmrg 13205b261ecSmrgint 13305b261ecSmrgProcRotateProperties(ClientPtr client) 13405b261ecSmrg{ 13535c4bbdfSmrg int i, j, delta, rc; 13635c4bbdfSmrg 13705b261ecSmrg REQUEST(xRotatePropertiesReq); 13805b261ecSmrg WindowPtr pWin; 13935c4bbdfSmrg Atom *atoms; 14035c4bbdfSmrg PropertyPtr *props; /* array of pointer */ 1414642e01fSmrg PropertyPtr pProp, saved; 14205b261ecSmrg 14305b261ecSmrg REQUEST_FIXED_SIZE(xRotatePropertiesReq, stuff->nAtoms << 2); 14405b261ecSmrg UpdateCurrentTime(); 1454642e01fSmrg rc = dixLookupWindow(&pWin, stuff->window, client, DixSetPropAccess); 1464642e01fSmrg if (rc != Success || stuff->nAtoms <= 0) 14705b261ecSmrg return rc; 1484642e01fSmrg 14935c4bbdfSmrg atoms = (Atom *) &stuff[1]; 15035c4bbdfSmrg props = xallocarray(stuff->nAtoms, sizeof(PropertyPtr)); 15135c4bbdfSmrg saved = xallocarray(stuff->nAtoms, sizeof(PropertyRec)); 1524642e01fSmrg if (!props || !saved) { 15335c4bbdfSmrg rc = BadAlloc; 15435c4bbdfSmrg goto out; 1554642e01fSmrg } 1564642e01fSmrg 15735c4bbdfSmrg for (i = 0; i < stuff->nAtoms; i++) { 1584642e01fSmrg if (!ValidAtom(atoms[i])) { 15935c4bbdfSmrg rc = BadAtom; 16035c4bbdfSmrg client->errorValue = atoms[i]; 16135c4bbdfSmrg goto out; 16205b261ecSmrg } 16305b261ecSmrg for (j = i + 1; j < stuff->nAtoms; j++) 16435c4bbdfSmrg if (atoms[j] == atoms[i]) { 16535c4bbdfSmrg rc = BadMatch; 16635c4bbdfSmrg goto out; 16705b261ecSmrg } 1684642e01fSmrg 16935c4bbdfSmrg rc = dixLookupProperty(&pProp, pWin, atoms[i], client, 17035c4bbdfSmrg DixReadAccess | DixWriteAccess); 17135c4bbdfSmrg if (rc != Success) 17235c4bbdfSmrg goto out; 1734642e01fSmrg 17405b261ecSmrg props[i] = pProp; 17535c4bbdfSmrg saved[i] = *pProp; 17605b261ecSmrg } 17705b261ecSmrg delta = stuff->nPositions; 17805b261ecSmrg 17905b261ecSmrg /* If the rotation is a complete 360 degrees, then moving the properties 18035c4bbdfSmrg around and generating PropertyNotify events should be skipped. */ 18105b261ecSmrg 18235c4bbdfSmrg if (abs(delta) % stuff->nAtoms) { 18335c4bbdfSmrg while (delta < 0) /* faster if abs value is small */ 18405b261ecSmrg delta += stuff->nAtoms; 18535c4bbdfSmrg for (i = 0; i < stuff->nAtoms; i++) { 18635c4bbdfSmrg j = (i + delta) % stuff->nAtoms; 1871b5d61b8Smrg deliverPropertyNotifyEvent(pWin, PropertyNewValue, props[i]); 18835c4bbdfSmrg 18935c4bbdfSmrg /* Preserve name and devPrivates */ 19035c4bbdfSmrg props[j]->type = saved[i].type; 19135c4bbdfSmrg props[j]->format = saved[i].format; 19235c4bbdfSmrg props[j]->size = saved[i].size; 19335c4bbdfSmrg props[j]->data = saved[i].data; 19435c4bbdfSmrg } 19505b261ecSmrg } 19635c4bbdfSmrg out: 1976747b715Smrg free(saved); 1986747b715Smrg free(props); 1994642e01fSmrg return rc; 20005b261ecSmrg} 20105b261ecSmrg 20235c4bbdfSmrgint 20305b261ecSmrgProcChangeProperty(ClientPtr client) 20435c4bbdfSmrg{ 20505b261ecSmrg WindowPtr pWin; 20605b261ecSmrg char format, mode; 20705b261ecSmrg unsigned long len; 208c82838c1Smrg int sizeInBytes, err; 209c82838c1Smrg uint64_t totalSize; 21035c4bbdfSmrg 21105b261ecSmrg REQUEST(xChangePropertyReq); 21205b261ecSmrg 21305b261ecSmrg REQUEST_AT_LEAST_SIZE(xChangePropertyReq); 21405b261ecSmrg UpdateCurrentTime(); 21505b261ecSmrg format = stuff->format; 21605b261ecSmrg mode = stuff->mode; 21705b261ecSmrg if ((mode != PropModeReplace) && (mode != PropModeAppend) && 21835c4bbdfSmrg (mode != PropModePrepend)) { 21935c4bbdfSmrg client->errorValue = mode; 22035c4bbdfSmrg return BadValue; 22105b261ecSmrg } 22235c4bbdfSmrg if ((format != 8) && (format != 16) && (format != 32)) { 22335c4bbdfSmrg client->errorValue = format; 22405b261ecSmrg return BadValue; 22505b261ecSmrg } 22605b261ecSmrg len = stuff->nUnits; 2276747b715Smrg if (len > bytes_to_int32(0xffffffff - sizeof(xChangePropertyReq))) 22835c4bbdfSmrg return BadLength; 22935c4bbdfSmrg sizeInBytes = format >> 3; 23005b261ecSmrg totalSize = len * sizeInBytes; 23105b261ecSmrg REQUEST_FIXED_SIZE(xChangePropertyReq, totalSize); 23205b261ecSmrg 2334642e01fSmrg err = dixLookupWindow(&pWin, stuff->window, client, DixSetPropAccess); 23405b261ecSmrg if (err != Success) 23535c4bbdfSmrg return err; 23635c4bbdfSmrg if (!ValidAtom(stuff->property)) { 23735c4bbdfSmrg client->errorValue = stuff->property; 23835c4bbdfSmrg return BadAtom; 23905b261ecSmrg } 24035c4bbdfSmrg if (!ValidAtom(stuff->type)) { 24135c4bbdfSmrg client->errorValue = stuff->type; 24235c4bbdfSmrg return BadAtom; 24305b261ecSmrg } 24405b261ecSmrg 2454642e01fSmrg err = dixChangeWindowProperty(client, pWin, stuff->property, stuff->type, 24635c4bbdfSmrg (int) format, (int) mode, len, &stuff[1], 24735c4bbdfSmrg TRUE); 24805b261ecSmrg if (err != Success) 24935c4bbdfSmrg return err; 25005b261ecSmrg else 25135c4bbdfSmrg return Success; 25205b261ecSmrg} 25305b261ecSmrg 2546747b715Smrgint 2554642e01fSmrgdixChangeWindowProperty(ClientPtr pClient, WindowPtr pWin, Atom property, 25635c4bbdfSmrg Atom type, int format, int mode, unsigned long len, 257ed6184dfSmrg const void *value, Bool sendevent) 25805b261ecSmrg{ 25905b261ecSmrg PropertyPtr pProp; 2606747b715Smrg PropertyRec savedProp; 2614642e01fSmrg int sizeInBytes, totalSize, rc; 2626747b715Smrg unsigned char *data; 2634642e01fSmrg Mask access_mode; 26405b261ecSmrg 26535c4bbdfSmrg sizeInBytes = format >> 3; 26605b261ecSmrg totalSize = len * sizeInBytes; 2674642e01fSmrg access_mode = (mode == PropModeReplace) ? DixWriteAccess : DixBlendAccess; 26805b261ecSmrg 26905b261ecSmrg /* first see if property already exists */ 2704642e01fSmrg rc = dixLookupProperty(&pProp, pWin, property, pClient, access_mode); 27105b261ecSmrg 27235c4bbdfSmrg if (rc == BadMatch) { /* just add to list */ 27335c4bbdfSmrg if (!pWin->optional && !MakeWindowOptional(pWin)) 27435c4bbdfSmrg return BadAlloc; 27535c4bbdfSmrg pProp = dixAllocateObjectWithPrivates(PropertyRec, PRIVATE_PROPERTY); 27635c4bbdfSmrg if (!pProp) 27735c4bbdfSmrg return BadAlloc; 2786747b715Smrg data = malloc(totalSize); 27958cf2af7Smrg if (totalSize) { 28058cf2af7Smrg if (!data) { 28158cf2af7Smrg dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY); 28258cf2af7Smrg return BadAlloc; 28358cf2af7Smrg } 28458cf2af7Smrg memcpy(data, value, totalSize); 28535c4bbdfSmrg } 28605b261ecSmrg pProp->propertyName = property; 28705b261ecSmrg pProp->type = type; 28805b261ecSmrg pProp->format = format; 28905b261ecSmrg pProp->data = data; 29035c4bbdfSmrg pProp->size = len; 29135c4bbdfSmrg rc = XaceHookPropertyAccess(pClient, pWin, &pProp, 29235c4bbdfSmrg DixCreateAccess | DixWriteAccess); 29335c4bbdfSmrg if (rc != Success) { 29435c4bbdfSmrg free(data); 29535c4bbdfSmrg dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY); 29635c4bbdfSmrg pClient->errorValue = property; 29735c4bbdfSmrg return rc; 29835c4bbdfSmrg } 29905b261ecSmrg pProp->next = pWin->optional->userProps; 30005b261ecSmrg pWin->optional->userProps = pProp; 30105b261ecSmrg } 30235c4bbdfSmrg else if (rc == Success) { 30335c4bbdfSmrg /* To append or prepend to a property the request format and type 30435c4bbdfSmrg must match those of the already defined property. The 30535c4bbdfSmrg existing format and type are irrelevant when using the mode 30635c4bbdfSmrg "PropModeReplace" since they will be written over. */ 30705b261ecSmrg 30805b261ecSmrg if ((format != pProp->format) && (mode != PropModeReplace)) 30935c4bbdfSmrg return BadMatch; 31005b261ecSmrg if ((pProp->type != type) && (mode != PropModeReplace)) 3116747b715Smrg return BadMatch; 3126747b715Smrg 31335c4bbdfSmrg /* save the old values for later */ 31435c4bbdfSmrg savedProp = *pProp; 31535c4bbdfSmrg 31635c4bbdfSmrg if (mode == PropModeReplace) { 31735c4bbdfSmrg data = malloc(totalSize); 31858cf2af7Smrg if (totalSize) { 31958cf2af7Smrg if (!data) 32058cf2af7Smrg return BadAlloc; 32158cf2af7Smrg memcpy(data, value, totalSize); 32258cf2af7Smrg } 32335c4bbdfSmrg pProp->data = data; 32435c4bbdfSmrg pProp->size = len; 32535c4bbdfSmrg pProp->type = type; 32635c4bbdfSmrg pProp->format = format; 32735c4bbdfSmrg } 32835c4bbdfSmrg else if (len == 0) { 32935c4bbdfSmrg /* do nothing */ 33035c4bbdfSmrg } 33135c4bbdfSmrg else if (mode == PropModeAppend) { 33235c4bbdfSmrg data = xallocarray(pProp->size + len, sizeInBytes); 33335c4bbdfSmrg if (!data) 33435c4bbdfSmrg return BadAlloc; 33535c4bbdfSmrg memcpy(data, pProp->data, pProp->size * sizeInBytes); 33635c4bbdfSmrg memcpy(data + pProp->size * sizeInBytes, value, totalSize); 33705b261ecSmrg pProp->data = data; 33805b261ecSmrg pProp->size += len; 33935c4bbdfSmrg } 34035c4bbdfSmrg else if (mode == PropModePrepend) { 34135c4bbdfSmrg data = xallocarray(len + pProp->size, sizeInBytes); 34235c4bbdfSmrg if (!data) 34335c4bbdfSmrg return BadAlloc; 3446747b715Smrg memcpy(data + totalSize, pProp->data, pProp->size * sizeInBytes); 3456747b715Smrg memcpy(data, value, totalSize); 34605b261ecSmrg pProp->data = data; 34705b261ecSmrg pProp->size += len; 34835c4bbdfSmrg } 34935c4bbdfSmrg 35035c4bbdfSmrg /* Allow security modules to check the new content */ 35135c4bbdfSmrg access_mode |= DixPostAccess; 35235c4bbdfSmrg rc = XaceHookPropertyAccess(pClient, pWin, &pProp, access_mode); 35335c4bbdfSmrg if (rc == Success) { 35435c4bbdfSmrg if (savedProp.data != pProp->data) 35535c4bbdfSmrg free(savedProp.data); 35635c4bbdfSmrg } 35735c4bbdfSmrg else { 35835c4bbdfSmrg if (savedProp.data != pProp->data) 35935c4bbdfSmrg free(pProp->data); 36035c4bbdfSmrg *pProp = savedProp; 36135c4bbdfSmrg return rc; 36235c4bbdfSmrg } 36305b261ecSmrg } 3644642e01fSmrg else 36535c4bbdfSmrg return rc; 36605b261ecSmrg 36705b261ecSmrg if (sendevent) 3681b5d61b8Smrg deliverPropertyNotifyEvent(pWin, PropertyNewValue, pProp); 36905b261ecSmrg 3706747b715Smrg return Success; 37105b261ecSmrg} 37205b261ecSmrg 37305b261ecSmrgint 3744642e01fSmrgDeleteProperty(ClientPtr client, WindowPtr pWin, Atom propName) 37505b261ecSmrg{ 37605b261ecSmrg PropertyPtr pProp, prevProp; 3774642e01fSmrg int rc; 37805b261ecSmrg 3794642e01fSmrg rc = dixLookupProperty(&pProp, pWin, propName, client, DixDestroyAccess); 3804642e01fSmrg if (rc == BadMatch) 38135c4bbdfSmrg return Success; /* Succeed if property does not exist */ 3824642e01fSmrg 3834642e01fSmrg if (rc == Success) { 38435c4bbdfSmrg if (pWin->optional->userProps == pProp) { 38535c4bbdfSmrg /* Takes care of head */ 38605b261ecSmrg if (!(pWin->optional->userProps = pProp->next)) 38735c4bbdfSmrg CheckWindowOptionalNeed(pWin); 38835c4bbdfSmrg } 38935c4bbdfSmrg else { 39035c4bbdfSmrg /* Need to traverse to find the previous element */ 39135c4bbdfSmrg prevProp = pWin->optional->userProps; 39235c4bbdfSmrg while (prevProp->next != pProp) 39335c4bbdfSmrg prevProp = prevProp->next; 39435c4bbdfSmrg prevProp->next = pProp->next; 39535c4bbdfSmrg } 39635c4bbdfSmrg 3971b5d61b8Smrg deliverPropertyNotifyEvent(pWin, PropertyDelete, pProp); 39835c4bbdfSmrg free(pProp->data); 39935c4bbdfSmrg dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY); 40005b261ecSmrg } 4014642e01fSmrg return rc; 40205b261ecSmrg} 40305b261ecSmrg 40405b261ecSmrgvoid 40505b261ecSmrgDeleteAllWindowProperties(WindowPtr pWin) 40605b261ecSmrg{ 40705b261ecSmrg PropertyPtr pProp, pNextProp; 40805b261ecSmrg 40935c4bbdfSmrg pProp = wUserProps(pWin); 41035c4bbdfSmrg while (pProp) { 4111b5d61b8Smrg deliverPropertyNotifyEvent(pWin, PropertyDelete, pProp); 41235c4bbdfSmrg pNextProp = pProp->next; 4136747b715Smrg free(pProp->data); 41435c4bbdfSmrg dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY); 41535c4bbdfSmrg pProp = pNextProp; 41605b261ecSmrg } 4179ace9065Smrg 4189ace9065Smrg if (pWin->optional) 4199ace9065Smrg pWin->optional->userProps = NULL; 42005b261ecSmrg} 42105b261ecSmrg 42205b261ecSmrgstatic int 42335c4bbdfSmrgNullPropertyReply(ClientPtr client, ATOM propertyType, int format) 42405b261ecSmrg{ 42535c4bbdfSmrg xGetPropertyReply reply = { 42635c4bbdfSmrg .type = X_Reply, 42735c4bbdfSmrg .format = format, 42835c4bbdfSmrg .sequenceNumber = client->sequence, 42935c4bbdfSmrg .length = 0, 43035c4bbdfSmrg .propertyType = propertyType, 43135c4bbdfSmrg .bytesAfter = 0, 43235c4bbdfSmrg .nItems = 0 43335c4bbdfSmrg }; 43435c4bbdfSmrg WriteReplyToClient(client, sizeof(xGenericReply), &reply); 4356747b715Smrg return Success; 43605b261ecSmrg} 43705b261ecSmrg 43805b261ecSmrg/***************** 43905b261ecSmrg * GetProperty 44005b261ecSmrg * If type Any is specified, returns the property from the specified 44105b261ecSmrg * window regardless of its type. If a type is specified, returns the 44205b261ecSmrg * property only if its type equals the specified type. 44305b261ecSmrg * If delete is True and a property is returned, the property is also 44405b261ecSmrg * deleted from the window and a PropertyNotify event is generated on the 44505b261ecSmrg * window. 44605b261ecSmrg *****************/ 44705b261ecSmrg 44805b261ecSmrgint 44905b261ecSmrgProcGetProperty(ClientPtr client) 45005b261ecSmrg{ 45105b261ecSmrg PropertyPtr pProp, prevProp; 4524642e01fSmrg unsigned long n, len, ind; 4534642e01fSmrg int rc; 45405b261ecSmrg WindowPtr pWin; 45505b261ecSmrg xGetPropertyReply reply; 4564642e01fSmrg Mask win_mode = DixGetPropAccess, prop_mode = DixReadAccess; 45735c4bbdfSmrg 45805b261ecSmrg REQUEST(xGetPropertyReq); 45905b261ecSmrg 46005b261ecSmrg REQUEST_SIZE_MATCH(xGetPropertyReq); 4614642e01fSmrg if (stuff->delete) { 46235c4bbdfSmrg UpdateCurrentTime(); 46335c4bbdfSmrg win_mode |= DixSetPropAccess; 46435c4bbdfSmrg prop_mode |= DixDestroyAccess; 4654642e01fSmrg } 4664642e01fSmrg rc = dixLookupWindow(&pWin, stuff->window, client, win_mode); 46705b261ecSmrg if (rc != Success) 46835c4bbdfSmrg return rc; 46905b261ecSmrg 47035c4bbdfSmrg if (!ValidAtom(stuff->property)) { 47135c4bbdfSmrg client->errorValue = stuff->property; 47235c4bbdfSmrg return BadAtom; 47305b261ecSmrg } 47435c4bbdfSmrg if ((stuff->delete != xTrue) && (stuff->delete != xFalse)) { 47535c4bbdfSmrg client->errorValue = stuff->delete; 47635c4bbdfSmrg return BadValue; 47705b261ecSmrg } 47835c4bbdfSmrg if ((stuff->type != AnyPropertyType) && !ValidAtom(stuff->type)) { 47935c4bbdfSmrg client->errorValue = stuff->type; 48035c4bbdfSmrg return BadAtom; 48105b261ecSmrg } 48205b261ecSmrg 4834642e01fSmrg rc = dixLookupProperty(&pProp, pWin, stuff->property, client, prop_mode); 4844642e01fSmrg if (rc == BadMatch) 48535c4bbdfSmrg return NullPropertyReply(client, None, 0); 4864642e01fSmrg else if (rc != Success) 48735c4bbdfSmrg return rc; 48805b261ecSmrg 48905b261ecSmrg /* If the request type and actual type don't match. Return the 49035c4bbdfSmrg property information, but not the data. */ 49135c4bbdfSmrg 49235c4bbdfSmrg if (((stuff->type != pProp->type) && (stuff->type != AnyPropertyType)) 49335c4bbdfSmrg ) { 49435c4bbdfSmrg reply = (xGetPropertyReply) { 49535c4bbdfSmrg .type = X_Reply, 49635c4bbdfSmrg .sequenceNumber = client->sequence, 49735c4bbdfSmrg .bytesAfter = pProp->size, 49835c4bbdfSmrg .format = pProp->format, 49935c4bbdfSmrg .length = 0, 50035c4bbdfSmrg .nItems = 0, 50135c4bbdfSmrg .propertyType = pProp->type 50235c4bbdfSmrg }; 50335c4bbdfSmrg WriteReplyToClient(client, sizeof(xGenericReply), &reply); 50435c4bbdfSmrg return Success; 50505b261ecSmrg } 50605b261ecSmrg 50705b261ecSmrg/* 50805b261ecSmrg * Return type, format, value to client 50905b261ecSmrg */ 51035c4bbdfSmrg n = (pProp->format / 8) * pProp->size; /* size (bytes) of prop */ 51135c4bbdfSmrg ind = stuff->longOffset << 2; 51205b261ecSmrg 51335c4bbdfSmrg /* If longOffset is invalid such that it causes "len" to 51435c4bbdfSmrg be negative, it's a value error. */ 51505b261ecSmrg 51635c4bbdfSmrg if (n < ind) { 51735c4bbdfSmrg client->errorValue = stuff->longOffset; 51835c4bbdfSmrg return BadValue; 51905b261ecSmrg } 52005b261ecSmrg 52105b261ecSmrg len = min(n - ind, 4 * stuff->longLength); 52205b261ecSmrg 52335c4bbdfSmrg reply = (xGetPropertyReply) { 52435c4bbdfSmrg .type = X_Reply, 52535c4bbdfSmrg .sequenceNumber = client->sequence, 52635c4bbdfSmrg .bytesAfter = n - (ind + len), 52735c4bbdfSmrg .format = pProp->format, 52835c4bbdfSmrg .length = bytes_to_int32(len), 52935c4bbdfSmrg .nItems = len / (pProp->format / 8), 53035c4bbdfSmrg .propertyType = pProp->type 53135c4bbdfSmrg }; 53205b261ecSmrg 53305b261ecSmrg if (stuff->delete && (reply.bytesAfter == 0)) 5341b5d61b8Smrg deliverPropertyNotifyEvent(pWin, PropertyDelete, pProp); 53505b261ecSmrg 53605b261ecSmrg WriteReplyToClient(client, sizeof(xGenericReply), &reply); 53735c4bbdfSmrg if (len) { 53835c4bbdfSmrg switch (reply.format) { 53935c4bbdfSmrg case 32: 54035c4bbdfSmrg client->pSwapReplyFunc = (ReplySwapPtr) CopySwap32Write; 54135c4bbdfSmrg break; 54235c4bbdfSmrg case 16: 54335c4bbdfSmrg client->pSwapReplyFunc = (ReplySwapPtr) CopySwap16Write; 54435c4bbdfSmrg break; 54535c4bbdfSmrg default: 54635c4bbdfSmrg client->pSwapReplyFunc = (ReplySwapPtr) WriteToClient; 54735c4bbdfSmrg break; 54835c4bbdfSmrg } 54935c4bbdfSmrg WriteSwappedDataToClient(client, len, (char *) pProp->data + ind); 55005b261ecSmrg } 55105b261ecSmrg 5524642e01fSmrg if (stuff->delete && (reply.bytesAfter == 0)) { 55335c4bbdfSmrg /* Delete the Property */ 55435c4bbdfSmrg if (pWin->optional->userProps == pProp) { 55535c4bbdfSmrg /* Takes care of head */ 5564642e01fSmrg if (!(pWin->optional->userProps = pProp->next)) 55735c4bbdfSmrg CheckWindowOptionalNeed(pWin); 55835c4bbdfSmrg } 55935c4bbdfSmrg else { 56035c4bbdfSmrg /* Need to traverse to find the previous element */ 56135c4bbdfSmrg prevProp = pWin->optional->userProps; 56235c4bbdfSmrg while (prevProp->next != pProp) 56335c4bbdfSmrg prevProp = prevProp->next; 56435c4bbdfSmrg prevProp->next = pProp->next; 56535c4bbdfSmrg } 56635c4bbdfSmrg 56735c4bbdfSmrg free(pProp->data); 56835c4bbdfSmrg dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY); 56905b261ecSmrg } 5706747b715Smrg return Success; 57105b261ecSmrg} 57205b261ecSmrg 57305b261ecSmrgint 57405b261ecSmrgProcListProperties(ClientPtr client) 57505b261ecSmrg{ 57605b261ecSmrg Atom *pAtoms = NULL, *temppAtoms; 57705b261ecSmrg xListPropertiesReply xlpr; 57835c4bbdfSmrg int rc, numProps = 0; 57905b261ecSmrg WindowPtr pWin; 5804642e01fSmrg PropertyPtr pProp, realProp; 58135c4bbdfSmrg 58205b261ecSmrg REQUEST(xResourceReq); 58305b261ecSmrg 58405b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 5854642e01fSmrg rc = dixLookupWindow(&pWin, stuff->id, client, DixListPropAccess); 58605b261ecSmrg if (rc != Success) 58705b261ecSmrg return rc; 58805b261ecSmrg 5894642e01fSmrg for (pProp = wUserProps(pWin); pProp; pProp = pProp->next) 59035c4bbdfSmrg numProps++; 5914642e01fSmrg 59258cf2af7Smrg if (numProps) { 59358cf2af7Smrg pAtoms = xallocarray(numProps, sizeof(Atom)); 59458cf2af7Smrg if (!pAtoms) 59558cf2af7Smrg return BadAlloc; 59658cf2af7Smrg 59758cf2af7Smrg numProps = 0; 59858cf2af7Smrg temppAtoms = pAtoms; 59958cf2af7Smrg for (pProp = wUserProps(pWin); pProp; pProp = pProp->next) { 60058cf2af7Smrg realProp = pProp; 60158cf2af7Smrg rc = XaceHookPropertyAccess(client, pWin, &realProp, DixGetAttrAccess); 60258cf2af7Smrg if (rc == Success && realProp == pProp) { 60358cf2af7Smrg *temppAtoms++ = pProp->propertyName; 60458cf2af7Smrg numProps++; 60558cf2af7Smrg } 60635c4bbdfSmrg } 60705b261ecSmrg } 60805b261ecSmrg 60935c4bbdfSmrg xlpr = (xListPropertiesReply) { 61035c4bbdfSmrg .type = X_Reply, 61135c4bbdfSmrg .sequenceNumber = client->sequence, 61235c4bbdfSmrg .length = bytes_to_int32(numProps * sizeof(Atom)), 61335c4bbdfSmrg .nProperties = numProps 61435c4bbdfSmrg }; 61505b261ecSmrg WriteReplyToClient(client, sizeof(xGenericReply), &xlpr); 61635c4bbdfSmrg if (numProps) { 61735c4bbdfSmrg client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; 61805b261ecSmrg WriteSwappedDataToClient(client, numProps * sizeof(Atom), pAtoms); 61958cf2af7Smrg free(pAtoms); 62005b261ecSmrg } 6216747b715Smrg return Success; 62205b261ecSmrg} 62305b261ecSmrg 62435c4bbdfSmrgint 62505b261ecSmrgProcDeleteProperty(ClientPtr client) 62605b261ecSmrg{ 62705b261ecSmrg WindowPtr pWin; 62835c4bbdfSmrg 62905b261ecSmrg REQUEST(xDeletePropertyReq); 63005b261ecSmrg int result; 63135c4bbdfSmrg 63205b261ecSmrg REQUEST_SIZE_MATCH(xDeletePropertyReq); 63305b261ecSmrg UpdateCurrentTime(); 6344642e01fSmrg result = dixLookupWindow(&pWin, stuff->window, client, DixSetPropAccess); 63505b261ecSmrg if (result != Success) 63605b261ecSmrg return result; 63735c4bbdfSmrg if (!ValidAtom(stuff->property)) { 63835c4bbdfSmrg client->errorValue = stuff->property; 63935c4bbdfSmrg return BadAtom; 64005b261ecSmrg } 64105b261ecSmrg 6426747b715Smrg return DeleteProperty(client, pWin, stuff->property); 64305b261ecSmrg} 644