property.c revision 1b5d61b8
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; 20805b261ecSmrg int sizeInBytes, totalSize, err; 20935c4bbdfSmrg 21005b261ecSmrg REQUEST(xChangePropertyReq); 21105b261ecSmrg 21205b261ecSmrg REQUEST_AT_LEAST_SIZE(xChangePropertyReq); 21305b261ecSmrg UpdateCurrentTime(); 21405b261ecSmrg format = stuff->format; 21505b261ecSmrg mode = stuff->mode; 21605b261ecSmrg if ((mode != PropModeReplace) && (mode != PropModeAppend) && 21735c4bbdfSmrg (mode != PropModePrepend)) { 21835c4bbdfSmrg client->errorValue = mode; 21935c4bbdfSmrg return BadValue; 22005b261ecSmrg } 22135c4bbdfSmrg if ((format != 8) && (format != 16) && (format != 32)) { 22235c4bbdfSmrg client->errorValue = format; 22305b261ecSmrg return BadValue; 22405b261ecSmrg } 22505b261ecSmrg len = stuff->nUnits; 2266747b715Smrg if (len > bytes_to_int32(0xffffffff - sizeof(xChangePropertyReq))) 22735c4bbdfSmrg return BadLength; 22835c4bbdfSmrg sizeInBytes = format >> 3; 22905b261ecSmrg totalSize = len * sizeInBytes; 23005b261ecSmrg REQUEST_FIXED_SIZE(xChangePropertyReq, totalSize); 23105b261ecSmrg 2324642e01fSmrg err = dixLookupWindow(&pWin, stuff->window, client, DixSetPropAccess); 23305b261ecSmrg if (err != Success) 23435c4bbdfSmrg return err; 23535c4bbdfSmrg if (!ValidAtom(stuff->property)) { 23635c4bbdfSmrg client->errorValue = stuff->property; 23735c4bbdfSmrg return BadAtom; 23805b261ecSmrg } 23935c4bbdfSmrg if (!ValidAtom(stuff->type)) { 24035c4bbdfSmrg client->errorValue = stuff->type; 24135c4bbdfSmrg return BadAtom; 24205b261ecSmrg } 24305b261ecSmrg 2444642e01fSmrg err = dixChangeWindowProperty(client, pWin, stuff->property, stuff->type, 24535c4bbdfSmrg (int) format, (int) mode, len, &stuff[1], 24635c4bbdfSmrg TRUE); 24705b261ecSmrg if (err != Success) 24835c4bbdfSmrg return err; 24905b261ecSmrg else 25035c4bbdfSmrg return Success; 25105b261ecSmrg} 25205b261ecSmrg 2536747b715Smrgint 2544642e01fSmrgdixChangeWindowProperty(ClientPtr pClient, WindowPtr pWin, Atom property, 25535c4bbdfSmrg Atom type, int format, int mode, unsigned long len, 25635c4bbdfSmrg void *value, Bool sendevent) 25705b261ecSmrg{ 25805b261ecSmrg PropertyPtr pProp; 2596747b715Smrg PropertyRec savedProp; 2604642e01fSmrg int sizeInBytes, totalSize, rc; 2616747b715Smrg unsigned char *data; 2624642e01fSmrg Mask access_mode; 26305b261ecSmrg 26435c4bbdfSmrg sizeInBytes = format >> 3; 26505b261ecSmrg totalSize = len * sizeInBytes; 2664642e01fSmrg access_mode = (mode == PropModeReplace) ? DixWriteAccess : DixBlendAccess; 26705b261ecSmrg 26805b261ecSmrg /* first see if property already exists */ 2694642e01fSmrg rc = dixLookupProperty(&pProp, pWin, property, pClient, access_mode); 27005b261ecSmrg 27135c4bbdfSmrg if (rc == BadMatch) { /* just add to list */ 27235c4bbdfSmrg if (!pWin->optional && !MakeWindowOptional(pWin)) 27335c4bbdfSmrg return BadAlloc; 27435c4bbdfSmrg pProp = dixAllocateObjectWithPrivates(PropertyRec, PRIVATE_PROPERTY); 27535c4bbdfSmrg if (!pProp) 27635c4bbdfSmrg return BadAlloc; 2776747b715Smrg data = malloc(totalSize); 27835c4bbdfSmrg if (!data && len) { 27935c4bbdfSmrg dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY); 28035c4bbdfSmrg return BadAlloc; 28135c4bbdfSmrg } 2826747b715Smrg memcpy(data, value, totalSize); 28305b261ecSmrg pProp->propertyName = property; 28405b261ecSmrg pProp->type = type; 28505b261ecSmrg pProp->format = format; 28605b261ecSmrg pProp->data = data; 28735c4bbdfSmrg pProp->size = len; 28835c4bbdfSmrg rc = XaceHookPropertyAccess(pClient, pWin, &pProp, 28935c4bbdfSmrg DixCreateAccess | DixWriteAccess); 29035c4bbdfSmrg if (rc != Success) { 29135c4bbdfSmrg free(data); 29235c4bbdfSmrg dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY); 29335c4bbdfSmrg pClient->errorValue = property; 29435c4bbdfSmrg return rc; 29535c4bbdfSmrg } 29605b261ecSmrg pProp->next = pWin->optional->userProps; 29705b261ecSmrg pWin->optional->userProps = pProp; 29805b261ecSmrg } 29935c4bbdfSmrg else if (rc == Success) { 30035c4bbdfSmrg /* To append or prepend to a property the request format and type 30135c4bbdfSmrg must match those of the already defined property. The 30235c4bbdfSmrg existing format and type are irrelevant when using the mode 30335c4bbdfSmrg "PropModeReplace" since they will be written over. */ 30405b261ecSmrg 30505b261ecSmrg if ((format != pProp->format) && (mode != PropModeReplace)) 30635c4bbdfSmrg return BadMatch; 30705b261ecSmrg if ((pProp->type != type) && (mode != PropModeReplace)) 3086747b715Smrg return BadMatch; 3096747b715Smrg 31035c4bbdfSmrg /* save the old values for later */ 31135c4bbdfSmrg savedProp = *pProp; 31235c4bbdfSmrg 31335c4bbdfSmrg if (mode == PropModeReplace) { 31435c4bbdfSmrg data = malloc(totalSize); 31535c4bbdfSmrg if (!data && len) 31635c4bbdfSmrg return BadAlloc; 31735c4bbdfSmrg memcpy(data, value, totalSize); 31835c4bbdfSmrg pProp->data = data; 31935c4bbdfSmrg pProp->size = len; 32035c4bbdfSmrg pProp->type = type; 32135c4bbdfSmrg pProp->format = format; 32235c4bbdfSmrg } 32335c4bbdfSmrg else if (len == 0) { 32435c4bbdfSmrg /* do nothing */ 32535c4bbdfSmrg } 32635c4bbdfSmrg else if (mode == PropModeAppend) { 32735c4bbdfSmrg data = xallocarray(pProp->size + len, sizeInBytes); 32835c4bbdfSmrg if (!data) 32935c4bbdfSmrg return BadAlloc; 33035c4bbdfSmrg memcpy(data, pProp->data, pProp->size * sizeInBytes); 33135c4bbdfSmrg memcpy(data + pProp->size * sizeInBytes, value, totalSize); 33205b261ecSmrg pProp->data = data; 33305b261ecSmrg pProp->size += len; 33435c4bbdfSmrg } 33535c4bbdfSmrg else if (mode == PropModePrepend) { 33635c4bbdfSmrg data = xallocarray(len + pProp->size, sizeInBytes); 33735c4bbdfSmrg if (!data) 33835c4bbdfSmrg return BadAlloc; 3396747b715Smrg memcpy(data + totalSize, pProp->data, pProp->size * sizeInBytes); 3406747b715Smrg memcpy(data, value, totalSize); 34105b261ecSmrg pProp->data = data; 34205b261ecSmrg pProp->size += len; 34335c4bbdfSmrg } 34435c4bbdfSmrg 34535c4bbdfSmrg /* Allow security modules to check the new content */ 34635c4bbdfSmrg access_mode |= DixPostAccess; 34735c4bbdfSmrg rc = XaceHookPropertyAccess(pClient, pWin, &pProp, access_mode); 34835c4bbdfSmrg if (rc == Success) { 34935c4bbdfSmrg if (savedProp.data != pProp->data) 35035c4bbdfSmrg free(savedProp.data); 35135c4bbdfSmrg } 35235c4bbdfSmrg else { 35335c4bbdfSmrg if (savedProp.data != pProp->data) 35435c4bbdfSmrg free(pProp->data); 35535c4bbdfSmrg *pProp = savedProp; 35635c4bbdfSmrg return rc; 35735c4bbdfSmrg } 35805b261ecSmrg } 3594642e01fSmrg else 36035c4bbdfSmrg return rc; 36105b261ecSmrg 36205b261ecSmrg if (sendevent) 3631b5d61b8Smrg deliverPropertyNotifyEvent(pWin, PropertyNewValue, pProp); 36405b261ecSmrg 3656747b715Smrg return Success; 36605b261ecSmrg} 36705b261ecSmrg 36805b261ecSmrgint 3694642e01fSmrgDeleteProperty(ClientPtr client, WindowPtr pWin, Atom propName) 37005b261ecSmrg{ 37105b261ecSmrg PropertyPtr pProp, prevProp; 3724642e01fSmrg int rc; 37305b261ecSmrg 3744642e01fSmrg rc = dixLookupProperty(&pProp, pWin, propName, client, DixDestroyAccess); 3754642e01fSmrg if (rc == BadMatch) 37635c4bbdfSmrg return Success; /* Succeed if property does not exist */ 3774642e01fSmrg 3784642e01fSmrg if (rc == Success) { 37935c4bbdfSmrg if (pWin->optional->userProps == pProp) { 38035c4bbdfSmrg /* Takes care of head */ 38105b261ecSmrg if (!(pWin->optional->userProps = pProp->next)) 38235c4bbdfSmrg CheckWindowOptionalNeed(pWin); 38335c4bbdfSmrg } 38435c4bbdfSmrg else { 38535c4bbdfSmrg /* Need to traverse to find the previous element */ 38635c4bbdfSmrg prevProp = pWin->optional->userProps; 38735c4bbdfSmrg while (prevProp->next != pProp) 38835c4bbdfSmrg prevProp = prevProp->next; 38935c4bbdfSmrg prevProp->next = pProp->next; 39035c4bbdfSmrg } 39135c4bbdfSmrg 3921b5d61b8Smrg deliverPropertyNotifyEvent(pWin, PropertyDelete, pProp); 39335c4bbdfSmrg free(pProp->data); 39435c4bbdfSmrg dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY); 39505b261ecSmrg } 3964642e01fSmrg return rc; 39705b261ecSmrg} 39805b261ecSmrg 39905b261ecSmrgvoid 40005b261ecSmrgDeleteAllWindowProperties(WindowPtr pWin) 40105b261ecSmrg{ 40205b261ecSmrg PropertyPtr pProp, pNextProp; 40305b261ecSmrg 40435c4bbdfSmrg pProp = wUserProps(pWin); 40535c4bbdfSmrg while (pProp) { 4061b5d61b8Smrg deliverPropertyNotifyEvent(pWin, PropertyDelete, pProp); 40735c4bbdfSmrg pNextProp = pProp->next; 4086747b715Smrg free(pProp->data); 40935c4bbdfSmrg dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY); 41035c4bbdfSmrg pProp = pNextProp; 41105b261ecSmrg } 4129ace9065Smrg 4139ace9065Smrg if (pWin->optional) 4149ace9065Smrg pWin->optional->userProps = NULL; 41505b261ecSmrg} 41605b261ecSmrg 41705b261ecSmrgstatic int 41835c4bbdfSmrgNullPropertyReply(ClientPtr client, ATOM propertyType, int format) 41905b261ecSmrg{ 42035c4bbdfSmrg xGetPropertyReply reply = { 42135c4bbdfSmrg .type = X_Reply, 42235c4bbdfSmrg .format = format, 42335c4bbdfSmrg .sequenceNumber = client->sequence, 42435c4bbdfSmrg .length = 0, 42535c4bbdfSmrg .propertyType = propertyType, 42635c4bbdfSmrg .bytesAfter = 0, 42735c4bbdfSmrg .nItems = 0 42835c4bbdfSmrg }; 42935c4bbdfSmrg WriteReplyToClient(client, sizeof(xGenericReply), &reply); 4306747b715Smrg return Success; 43105b261ecSmrg} 43205b261ecSmrg 43305b261ecSmrg/***************** 43405b261ecSmrg * GetProperty 43505b261ecSmrg * If type Any is specified, returns the property from the specified 43605b261ecSmrg * window regardless of its type. If a type is specified, returns the 43705b261ecSmrg * property only if its type equals the specified type. 43805b261ecSmrg * If delete is True and a property is returned, the property is also 43905b261ecSmrg * deleted from the window and a PropertyNotify event is generated on the 44005b261ecSmrg * window. 44105b261ecSmrg *****************/ 44205b261ecSmrg 44305b261ecSmrgint 44405b261ecSmrgProcGetProperty(ClientPtr client) 44505b261ecSmrg{ 44605b261ecSmrg PropertyPtr pProp, prevProp; 4474642e01fSmrg unsigned long n, len, ind; 4484642e01fSmrg int rc; 44905b261ecSmrg WindowPtr pWin; 45005b261ecSmrg xGetPropertyReply reply; 4514642e01fSmrg Mask win_mode = DixGetPropAccess, prop_mode = DixReadAccess; 45235c4bbdfSmrg 45305b261ecSmrg REQUEST(xGetPropertyReq); 45405b261ecSmrg 45505b261ecSmrg REQUEST_SIZE_MATCH(xGetPropertyReq); 4564642e01fSmrg if (stuff->delete) { 45735c4bbdfSmrg UpdateCurrentTime(); 45835c4bbdfSmrg win_mode |= DixSetPropAccess; 45935c4bbdfSmrg prop_mode |= DixDestroyAccess; 4604642e01fSmrg } 4614642e01fSmrg rc = dixLookupWindow(&pWin, stuff->window, client, win_mode); 46205b261ecSmrg if (rc != Success) 46335c4bbdfSmrg return rc; 46405b261ecSmrg 46535c4bbdfSmrg if (!ValidAtom(stuff->property)) { 46635c4bbdfSmrg client->errorValue = stuff->property; 46735c4bbdfSmrg return BadAtom; 46805b261ecSmrg } 46935c4bbdfSmrg if ((stuff->delete != xTrue) && (stuff->delete != xFalse)) { 47035c4bbdfSmrg client->errorValue = stuff->delete; 47135c4bbdfSmrg return BadValue; 47205b261ecSmrg } 47335c4bbdfSmrg if ((stuff->type != AnyPropertyType) && !ValidAtom(stuff->type)) { 47435c4bbdfSmrg client->errorValue = stuff->type; 47535c4bbdfSmrg return BadAtom; 47605b261ecSmrg } 47705b261ecSmrg 4784642e01fSmrg rc = dixLookupProperty(&pProp, pWin, stuff->property, client, prop_mode); 4794642e01fSmrg if (rc == BadMatch) 48035c4bbdfSmrg return NullPropertyReply(client, None, 0); 4814642e01fSmrg else if (rc != Success) 48235c4bbdfSmrg return rc; 48305b261ecSmrg 48405b261ecSmrg /* If the request type and actual type don't match. Return the 48535c4bbdfSmrg property information, but not the data. */ 48635c4bbdfSmrg 48735c4bbdfSmrg if (((stuff->type != pProp->type) && (stuff->type != AnyPropertyType)) 48835c4bbdfSmrg ) { 48935c4bbdfSmrg reply = (xGetPropertyReply) { 49035c4bbdfSmrg .type = X_Reply, 49135c4bbdfSmrg .sequenceNumber = client->sequence, 49235c4bbdfSmrg .bytesAfter = pProp->size, 49335c4bbdfSmrg .format = pProp->format, 49435c4bbdfSmrg .length = 0, 49535c4bbdfSmrg .nItems = 0, 49635c4bbdfSmrg .propertyType = pProp->type 49735c4bbdfSmrg }; 49835c4bbdfSmrg WriteReplyToClient(client, sizeof(xGenericReply), &reply); 49935c4bbdfSmrg return Success; 50005b261ecSmrg } 50105b261ecSmrg 50205b261ecSmrg/* 50305b261ecSmrg * Return type, format, value to client 50405b261ecSmrg */ 50535c4bbdfSmrg n = (pProp->format / 8) * pProp->size; /* size (bytes) of prop */ 50635c4bbdfSmrg ind = stuff->longOffset << 2; 50705b261ecSmrg 50835c4bbdfSmrg /* If longOffset is invalid such that it causes "len" to 50935c4bbdfSmrg be negative, it's a value error. */ 51005b261ecSmrg 51135c4bbdfSmrg if (n < ind) { 51235c4bbdfSmrg client->errorValue = stuff->longOffset; 51335c4bbdfSmrg return BadValue; 51405b261ecSmrg } 51505b261ecSmrg 51605b261ecSmrg len = min(n - ind, 4 * stuff->longLength); 51705b261ecSmrg 51835c4bbdfSmrg reply = (xGetPropertyReply) { 51935c4bbdfSmrg .type = X_Reply, 52035c4bbdfSmrg .sequenceNumber = client->sequence, 52135c4bbdfSmrg .bytesAfter = n - (ind + len), 52235c4bbdfSmrg .format = pProp->format, 52335c4bbdfSmrg .length = bytes_to_int32(len), 52435c4bbdfSmrg .nItems = len / (pProp->format / 8), 52535c4bbdfSmrg .propertyType = pProp->type 52635c4bbdfSmrg }; 52705b261ecSmrg 52805b261ecSmrg if (stuff->delete && (reply.bytesAfter == 0)) 5291b5d61b8Smrg deliverPropertyNotifyEvent(pWin, PropertyDelete, pProp); 53005b261ecSmrg 53105b261ecSmrg WriteReplyToClient(client, sizeof(xGenericReply), &reply); 53235c4bbdfSmrg if (len) { 53335c4bbdfSmrg switch (reply.format) { 53435c4bbdfSmrg case 32: 53535c4bbdfSmrg client->pSwapReplyFunc = (ReplySwapPtr) CopySwap32Write; 53635c4bbdfSmrg break; 53735c4bbdfSmrg case 16: 53835c4bbdfSmrg client->pSwapReplyFunc = (ReplySwapPtr) CopySwap16Write; 53935c4bbdfSmrg break; 54035c4bbdfSmrg default: 54135c4bbdfSmrg client->pSwapReplyFunc = (ReplySwapPtr) WriteToClient; 54235c4bbdfSmrg break; 54335c4bbdfSmrg } 54435c4bbdfSmrg WriteSwappedDataToClient(client, len, (char *) pProp->data + ind); 54505b261ecSmrg } 54605b261ecSmrg 5474642e01fSmrg if (stuff->delete && (reply.bytesAfter == 0)) { 54835c4bbdfSmrg /* Delete the Property */ 54935c4bbdfSmrg if (pWin->optional->userProps == pProp) { 55035c4bbdfSmrg /* Takes care of head */ 5514642e01fSmrg if (!(pWin->optional->userProps = pProp->next)) 55235c4bbdfSmrg CheckWindowOptionalNeed(pWin); 55335c4bbdfSmrg } 55435c4bbdfSmrg else { 55535c4bbdfSmrg /* Need to traverse to find the previous element */ 55635c4bbdfSmrg prevProp = pWin->optional->userProps; 55735c4bbdfSmrg while (prevProp->next != pProp) 55835c4bbdfSmrg prevProp = prevProp->next; 55935c4bbdfSmrg prevProp->next = pProp->next; 56035c4bbdfSmrg } 56135c4bbdfSmrg 56235c4bbdfSmrg free(pProp->data); 56335c4bbdfSmrg dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY); 56405b261ecSmrg } 5656747b715Smrg return Success; 56605b261ecSmrg} 56705b261ecSmrg 56805b261ecSmrgint 56905b261ecSmrgProcListProperties(ClientPtr client) 57005b261ecSmrg{ 57105b261ecSmrg Atom *pAtoms = NULL, *temppAtoms; 57205b261ecSmrg xListPropertiesReply xlpr; 57335c4bbdfSmrg int rc, numProps = 0; 57405b261ecSmrg WindowPtr pWin; 5754642e01fSmrg PropertyPtr pProp, realProp; 57635c4bbdfSmrg 57705b261ecSmrg REQUEST(xResourceReq); 57805b261ecSmrg 57905b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 5804642e01fSmrg rc = dixLookupWindow(&pWin, stuff->id, client, DixListPropAccess); 58105b261ecSmrg if (rc != Success) 58205b261ecSmrg return rc; 58305b261ecSmrg 5844642e01fSmrg for (pProp = wUserProps(pWin); pProp; pProp = pProp->next) 58535c4bbdfSmrg numProps++; 5864642e01fSmrg 58735c4bbdfSmrg if (numProps && !(pAtoms = xallocarray(numProps, sizeof(Atom)))) 58835c4bbdfSmrg return BadAlloc; 5894642e01fSmrg 5904642e01fSmrg numProps = 0; 5914642e01fSmrg temppAtoms = pAtoms; 5924642e01fSmrg for (pProp = wUserProps(pWin); pProp; pProp = pProp->next) { 59335c4bbdfSmrg realProp = pProp; 59435c4bbdfSmrg rc = XaceHookPropertyAccess(client, pWin, &realProp, DixGetAttrAccess); 59535c4bbdfSmrg if (rc == Success && realProp == pProp) { 59635c4bbdfSmrg *temppAtoms++ = pProp->propertyName; 59735c4bbdfSmrg numProps++; 59835c4bbdfSmrg } 59905b261ecSmrg } 60005b261ecSmrg 60135c4bbdfSmrg xlpr = (xListPropertiesReply) { 60235c4bbdfSmrg .type = X_Reply, 60335c4bbdfSmrg .sequenceNumber = client->sequence, 60435c4bbdfSmrg .length = bytes_to_int32(numProps * sizeof(Atom)), 60535c4bbdfSmrg .nProperties = numProps 60635c4bbdfSmrg }; 60705b261ecSmrg WriteReplyToClient(client, sizeof(xGenericReply), &xlpr); 60835c4bbdfSmrg if (numProps) { 60935c4bbdfSmrg client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; 61005b261ecSmrg WriteSwappedDataToClient(client, numProps * sizeof(Atom), pAtoms); 61105b261ecSmrg } 6126747b715Smrg free(pAtoms); 6136747b715Smrg return Success; 61405b261ecSmrg} 61505b261ecSmrg 61635c4bbdfSmrgint 61705b261ecSmrgProcDeleteProperty(ClientPtr client) 61805b261ecSmrg{ 61905b261ecSmrg WindowPtr pWin; 62035c4bbdfSmrg 62105b261ecSmrg REQUEST(xDeletePropertyReq); 62205b261ecSmrg int result; 62335c4bbdfSmrg 62405b261ecSmrg REQUEST_SIZE_MATCH(xDeletePropertyReq); 62505b261ecSmrg UpdateCurrentTime(); 6264642e01fSmrg result = dixLookupWindow(&pWin, stuff->window, client, DixSetPropAccess); 62705b261ecSmrg if (result != Success) 62805b261ecSmrg return result; 62935c4bbdfSmrg if (!ValidAtom(stuff->property)) { 63035c4bbdfSmrg client->errorValue = stuff->property; 63135c4bbdfSmrg return BadAtom; 63205b261ecSmrg } 63305b261ecSmrg 6346747b715Smrg return DeleteProperty(client, pWin, stuff->property); 63505b261ecSmrg} 636