property.c revision 35c4bbdf
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 10805b261ecSmrgstatic void 10905b261ecSmrgdeliverPropertyNotifyEvent(WindowPtr pWin, int state, Atom atom) 11005b261ecSmrg{ 11135c4bbdfSmrg xEvent event = { 11235c4bbdfSmrg .u.property.window = pWin->drawable.id, 11335c4bbdfSmrg .u.property.state = state, 11435c4bbdfSmrg .u.property.atom = atom, 11535c4bbdfSmrg .u.property.time = currentTime.milliseconds 11635c4bbdfSmrg }; 11705b261ecSmrg event.u.u.type = PropertyNotify; 11835c4bbdfSmrg DeliverEvents(pWin, &event, 1, (WindowPtr) NULL); 11905b261ecSmrg} 12005b261ecSmrg 12105b261ecSmrgint 12205b261ecSmrgProcRotateProperties(ClientPtr client) 12305b261ecSmrg{ 12435c4bbdfSmrg int i, j, delta, rc; 12535c4bbdfSmrg 12605b261ecSmrg REQUEST(xRotatePropertiesReq); 12705b261ecSmrg WindowPtr pWin; 12835c4bbdfSmrg Atom *atoms; 12935c4bbdfSmrg PropertyPtr *props; /* array of pointer */ 1304642e01fSmrg PropertyPtr pProp, saved; 13105b261ecSmrg 13205b261ecSmrg REQUEST_FIXED_SIZE(xRotatePropertiesReq, stuff->nAtoms << 2); 13305b261ecSmrg UpdateCurrentTime(); 1344642e01fSmrg rc = dixLookupWindow(&pWin, stuff->window, client, DixSetPropAccess); 1354642e01fSmrg if (rc != Success || stuff->nAtoms <= 0) 13605b261ecSmrg return rc; 1374642e01fSmrg 13835c4bbdfSmrg atoms = (Atom *) &stuff[1]; 13935c4bbdfSmrg props = xallocarray(stuff->nAtoms, sizeof(PropertyPtr)); 14035c4bbdfSmrg saved = xallocarray(stuff->nAtoms, sizeof(PropertyRec)); 1414642e01fSmrg if (!props || !saved) { 14235c4bbdfSmrg rc = BadAlloc; 14335c4bbdfSmrg goto out; 1444642e01fSmrg } 1454642e01fSmrg 14635c4bbdfSmrg for (i = 0; i < stuff->nAtoms; i++) { 1474642e01fSmrg if (!ValidAtom(atoms[i])) { 14835c4bbdfSmrg rc = BadAtom; 14935c4bbdfSmrg client->errorValue = atoms[i]; 15035c4bbdfSmrg goto out; 15105b261ecSmrg } 15205b261ecSmrg for (j = i + 1; j < stuff->nAtoms; j++) 15335c4bbdfSmrg if (atoms[j] == atoms[i]) { 15435c4bbdfSmrg rc = BadMatch; 15535c4bbdfSmrg goto out; 15605b261ecSmrg } 1574642e01fSmrg 15835c4bbdfSmrg rc = dixLookupProperty(&pProp, pWin, atoms[i], client, 15935c4bbdfSmrg DixReadAccess | DixWriteAccess); 16035c4bbdfSmrg if (rc != Success) 16135c4bbdfSmrg goto out; 1624642e01fSmrg 16305b261ecSmrg props[i] = pProp; 16435c4bbdfSmrg saved[i] = *pProp; 16505b261ecSmrg } 16605b261ecSmrg delta = stuff->nPositions; 16705b261ecSmrg 16805b261ecSmrg /* If the rotation is a complete 360 degrees, then moving the properties 16935c4bbdfSmrg around and generating PropertyNotify events should be skipped. */ 17005b261ecSmrg 17135c4bbdfSmrg if (abs(delta) % stuff->nAtoms) { 17235c4bbdfSmrg while (delta < 0) /* faster if abs value is small */ 17305b261ecSmrg delta += stuff->nAtoms; 17435c4bbdfSmrg for (i = 0; i < stuff->nAtoms; i++) { 17535c4bbdfSmrg j = (i + delta) % stuff->nAtoms; 17635c4bbdfSmrg deliverPropertyNotifyEvent(pWin, PropertyNewValue, atoms[i]); 17735c4bbdfSmrg 17835c4bbdfSmrg /* Preserve name and devPrivates */ 17935c4bbdfSmrg props[j]->type = saved[i].type; 18035c4bbdfSmrg props[j]->format = saved[i].format; 18135c4bbdfSmrg props[j]->size = saved[i].size; 18235c4bbdfSmrg props[j]->data = saved[i].data; 18335c4bbdfSmrg } 18405b261ecSmrg } 18535c4bbdfSmrg out: 1866747b715Smrg free(saved); 1876747b715Smrg free(props); 1884642e01fSmrg return rc; 18905b261ecSmrg} 19005b261ecSmrg 19135c4bbdfSmrgint 19205b261ecSmrgProcChangeProperty(ClientPtr client) 19335c4bbdfSmrg{ 19405b261ecSmrg WindowPtr pWin; 19505b261ecSmrg char format, mode; 19605b261ecSmrg unsigned long len; 19705b261ecSmrg int sizeInBytes, totalSize, err; 19835c4bbdfSmrg 19905b261ecSmrg REQUEST(xChangePropertyReq); 20005b261ecSmrg 20105b261ecSmrg REQUEST_AT_LEAST_SIZE(xChangePropertyReq); 20205b261ecSmrg UpdateCurrentTime(); 20305b261ecSmrg format = stuff->format; 20405b261ecSmrg mode = stuff->mode; 20505b261ecSmrg if ((mode != PropModeReplace) && (mode != PropModeAppend) && 20635c4bbdfSmrg (mode != PropModePrepend)) { 20735c4bbdfSmrg client->errorValue = mode; 20835c4bbdfSmrg return BadValue; 20905b261ecSmrg } 21035c4bbdfSmrg if ((format != 8) && (format != 16) && (format != 32)) { 21135c4bbdfSmrg client->errorValue = format; 21205b261ecSmrg return BadValue; 21305b261ecSmrg } 21405b261ecSmrg len = stuff->nUnits; 2156747b715Smrg if (len > bytes_to_int32(0xffffffff - sizeof(xChangePropertyReq))) 21635c4bbdfSmrg return BadLength; 21735c4bbdfSmrg sizeInBytes = format >> 3; 21805b261ecSmrg totalSize = len * sizeInBytes; 21905b261ecSmrg REQUEST_FIXED_SIZE(xChangePropertyReq, totalSize); 22005b261ecSmrg 2214642e01fSmrg err = dixLookupWindow(&pWin, stuff->window, client, DixSetPropAccess); 22205b261ecSmrg if (err != Success) 22335c4bbdfSmrg return err; 22435c4bbdfSmrg if (!ValidAtom(stuff->property)) { 22535c4bbdfSmrg client->errorValue = stuff->property; 22635c4bbdfSmrg return BadAtom; 22705b261ecSmrg } 22835c4bbdfSmrg if (!ValidAtom(stuff->type)) { 22935c4bbdfSmrg client->errorValue = stuff->type; 23035c4bbdfSmrg return BadAtom; 23105b261ecSmrg } 23205b261ecSmrg 2334642e01fSmrg err = dixChangeWindowProperty(client, pWin, stuff->property, stuff->type, 23435c4bbdfSmrg (int) format, (int) mode, len, &stuff[1], 23535c4bbdfSmrg TRUE); 23605b261ecSmrg if (err != Success) 23735c4bbdfSmrg return err; 23805b261ecSmrg else 23935c4bbdfSmrg return Success; 24005b261ecSmrg} 24105b261ecSmrg 2426747b715Smrgint 2434642e01fSmrgdixChangeWindowProperty(ClientPtr pClient, WindowPtr pWin, Atom property, 24435c4bbdfSmrg Atom type, int format, int mode, unsigned long len, 24535c4bbdfSmrg void *value, Bool sendevent) 24605b261ecSmrg{ 24705b261ecSmrg PropertyPtr pProp; 2486747b715Smrg PropertyRec savedProp; 2494642e01fSmrg int sizeInBytes, totalSize, rc; 2506747b715Smrg unsigned char *data; 2514642e01fSmrg Mask access_mode; 25205b261ecSmrg 25335c4bbdfSmrg sizeInBytes = format >> 3; 25405b261ecSmrg totalSize = len * sizeInBytes; 2554642e01fSmrg access_mode = (mode == PropModeReplace) ? DixWriteAccess : DixBlendAccess; 25605b261ecSmrg 25705b261ecSmrg /* first see if property already exists */ 2584642e01fSmrg rc = dixLookupProperty(&pProp, pWin, property, pClient, access_mode); 25905b261ecSmrg 26035c4bbdfSmrg if (rc == BadMatch) { /* just add to list */ 26135c4bbdfSmrg if (!pWin->optional && !MakeWindowOptional(pWin)) 26235c4bbdfSmrg return BadAlloc; 26335c4bbdfSmrg pProp = dixAllocateObjectWithPrivates(PropertyRec, PRIVATE_PROPERTY); 26435c4bbdfSmrg if (!pProp) 26535c4bbdfSmrg return BadAlloc; 2666747b715Smrg data = malloc(totalSize); 26735c4bbdfSmrg if (!data && len) { 26835c4bbdfSmrg dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY); 26935c4bbdfSmrg return BadAlloc; 27035c4bbdfSmrg } 2716747b715Smrg memcpy(data, value, totalSize); 27205b261ecSmrg pProp->propertyName = property; 27305b261ecSmrg pProp->type = type; 27405b261ecSmrg pProp->format = format; 27505b261ecSmrg pProp->data = data; 27635c4bbdfSmrg pProp->size = len; 27735c4bbdfSmrg rc = XaceHookPropertyAccess(pClient, pWin, &pProp, 27835c4bbdfSmrg DixCreateAccess | DixWriteAccess); 27935c4bbdfSmrg if (rc != Success) { 28035c4bbdfSmrg free(data); 28135c4bbdfSmrg dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY); 28235c4bbdfSmrg pClient->errorValue = property; 28335c4bbdfSmrg return rc; 28435c4bbdfSmrg } 28505b261ecSmrg pProp->next = pWin->optional->userProps; 28605b261ecSmrg pWin->optional->userProps = pProp; 28705b261ecSmrg } 28835c4bbdfSmrg else if (rc == Success) { 28935c4bbdfSmrg /* To append or prepend to a property the request format and type 29035c4bbdfSmrg must match those of the already defined property. The 29135c4bbdfSmrg existing format and type are irrelevant when using the mode 29235c4bbdfSmrg "PropModeReplace" since they will be written over. */ 29305b261ecSmrg 29405b261ecSmrg if ((format != pProp->format) && (mode != PropModeReplace)) 29535c4bbdfSmrg return BadMatch; 29605b261ecSmrg if ((pProp->type != type) && (mode != PropModeReplace)) 2976747b715Smrg return BadMatch; 2986747b715Smrg 29935c4bbdfSmrg /* save the old values for later */ 30035c4bbdfSmrg savedProp = *pProp; 30135c4bbdfSmrg 30235c4bbdfSmrg if (mode == PropModeReplace) { 30335c4bbdfSmrg data = malloc(totalSize); 30435c4bbdfSmrg if (!data && len) 30535c4bbdfSmrg return BadAlloc; 30635c4bbdfSmrg memcpy(data, value, totalSize); 30735c4bbdfSmrg pProp->data = data; 30835c4bbdfSmrg pProp->size = len; 30935c4bbdfSmrg pProp->type = type; 31035c4bbdfSmrg pProp->format = format; 31135c4bbdfSmrg } 31235c4bbdfSmrg else if (len == 0) { 31335c4bbdfSmrg /* do nothing */ 31435c4bbdfSmrg } 31535c4bbdfSmrg else if (mode == PropModeAppend) { 31635c4bbdfSmrg data = xallocarray(pProp->size + len, sizeInBytes); 31735c4bbdfSmrg if (!data) 31835c4bbdfSmrg return BadAlloc; 31935c4bbdfSmrg memcpy(data, pProp->data, pProp->size * sizeInBytes); 32035c4bbdfSmrg memcpy(data + pProp->size * sizeInBytes, value, totalSize); 32105b261ecSmrg pProp->data = data; 32205b261ecSmrg pProp->size += len; 32335c4bbdfSmrg } 32435c4bbdfSmrg else if (mode == PropModePrepend) { 32535c4bbdfSmrg data = xallocarray(len + pProp->size, sizeInBytes); 32635c4bbdfSmrg if (!data) 32735c4bbdfSmrg return BadAlloc; 3286747b715Smrg memcpy(data + totalSize, pProp->data, pProp->size * sizeInBytes); 3296747b715Smrg memcpy(data, value, totalSize); 33005b261ecSmrg pProp->data = data; 33105b261ecSmrg pProp->size += len; 33235c4bbdfSmrg } 33335c4bbdfSmrg 33435c4bbdfSmrg /* Allow security modules to check the new content */ 33535c4bbdfSmrg access_mode |= DixPostAccess; 33635c4bbdfSmrg rc = XaceHookPropertyAccess(pClient, pWin, &pProp, access_mode); 33735c4bbdfSmrg if (rc == Success) { 33835c4bbdfSmrg if (savedProp.data != pProp->data) 33935c4bbdfSmrg free(savedProp.data); 34035c4bbdfSmrg } 34135c4bbdfSmrg else { 34235c4bbdfSmrg if (savedProp.data != pProp->data) 34335c4bbdfSmrg free(pProp->data); 34435c4bbdfSmrg *pProp = savedProp; 34535c4bbdfSmrg return rc; 34635c4bbdfSmrg } 34705b261ecSmrg } 3484642e01fSmrg else 34935c4bbdfSmrg return rc; 35005b261ecSmrg 35105b261ecSmrg if (sendevent) 35235c4bbdfSmrg deliverPropertyNotifyEvent(pWin, PropertyNewValue, pProp->propertyName); 35305b261ecSmrg 3546747b715Smrg return Success; 35505b261ecSmrg} 35605b261ecSmrg 3576747b715Smrgint 35835c4bbdfSmrgChangeWindowProperty(WindowPtr pWin, Atom property, Atom type, int format, 35935c4bbdfSmrg int mode, unsigned long len, void *value, Bool sendevent) 3604642e01fSmrg{ 3614642e01fSmrg return dixChangeWindowProperty(serverClient, pWin, property, type, format, 36235c4bbdfSmrg mode, len, value, sendevent); 3634642e01fSmrg} 3644642e01fSmrg 36505b261ecSmrgint 3664642e01fSmrgDeleteProperty(ClientPtr client, WindowPtr pWin, Atom propName) 36705b261ecSmrg{ 36805b261ecSmrg PropertyPtr pProp, prevProp; 3694642e01fSmrg int rc; 37005b261ecSmrg 3714642e01fSmrg rc = dixLookupProperty(&pProp, pWin, propName, client, DixDestroyAccess); 3724642e01fSmrg if (rc == BadMatch) 37335c4bbdfSmrg return Success; /* Succeed if property does not exist */ 3744642e01fSmrg 3754642e01fSmrg if (rc == Success) { 37635c4bbdfSmrg if (pWin->optional->userProps == pProp) { 37735c4bbdfSmrg /* Takes care of head */ 37805b261ecSmrg if (!(pWin->optional->userProps = pProp->next)) 37935c4bbdfSmrg CheckWindowOptionalNeed(pWin); 38035c4bbdfSmrg } 38135c4bbdfSmrg else { 38235c4bbdfSmrg /* Need to traverse to find the previous element */ 38335c4bbdfSmrg prevProp = pWin->optional->userProps; 38435c4bbdfSmrg while (prevProp->next != pProp) 38535c4bbdfSmrg prevProp = prevProp->next; 38635c4bbdfSmrg prevProp->next = pProp->next; 38735c4bbdfSmrg } 38835c4bbdfSmrg 38935c4bbdfSmrg deliverPropertyNotifyEvent(pWin, PropertyDelete, pProp->propertyName); 39035c4bbdfSmrg free(pProp->data); 39135c4bbdfSmrg dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY); 39205b261ecSmrg } 3934642e01fSmrg return rc; 39405b261ecSmrg} 39505b261ecSmrg 39605b261ecSmrgvoid 39705b261ecSmrgDeleteAllWindowProperties(WindowPtr pWin) 39805b261ecSmrg{ 39905b261ecSmrg PropertyPtr pProp, pNextProp; 40005b261ecSmrg 40135c4bbdfSmrg pProp = wUserProps(pWin); 40235c4bbdfSmrg while (pProp) { 40335c4bbdfSmrg deliverPropertyNotifyEvent(pWin, PropertyDelete, pProp->propertyName); 40435c4bbdfSmrg pNextProp = pProp->next; 4056747b715Smrg free(pProp->data); 40635c4bbdfSmrg dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY); 40735c4bbdfSmrg pProp = pNextProp; 40805b261ecSmrg } 4099ace9065Smrg 4109ace9065Smrg if (pWin->optional) 4119ace9065Smrg pWin->optional->userProps = NULL; 41205b261ecSmrg} 41305b261ecSmrg 41405b261ecSmrgstatic int 41535c4bbdfSmrgNullPropertyReply(ClientPtr client, ATOM propertyType, int format) 41605b261ecSmrg{ 41735c4bbdfSmrg xGetPropertyReply reply = { 41835c4bbdfSmrg .type = X_Reply, 41935c4bbdfSmrg .format = format, 42035c4bbdfSmrg .sequenceNumber = client->sequence, 42135c4bbdfSmrg .length = 0, 42235c4bbdfSmrg .propertyType = propertyType, 42335c4bbdfSmrg .bytesAfter = 0, 42435c4bbdfSmrg .nItems = 0 42535c4bbdfSmrg }; 42635c4bbdfSmrg WriteReplyToClient(client, sizeof(xGenericReply), &reply); 4276747b715Smrg return Success; 42805b261ecSmrg} 42905b261ecSmrg 43005b261ecSmrg/***************** 43105b261ecSmrg * GetProperty 43205b261ecSmrg * If type Any is specified, returns the property from the specified 43305b261ecSmrg * window regardless of its type. If a type is specified, returns the 43405b261ecSmrg * property only if its type equals the specified type. 43505b261ecSmrg * If delete is True and a property is returned, the property is also 43605b261ecSmrg * deleted from the window and a PropertyNotify event is generated on the 43705b261ecSmrg * window. 43805b261ecSmrg *****************/ 43905b261ecSmrg 44005b261ecSmrgint 44105b261ecSmrgProcGetProperty(ClientPtr client) 44205b261ecSmrg{ 44305b261ecSmrg PropertyPtr pProp, prevProp; 4444642e01fSmrg unsigned long n, len, ind; 4454642e01fSmrg int rc; 44605b261ecSmrg WindowPtr pWin; 44705b261ecSmrg xGetPropertyReply reply; 4484642e01fSmrg Mask win_mode = DixGetPropAccess, prop_mode = DixReadAccess; 44935c4bbdfSmrg 45005b261ecSmrg REQUEST(xGetPropertyReq); 45105b261ecSmrg 45205b261ecSmrg REQUEST_SIZE_MATCH(xGetPropertyReq); 4534642e01fSmrg if (stuff->delete) { 45435c4bbdfSmrg UpdateCurrentTime(); 45535c4bbdfSmrg win_mode |= DixSetPropAccess; 45635c4bbdfSmrg prop_mode |= DixDestroyAccess; 4574642e01fSmrg } 4584642e01fSmrg rc = dixLookupWindow(&pWin, stuff->window, client, win_mode); 45905b261ecSmrg if (rc != Success) 46035c4bbdfSmrg return rc; 46105b261ecSmrg 46235c4bbdfSmrg if (!ValidAtom(stuff->property)) { 46335c4bbdfSmrg client->errorValue = stuff->property; 46435c4bbdfSmrg return BadAtom; 46505b261ecSmrg } 46635c4bbdfSmrg if ((stuff->delete != xTrue) && (stuff->delete != xFalse)) { 46735c4bbdfSmrg client->errorValue = stuff->delete; 46835c4bbdfSmrg return BadValue; 46905b261ecSmrg } 47035c4bbdfSmrg if ((stuff->type != AnyPropertyType) && !ValidAtom(stuff->type)) { 47135c4bbdfSmrg client->errorValue = stuff->type; 47235c4bbdfSmrg return BadAtom; 47305b261ecSmrg } 47405b261ecSmrg 4754642e01fSmrg rc = dixLookupProperty(&pProp, pWin, stuff->property, client, prop_mode); 4764642e01fSmrg if (rc == BadMatch) 47735c4bbdfSmrg return NullPropertyReply(client, None, 0); 4784642e01fSmrg else if (rc != Success) 47935c4bbdfSmrg return rc; 48005b261ecSmrg 48105b261ecSmrg /* If the request type and actual type don't match. Return the 48235c4bbdfSmrg property information, but not the data. */ 48335c4bbdfSmrg 48435c4bbdfSmrg if (((stuff->type != pProp->type) && (stuff->type != AnyPropertyType)) 48535c4bbdfSmrg ) { 48635c4bbdfSmrg reply = (xGetPropertyReply) { 48735c4bbdfSmrg .type = X_Reply, 48835c4bbdfSmrg .sequenceNumber = client->sequence, 48935c4bbdfSmrg .bytesAfter = pProp->size, 49035c4bbdfSmrg .format = pProp->format, 49135c4bbdfSmrg .length = 0, 49235c4bbdfSmrg .nItems = 0, 49335c4bbdfSmrg .propertyType = pProp->type 49435c4bbdfSmrg }; 49535c4bbdfSmrg WriteReplyToClient(client, sizeof(xGenericReply), &reply); 49635c4bbdfSmrg return Success; 49705b261ecSmrg } 49805b261ecSmrg 49905b261ecSmrg/* 50005b261ecSmrg * Return type, format, value to client 50105b261ecSmrg */ 50235c4bbdfSmrg n = (pProp->format / 8) * pProp->size; /* size (bytes) of prop */ 50335c4bbdfSmrg ind = stuff->longOffset << 2; 50405b261ecSmrg 50535c4bbdfSmrg /* If longOffset is invalid such that it causes "len" to 50635c4bbdfSmrg be negative, it's a value error. */ 50705b261ecSmrg 50835c4bbdfSmrg if (n < ind) { 50935c4bbdfSmrg client->errorValue = stuff->longOffset; 51035c4bbdfSmrg return BadValue; 51105b261ecSmrg } 51205b261ecSmrg 51305b261ecSmrg len = min(n - ind, 4 * stuff->longLength); 51405b261ecSmrg 51535c4bbdfSmrg reply = (xGetPropertyReply) { 51635c4bbdfSmrg .type = X_Reply, 51735c4bbdfSmrg .sequenceNumber = client->sequence, 51835c4bbdfSmrg .bytesAfter = n - (ind + len), 51935c4bbdfSmrg .format = pProp->format, 52035c4bbdfSmrg .length = bytes_to_int32(len), 52135c4bbdfSmrg .nItems = len / (pProp->format / 8), 52235c4bbdfSmrg .propertyType = pProp->type 52335c4bbdfSmrg }; 52405b261ecSmrg 52505b261ecSmrg if (stuff->delete && (reply.bytesAfter == 0)) 52635c4bbdfSmrg deliverPropertyNotifyEvent(pWin, PropertyDelete, pProp->propertyName); 52705b261ecSmrg 52805b261ecSmrg WriteReplyToClient(client, sizeof(xGenericReply), &reply); 52935c4bbdfSmrg if (len) { 53035c4bbdfSmrg switch (reply.format) { 53135c4bbdfSmrg case 32: 53235c4bbdfSmrg client->pSwapReplyFunc = (ReplySwapPtr) CopySwap32Write; 53335c4bbdfSmrg break; 53435c4bbdfSmrg case 16: 53535c4bbdfSmrg client->pSwapReplyFunc = (ReplySwapPtr) CopySwap16Write; 53635c4bbdfSmrg break; 53735c4bbdfSmrg default: 53835c4bbdfSmrg client->pSwapReplyFunc = (ReplySwapPtr) WriteToClient; 53935c4bbdfSmrg break; 54035c4bbdfSmrg } 54135c4bbdfSmrg WriteSwappedDataToClient(client, len, (char *) pProp->data + ind); 54205b261ecSmrg } 54305b261ecSmrg 5444642e01fSmrg if (stuff->delete && (reply.bytesAfter == 0)) { 54535c4bbdfSmrg /* Delete the Property */ 54635c4bbdfSmrg if (pWin->optional->userProps == pProp) { 54735c4bbdfSmrg /* Takes care of head */ 5484642e01fSmrg if (!(pWin->optional->userProps = pProp->next)) 54935c4bbdfSmrg CheckWindowOptionalNeed(pWin); 55035c4bbdfSmrg } 55135c4bbdfSmrg else { 55235c4bbdfSmrg /* Need to traverse to find the previous element */ 55335c4bbdfSmrg prevProp = pWin->optional->userProps; 55435c4bbdfSmrg while (prevProp->next != pProp) 55535c4bbdfSmrg prevProp = prevProp->next; 55635c4bbdfSmrg prevProp->next = pProp->next; 55735c4bbdfSmrg } 55835c4bbdfSmrg 55935c4bbdfSmrg free(pProp->data); 56035c4bbdfSmrg dixFreeObjectWithPrivates(pProp, PRIVATE_PROPERTY); 56105b261ecSmrg } 5626747b715Smrg return Success; 56305b261ecSmrg} 56405b261ecSmrg 56505b261ecSmrgint 56605b261ecSmrgProcListProperties(ClientPtr client) 56705b261ecSmrg{ 56805b261ecSmrg Atom *pAtoms = NULL, *temppAtoms; 56905b261ecSmrg xListPropertiesReply xlpr; 57035c4bbdfSmrg int rc, numProps = 0; 57105b261ecSmrg WindowPtr pWin; 5724642e01fSmrg PropertyPtr pProp, realProp; 57335c4bbdfSmrg 57405b261ecSmrg REQUEST(xResourceReq); 57505b261ecSmrg 57605b261ecSmrg REQUEST_SIZE_MATCH(xResourceReq); 5774642e01fSmrg rc = dixLookupWindow(&pWin, stuff->id, client, DixListPropAccess); 57805b261ecSmrg if (rc != Success) 57905b261ecSmrg return rc; 58005b261ecSmrg 5814642e01fSmrg for (pProp = wUserProps(pWin); pProp; pProp = pProp->next) 58235c4bbdfSmrg numProps++; 5834642e01fSmrg 58435c4bbdfSmrg if (numProps && !(pAtoms = xallocarray(numProps, sizeof(Atom)))) 58535c4bbdfSmrg return BadAlloc; 5864642e01fSmrg 5874642e01fSmrg numProps = 0; 5884642e01fSmrg temppAtoms = pAtoms; 5894642e01fSmrg for (pProp = wUserProps(pWin); pProp; pProp = pProp->next) { 59035c4bbdfSmrg realProp = pProp; 59135c4bbdfSmrg rc = XaceHookPropertyAccess(client, pWin, &realProp, DixGetAttrAccess); 59235c4bbdfSmrg if (rc == Success && realProp == pProp) { 59335c4bbdfSmrg *temppAtoms++ = pProp->propertyName; 59435c4bbdfSmrg numProps++; 59535c4bbdfSmrg } 59605b261ecSmrg } 59705b261ecSmrg 59835c4bbdfSmrg xlpr = (xListPropertiesReply) { 59935c4bbdfSmrg .type = X_Reply, 60035c4bbdfSmrg .sequenceNumber = client->sequence, 60135c4bbdfSmrg .length = bytes_to_int32(numProps * sizeof(Atom)), 60235c4bbdfSmrg .nProperties = numProps 60335c4bbdfSmrg }; 60405b261ecSmrg WriteReplyToClient(client, sizeof(xGenericReply), &xlpr); 60535c4bbdfSmrg if (numProps) { 60635c4bbdfSmrg client->pSwapReplyFunc = (ReplySwapPtr) Swap32Write; 60705b261ecSmrg WriteSwappedDataToClient(client, numProps * sizeof(Atom), pAtoms); 60805b261ecSmrg } 6096747b715Smrg free(pAtoms); 6106747b715Smrg return Success; 61105b261ecSmrg} 61205b261ecSmrg 61335c4bbdfSmrgint 61405b261ecSmrgProcDeleteProperty(ClientPtr client) 61505b261ecSmrg{ 61605b261ecSmrg WindowPtr pWin; 61735c4bbdfSmrg 61805b261ecSmrg REQUEST(xDeletePropertyReq); 61905b261ecSmrg int result; 62035c4bbdfSmrg 62105b261ecSmrg REQUEST_SIZE_MATCH(xDeletePropertyReq); 62205b261ecSmrg UpdateCurrentTime(); 6234642e01fSmrg result = dixLookupWindow(&pWin, stuff->window, client, DixSetPropAccess); 62405b261ecSmrg if (result != Success) 62505b261ecSmrg return result; 62635c4bbdfSmrg if (!ValidAtom(stuff->property)) { 62735c4bbdfSmrg client->errorValue = stuff->property; 62835c4bbdfSmrg return BadAtom; 62905b261ecSmrg } 63005b261ecSmrg 6316747b715Smrg return DeleteProperty(client, pWin, stuff->property); 63205b261ecSmrg} 633