xres.c revision 35c4bbdf
105b261ecSmrg/* 205b261ecSmrg Copyright (c) 2002 XFree86 Inc 305b261ecSmrg*/ 405b261ecSmrg 505b261ecSmrg#ifdef HAVE_DIX_CONFIG_H 605b261ecSmrg#include <dix-config.h> 705b261ecSmrg#endif 805b261ecSmrg 905b261ecSmrg#include <stdio.h> 1005b261ecSmrg#include <string.h> 1105b261ecSmrg#include <X11/X.h> 1205b261ecSmrg#include <X11/Xproto.h> 1335c4bbdfSmrg#include <assert.h> 1405b261ecSmrg#include "misc.h" 1505b261ecSmrg#include "os.h" 1605b261ecSmrg#include "dixstruct.h" 1705b261ecSmrg#include "extnsionst.h" 1805b261ecSmrg#include "swaprep.h" 194642e01fSmrg#include "registry.h" 2005b261ecSmrg#include <X11/extensions/XResproto.h> 2105b261ecSmrg#include "pixmapstr.h" 2205b261ecSmrg#include "windowstr.h" 2305b261ecSmrg#include "gcstruct.h" 2435c4bbdfSmrg#include "extinit.h" 256747b715Smrg#include "protocol-versions.h" 2635c4bbdfSmrg#include "client.h" 2735c4bbdfSmrg#include "list.h" 2835c4bbdfSmrg#include "misc.h" 2935c4bbdfSmrg#include <string.h> 3035c4bbdfSmrg#include "hashtable.h" 3135c4bbdfSmrg#include "picturestr.h" 3235c4bbdfSmrg 3335c4bbdfSmrg#ifdef COMPOSITE 3435c4bbdfSmrg#include "compint.h" 3535c4bbdfSmrg#endif 3635c4bbdfSmrg 3735c4bbdfSmrg/** @brief Holds fragments of responses for ConstructClientIds. 3835c4bbdfSmrg * 3935c4bbdfSmrg * note: there is no consideration for data alignment */ 4035c4bbdfSmrgtypedef struct { 4135c4bbdfSmrg struct xorg_list l; 4235c4bbdfSmrg int bytes; 4335c4bbdfSmrg /* data follows */ 4435c4bbdfSmrg} FragmentList; 4535c4bbdfSmrg 4635c4bbdfSmrg#define FRAGMENT_DATA(ptr) ((void*) ((char*) (ptr) + sizeof(FragmentList))) 4735c4bbdfSmrg 4835c4bbdfSmrg/** @brief Holds structure for the generated response to 4935c4bbdfSmrg ProcXResQueryClientIds; used by ConstructClientId* -functions */ 5035c4bbdfSmrgtypedef struct { 5135c4bbdfSmrg int numIds; 5235c4bbdfSmrg int resultBytes; 5335c4bbdfSmrg struct xorg_list response; 5435c4bbdfSmrg int sentClientMasks[MAXCLIENTS]; 5535c4bbdfSmrg} ConstructClientIdCtx; 5635c4bbdfSmrg 5735c4bbdfSmrg/** @brief Holds the structure for information required to 5835c4bbdfSmrg generate the response to XResQueryResourceBytes. In addition 5935c4bbdfSmrg to response it contains information on the query as well, 6035c4bbdfSmrg as well as some volatile information required by a few 6135c4bbdfSmrg functions that cannot take that information directly 6235c4bbdfSmrg via a parameter, as they are called via already-existing 6335c4bbdfSmrg higher order functions. */ 6435c4bbdfSmrgtypedef struct { 6535c4bbdfSmrg ClientPtr sendClient; 6635c4bbdfSmrg int numSizes; 6735c4bbdfSmrg int resultBytes; 6835c4bbdfSmrg struct xorg_list response; 6935c4bbdfSmrg int status; 7035c4bbdfSmrg long numSpecs; 7135c4bbdfSmrg xXResResourceIdSpec *specs; 7235c4bbdfSmrg HashTable visitedResources; 7335c4bbdfSmrg 7435c4bbdfSmrg /* Used by AddSubResourceSizeSpec when AddResourceSizeValue is 7535c4bbdfSmrg handling crossreferences */ 7635c4bbdfSmrg HashTable visitedSubResources; 7735c4bbdfSmrg 7835c4bbdfSmrg /* used when ConstructResourceBytesCtx is passed to 7935c4bbdfSmrg AddResourceSizeValue2 via FindClientResourcesByType */ 8035c4bbdfSmrg RESTYPE resType; 8135c4bbdfSmrg 8235c4bbdfSmrg /* used when ConstructResourceBytesCtx is passed to 8335c4bbdfSmrg AddResourceSizeValueByResource from ConstructResourceBytesByResource */ 8435c4bbdfSmrg xXResResourceIdSpec *curSpec; 8535c4bbdfSmrg 8635c4bbdfSmrg /** Used when iterating through a single resource's subresources 8735c4bbdfSmrg 8835c4bbdfSmrg @see AddSubResourceSizeSpec */ 8935c4bbdfSmrg xXResResourceSizeValue *sizeValue; 9035c4bbdfSmrg} ConstructResourceBytesCtx; 9135c4bbdfSmrg 9235c4bbdfSmrg/** @brief Allocate and add a sequence of bytes at the end of a fragment list. 9335c4bbdfSmrg Call DestroyFragments to release the list. 9435c4bbdfSmrg 9535c4bbdfSmrg @param frags A pointer to head of an initialized linked list 9635c4bbdfSmrg @param bytes Number of bytes to allocate 9735c4bbdfSmrg @return Returns a pointer to the allocated non-zeroed region 9835c4bbdfSmrg that is to be filled by the caller. On error (out of memory) 9935c4bbdfSmrg returns NULL and makes no changes to the list. 10035c4bbdfSmrg*/ 10135c4bbdfSmrgstatic void * 10235c4bbdfSmrgAddFragment(struct xorg_list *frags, int bytes) 10335c4bbdfSmrg{ 10435c4bbdfSmrg FragmentList *f = malloc(sizeof(FragmentList) + bytes); 10535c4bbdfSmrg if (!f) { 10635c4bbdfSmrg return NULL; 10735c4bbdfSmrg } else { 10835c4bbdfSmrg f->bytes = bytes; 10935c4bbdfSmrg xorg_list_add(&f->l, frags->prev); 11035c4bbdfSmrg return (char*) f + sizeof(*f); 11135c4bbdfSmrg } 11235c4bbdfSmrg} 11335c4bbdfSmrg 11435c4bbdfSmrg/** @brief Sends all fragments in the list to the client. Does not 11535c4bbdfSmrg free anything. 11635c4bbdfSmrg 11735c4bbdfSmrg @param client The client to send the fragments to 11835c4bbdfSmrg @param frags The head of the list of fragments 11935c4bbdfSmrg*/ 12035c4bbdfSmrgstatic void 12135c4bbdfSmrgWriteFragmentsToClient(ClientPtr client, struct xorg_list *frags) 12235c4bbdfSmrg{ 12335c4bbdfSmrg FragmentList *it; 12435c4bbdfSmrg xorg_list_for_each_entry(it, frags, l) { 12535c4bbdfSmrg WriteToClient(client, it->bytes, (char*) it + sizeof(*it)); 12635c4bbdfSmrg } 12735c4bbdfSmrg} 12835c4bbdfSmrg 12935c4bbdfSmrg/** @brief Frees a list of fragments. Does not free() root node. 13035c4bbdfSmrg 13135c4bbdfSmrg @param frags The head of the list of fragments 13235c4bbdfSmrg*/ 13335c4bbdfSmrgstatic void 13435c4bbdfSmrgDestroyFragments(struct xorg_list *frags) 13535c4bbdfSmrg{ 13635c4bbdfSmrg FragmentList *it, *tmp; 13735c4bbdfSmrg xorg_list_for_each_entry_safe(it, tmp, frags, l) { 13835c4bbdfSmrg xorg_list_del(&it->l); 13935c4bbdfSmrg free(it); 14035c4bbdfSmrg } 14135c4bbdfSmrg} 14235c4bbdfSmrg 14335c4bbdfSmrg/** @brief Constructs a context record for ConstructClientId* functions 14435c4bbdfSmrg to use */ 14535c4bbdfSmrgstatic void 14635c4bbdfSmrgInitConstructClientIdCtx(ConstructClientIdCtx *ctx) 14735c4bbdfSmrg{ 14835c4bbdfSmrg ctx->numIds = 0; 14935c4bbdfSmrg ctx->resultBytes = 0; 15035c4bbdfSmrg xorg_list_init(&ctx->response); 15135c4bbdfSmrg memset(ctx->sentClientMasks, 0, sizeof(ctx->sentClientMasks)); 15235c4bbdfSmrg} 15335c4bbdfSmrg 15435c4bbdfSmrg/** @brief Destroys a context record, releases all memory (except the storage 15535c4bbdfSmrg for *ctx itself) */ 15635c4bbdfSmrgstatic void 15735c4bbdfSmrgDestroyConstructClientIdCtx(ConstructClientIdCtx *ctx) 15835c4bbdfSmrg{ 15935c4bbdfSmrg DestroyFragments(&ctx->response); 16035c4bbdfSmrg} 16135c4bbdfSmrg 16235c4bbdfSmrgstatic Bool 16335c4bbdfSmrgInitConstructResourceBytesCtx(ConstructResourceBytesCtx *ctx, 16435c4bbdfSmrg ClientPtr sendClient, 16535c4bbdfSmrg long numSpecs, 16635c4bbdfSmrg xXResResourceIdSpec *specs) 16735c4bbdfSmrg{ 16835c4bbdfSmrg ctx->sendClient = sendClient; 16935c4bbdfSmrg ctx->numSizes = 0; 17035c4bbdfSmrg ctx->resultBytes = 0; 17135c4bbdfSmrg xorg_list_init(&ctx->response); 17235c4bbdfSmrg ctx->status = Success; 17335c4bbdfSmrg ctx->numSpecs = numSpecs; 17435c4bbdfSmrg ctx->specs = specs; 17535c4bbdfSmrg ctx->visitedResources = ht_create(sizeof(XID), 0, 17635c4bbdfSmrg ht_resourceid_hash, ht_resourceid_compare, 17735c4bbdfSmrg NULL); 17835c4bbdfSmrg 17935c4bbdfSmrg if (!ctx->visitedResources) { 18035c4bbdfSmrg return FALSE; 18135c4bbdfSmrg } else { 18235c4bbdfSmrg return TRUE; 18335c4bbdfSmrg } 18435c4bbdfSmrg} 18535c4bbdfSmrg 18635c4bbdfSmrgstatic void 18735c4bbdfSmrgDestroyConstructResourceBytesCtx(ConstructResourceBytesCtx *ctx) 18835c4bbdfSmrg{ 18935c4bbdfSmrg DestroyFragments(&ctx->response); 19035c4bbdfSmrg ht_destroy(ctx->visitedResources); 19135c4bbdfSmrg} 19205b261ecSmrg 19305b261ecSmrgstatic int 19435c4bbdfSmrgProcXResQueryVersion(ClientPtr client) 19535c4bbdfSmrg{ 19635c4bbdfSmrg xXResQueryVersionReply rep = { 19735c4bbdfSmrg .type = X_Reply, 19835c4bbdfSmrg .sequenceNumber = client->sequence, 19935c4bbdfSmrg .length = 0, 20035c4bbdfSmrg .server_major = SERVER_XRES_MAJOR_VERSION, 20135c4bbdfSmrg .server_minor = SERVER_XRES_MINOR_VERSION 20235c4bbdfSmrg }; 20335c4bbdfSmrg 20435c4bbdfSmrg REQUEST_SIZE_MATCH(xXResQueryVersionReq); 20535c4bbdfSmrg 20635c4bbdfSmrg if (client->swapped) { 20735c4bbdfSmrg swaps(&rep.sequenceNumber); 20835c4bbdfSmrg swapl(&rep.length); 20935c4bbdfSmrg swaps(&rep.server_major); 21035c4bbdfSmrg swaps(&rep.server_minor); 21135c4bbdfSmrg } 21235c4bbdfSmrg WriteToClient(client, sizeof(xXResQueryVersionReply), &rep); 2136747b715Smrg return Success; 21405b261ecSmrg} 21505b261ecSmrg 21605b261ecSmrgstatic int 21735c4bbdfSmrgProcXResQueryClients(ClientPtr client) 21805b261ecSmrg{ 21905b261ecSmrg /* REQUEST(xXResQueryClientsReq); */ 22005b261ecSmrg xXResQueryClientsReply rep; 22105b261ecSmrg int *current_clients; 22205b261ecSmrg int i, num_clients; 22305b261ecSmrg 22405b261ecSmrg REQUEST_SIZE_MATCH(xXResQueryClientsReq); 22505b261ecSmrg 22635c4bbdfSmrg current_clients = xallocarray(currentMaxClients, sizeof(int)); 22705b261ecSmrg 22805b261ecSmrg num_clients = 0; 22935c4bbdfSmrg for (i = 0; i < currentMaxClients; i++) { 23035c4bbdfSmrg if (clients[i]) { 23135c4bbdfSmrg current_clients[num_clients] = i; 23235c4bbdfSmrg num_clients++; 23335c4bbdfSmrg } 23405b261ecSmrg } 23505b261ecSmrg 23635c4bbdfSmrg rep = (xXResQueryClientsReply) { 23735c4bbdfSmrg .type = X_Reply, 23835c4bbdfSmrg .sequenceNumber = client->sequence, 23935c4bbdfSmrg .length = bytes_to_int32(num_clients * sz_xXResClient), 24035c4bbdfSmrg .num_clients = num_clients 24135c4bbdfSmrg }; 24205b261ecSmrg if (client->swapped) { 24335c4bbdfSmrg swaps(&rep.sequenceNumber); 24435c4bbdfSmrg swapl(&rep.length); 24535c4bbdfSmrg swapl(&rep.num_clients); 24635c4bbdfSmrg } 24735c4bbdfSmrg WriteToClient(client, sizeof(xXResQueryClientsReply), &rep); 24835c4bbdfSmrg 24935c4bbdfSmrg if (num_clients) { 25005b261ecSmrg xXResClient scratch; 25105b261ecSmrg 25235c4bbdfSmrg for (i = 0; i < num_clients; i++) { 25305b261ecSmrg scratch.resource_base = clients[current_clients[i]]->clientAsMask; 25405b261ecSmrg scratch.resource_mask = RESOURCE_ID_MASK; 25535c4bbdfSmrg 25635c4bbdfSmrg if (client->swapped) { 25735c4bbdfSmrg swapl(&scratch.resource_base); 25835c4bbdfSmrg swapl(&scratch.resource_mask); 25905b261ecSmrg } 26035c4bbdfSmrg WriteToClient(client, sz_xXResClient, &scratch); 26105b261ecSmrg } 26205b261ecSmrg } 26305b261ecSmrg 2646747b715Smrg free(current_clients); 26505b261ecSmrg 2666747b715Smrg return Success; 26705b261ecSmrg} 26805b261ecSmrg 26905b261ecSmrgstatic void 27035c4bbdfSmrgResFindAllRes(void *value, XID id, RESTYPE type, void *cdata) 27105b261ecSmrg{ 27235c4bbdfSmrg int *counts = (int *) cdata; 27305b261ecSmrg 27405b261ecSmrg counts[(type & TypeMask) - 1]++; 27505b261ecSmrg} 27605b261ecSmrg 27705b261ecSmrgstatic int 27835c4bbdfSmrgProcXResQueryClientResources(ClientPtr client) 27905b261ecSmrg{ 28005b261ecSmrg REQUEST(xXResQueryClientResourcesReq); 28105b261ecSmrg xXResQueryClientResourcesReply rep; 28205b261ecSmrg int i, clientID, num_types; 28305b261ecSmrg int *counts; 28405b261ecSmrg 28505b261ecSmrg REQUEST_SIZE_MATCH(xXResQueryClientResourcesReq); 28605b261ecSmrg 28705b261ecSmrg clientID = CLIENT_ID(stuff->xid); 28805b261ecSmrg 28935c4bbdfSmrg if ((clientID >= currentMaxClients) || !clients[clientID]) { 29005b261ecSmrg client->errorValue = stuff->xid; 29105b261ecSmrg return BadValue; 29205b261ecSmrg } 29305b261ecSmrg 2946747b715Smrg counts = calloc(lastResourceType + 1, sizeof(int)); 29505b261ecSmrg 29605b261ecSmrg FindAllClientResources(clients[clientID], ResFindAllRes, counts); 29705b261ecSmrg 29805b261ecSmrg num_types = 0; 29905b261ecSmrg 30035c4bbdfSmrg for (i = 0; i <= lastResourceType; i++) { 30135c4bbdfSmrg if (counts[i]) 30235c4bbdfSmrg num_types++; 30305b261ecSmrg } 30405b261ecSmrg 30535c4bbdfSmrg rep = (xXResQueryClientResourcesReply) { 30635c4bbdfSmrg .type = X_Reply, 30735c4bbdfSmrg .sequenceNumber = client->sequence, 30835c4bbdfSmrg .length = bytes_to_int32(num_types * sz_xXResType), 30935c4bbdfSmrg .num_types = num_types 31035c4bbdfSmrg }; 31105b261ecSmrg if (client->swapped) { 31235c4bbdfSmrg swaps(&rep.sequenceNumber); 31335c4bbdfSmrg swapl(&rep.length); 31435c4bbdfSmrg swapl(&rep.num_types); 31535c4bbdfSmrg } 31605b261ecSmrg 31735c4bbdfSmrg WriteToClient(client, sizeof(xXResQueryClientResourcesReply), &rep); 31805b261ecSmrg 31935c4bbdfSmrg if (num_types) { 32005b261ecSmrg xXResType scratch; 32135c4bbdfSmrg const char *name; 32205b261ecSmrg 32335c4bbdfSmrg for (i = 0; i < lastResourceType; i++) { 32435c4bbdfSmrg if (!counts[i]) 32535c4bbdfSmrg continue; 32605b261ecSmrg 32735c4bbdfSmrg name = LookupResourceName(i + 1); 3284642e01fSmrg if (strcmp(name, XREGISTRY_UNKNOWN)) 32935c4bbdfSmrg scratch.resource_type = MakeAtom(name, strlen(name), TRUE); 33035c4bbdfSmrg else { 33105b261ecSmrg char buf[40]; 33235c4bbdfSmrg 33305b261ecSmrg snprintf(buf, sizeof(buf), "Unregistered resource %i", i + 1); 33435c4bbdfSmrg scratch.resource_type = MakeAtom(buf, strlen(buf), TRUE); 33505b261ecSmrg } 33605b261ecSmrg 33705b261ecSmrg scratch.count = counts[i]; 33805b261ecSmrg 33935c4bbdfSmrg if (client->swapped) { 34035c4bbdfSmrg swapl(&scratch.resource_type); 34135c4bbdfSmrg swapl(&scratch.count); 34205b261ecSmrg } 34335c4bbdfSmrg WriteToClient(client, sz_xXResType, &scratch); 34405b261ecSmrg } 34505b261ecSmrg } 34605b261ecSmrg 3476747b715Smrg free(counts); 34835c4bbdfSmrg 3496747b715Smrg return Success; 35005b261ecSmrg} 35105b261ecSmrg 35205b261ecSmrgstatic unsigned long 35335c4bbdfSmrgResGetApproxPixmapBytes(PixmapPtr pix) 35405b261ecSmrg{ 35535c4bbdfSmrg unsigned long nPixels; 35635c4bbdfSmrg float bytesPerPixel; 35705b261ecSmrg 35835c4bbdfSmrg bytesPerPixel = (float)pix->drawable.bitsPerPixel / 8.0; 35935c4bbdfSmrg nPixels = pix->drawable.width * pix->drawable.height; 36005b261ecSmrg 36135c4bbdfSmrg /* Divide by refcnt as pixmap could be shared between clients, 36235c4bbdfSmrg * so total pixmap mem is shared between these. 36335c4bbdfSmrg */ 36435c4bbdfSmrg return (nPixels * bytesPerPixel) / pix->refcnt; 36505b261ecSmrg} 36605b261ecSmrg 36735c4bbdfSmrgstatic void 36835c4bbdfSmrgResFindResourcePixmaps(void *value, XID id, RESTYPE type, void *cdata) 36905b261ecSmrg{ 37035c4bbdfSmrg SizeType sizeFunc = GetResourceTypeSizeFunc(type); 37135c4bbdfSmrg ResourceSizeRec size = { 0, 0, 0 }; 37235c4bbdfSmrg unsigned long *bytes = cdata; 37305b261ecSmrg 37435c4bbdfSmrg sizeFunc(value, id, &size); 37535c4bbdfSmrg *bytes += size.pixmapRefSize; 37605b261ecSmrg} 37705b261ecSmrg 37805b261ecSmrgstatic void 37935c4bbdfSmrgResFindPixmaps(void *value, XID id, void *cdata) 38005b261ecSmrg{ 38135c4bbdfSmrg unsigned long *bytes = (unsigned long *) cdata; 38235c4bbdfSmrg PixmapPtr pix = (PixmapPtr) value; 38305b261ecSmrg 38435c4bbdfSmrg *bytes += ResGetApproxPixmapBytes(pix); 38535c4bbdfSmrg} 38605b261ecSmrg 38735c4bbdfSmrgstatic void 38835c4bbdfSmrgResFindWindowPixmaps(void *value, XID id, void *cdata) 38935c4bbdfSmrg{ 39035c4bbdfSmrg unsigned long *bytes = (unsigned long *) cdata; 39135c4bbdfSmrg WindowPtr pWin = (WindowPtr) value; 39235c4bbdfSmrg 39335c4bbdfSmrg if (pWin->backgroundState == BackgroundPixmap) 39435c4bbdfSmrg *bytes += ResGetApproxPixmapBytes(pWin->background.pixmap); 39535c4bbdfSmrg 39635c4bbdfSmrg if (pWin->border.pixmap != NULL && !pWin->borderIsPixel) 39735c4bbdfSmrg *bytes += ResGetApproxPixmapBytes(pWin->border.pixmap); 39805b261ecSmrg} 39905b261ecSmrg 40005b261ecSmrgstatic void 40135c4bbdfSmrgResFindGCPixmaps(void *value, XID id, void *cdata) 40205b261ecSmrg{ 40335c4bbdfSmrg unsigned long *bytes = (unsigned long *) cdata; 40435c4bbdfSmrg GCPtr pGC = (GCPtr) value; 40505b261ecSmrg 40635c4bbdfSmrg if (pGC->stipple != NULL) 40735c4bbdfSmrg *bytes += ResGetApproxPixmapBytes(pGC->stipple); 40805b261ecSmrg 40935c4bbdfSmrg if (pGC->tile.pixmap != NULL && !pGC->tileIsPixel) 41035c4bbdfSmrg *bytes += ResGetApproxPixmapBytes(pGC->tile.pixmap); 41135c4bbdfSmrg} 41235c4bbdfSmrg 41335c4bbdfSmrg#ifdef RENDER 41435c4bbdfSmrgstatic void 41535c4bbdfSmrgResFindPicturePixmaps(void *value, XID id, void *cdata) 41635c4bbdfSmrg{ 41735c4bbdfSmrg ResFindResourcePixmaps(value, id, PictureType, cdata); 41835c4bbdfSmrg} 41935c4bbdfSmrg#endif 42035c4bbdfSmrg 42135c4bbdfSmrg#ifdef COMPOSITE 42235c4bbdfSmrgstatic void 42335c4bbdfSmrgResFindCompositeClientWindowPixmaps (void *value, XID id, void *cdata) 42435c4bbdfSmrg{ 42535c4bbdfSmrg ResFindResourcePixmaps(value, id, CompositeClientWindowType, cdata); 42605b261ecSmrg} 42735c4bbdfSmrg#endif 42805b261ecSmrg 42905b261ecSmrgstatic int 43035c4bbdfSmrgProcXResQueryClientPixmapBytes(ClientPtr client) 43105b261ecSmrg{ 43205b261ecSmrg REQUEST(xXResQueryClientPixmapBytesReq); 43305b261ecSmrg xXResQueryClientPixmapBytesReply rep; 43405b261ecSmrg int clientID; 43505b261ecSmrg unsigned long bytes; 43605b261ecSmrg 43705b261ecSmrg REQUEST_SIZE_MATCH(xXResQueryClientPixmapBytesReq); 43805b261ecSmrg 43905b261ecSmrg clientID = CLIENT_ID(stuff->xid); 44005b261ecSmrg 44135c4bbdfSmrg if ((clientID >= currentMaxClients) || !clients[clientID]) { 44205b261ecSmrg client->errorValue = stuff->xid; 44305b261ecSmrg return BadValue; 44405b261ecSmrg } 44505b261ecSmrg 44605b261ecSmrg bytes = 0; 44705b261ecSmrg 44835c4bbdfSmrg FindClientResourcesByType(clients[clientID], RT_PIXMAP, ResFindPixmaps, 44935c4bbdfSmrg (void *) (&bytes)); 45005b261ecSmrg 45135c4bbdfSmrg /* 45235c4bbdfSmrg * Make sure win background pixmaps also held to account. 45305b261ecSmrg */ 45435c4bbdfSmrg FindClientResourcesByType(clients[clientID], RT_WINDOW, 45535c4bbdfSmrg ResFindWindowPixmaps, (void *) (&bytes)); 45605b261ecSmrg 45735c4bbdfSmrg /* 45805b261ecSmrg * GC Tile & Stipple pixmaps too. 45935c4bbdfSmrg */ 46035c4bbdfSmrg FindClientResourcesByType(clients[clientID], RT_GC, 46135c4bbdfSmrg ResFindGCPixmaps, (void *) (&bytes)); 46235c4bbdfSmrg 46335c4bbdfSmrg#ifdef RENDER 46435c4bbdfSmrg /* Render extension picture pixmaps. */ 46535c4bbdfSmrg FindClientResourcesByType(clients[clientID], PictureType, 46635c4bbdfSmrg ResFindPicturePixmaps, 46735c4bbdfSmrg (void *)(&bytes)); 46835c4bbdfSmrg#endif 46905b261ecSmrg 47005b261ecSmrg#ifdef COMPOSITE 47135c4bbdfSmrg /* Composite extension client window pixmaps. */ 47235c4bbdfSmrg FindClientResourcesByType(clients[clientID], CompositeClientWindowType, 47335c4bbdfSmrg ResFindCompositeClientWindowPixmaps, 47435c4bbdfSmrg (void *)(&bytes)); 47505b261ecSmrg#endif 47605b261ecSmrg 47735c4bbdfSmrg rep = (xXResQueryClientPixmapBytesReply) { 47835c4bbdfSmrg .type = X_Reply, 47935c4bbdfSmrg .sequenceNumber = client->sequence, 48035c4bbdfSmrg .length = 0, 48135c4bbdfSmrg .bytes = bytes, 48205b261ecSmrg#ifdef _XSERVER64 48335c4bbdfSmrg .bytes_overflow = bytes >> 32 48405b261ecSmrg#else 48535c4bbdfSmrg .bytes_overflow = 0 48605b261ecSmrg#endif 48735c4bbdfSmrg }; 48805b261ecSmrg if (client->swapped) { 48935c4bbdfSmrg swaps(&rep.sequenceNumber); 49035c4bbdfSmrg swapl(&rep.length); 49135c4bbdfSmrg swapl(&rep.bytes); 49235c4bbdfSmrg swapl(&rep.bytes_overflow); 49305b261ecSmrg } 49435c4bbdfSmrg WriteToClient(client, sizeof(xXResQueryClientPixmapBytesReply), &rep); 49505b261ecSmrg 4966747b715Smrg return Success; 49705b261ecSmrg} 49805b261ecSmrg 49935c4bbdfSmrg/** @brief Finds out if a client's information need to be put into the 50035c4bbdfSmrg response; marks client having been handled, if that is the case. 50135c4bbdfSmrg 50235c4bbdfSmrg @param client The client to send information about 50335c4bbdfSmrg @param mask The request mask (0 to send everything, otherwise a 50435c4bbdfSmrg bitmask of X_XRes*Mask) 50535c4bbdfSmrg @param ctx The context record that tells which clients and id types 50635c4bbdfSmrg have been already handled 50735c4bbdfSmrg @param sendMask Which id type are we now considering. One of X_XRes*Mask. 50835c4bbdfSmrg 50935c4bbdfSmrg @return Returns TRUE if the client information needs to be on the 51035c4bbdfSmrg response, otherwise FALSE. 51135c4bbdfSmrg*/ 51235c4bbdfSmrgstatic Bool 51335c4bbdfSmrgWillConstructMask(ClientPtr client, CARD32 mask, 51435c4bbdfSmrg ConstructClientIdCtx *ctx, int sendMask) 51535c4bbdfSmrg{ 51635c4bbdfSmrg if ((!mask || (mask & sendMask)) 51735c4bbdfSmrg && !(ctx->sentClientMasks[client->index] & sendMask)) { 51835c4bbdfSmrg ctx->sentClientMasks[client->index] |= sendMask; 51935c4bbdfSmrg return TRUE; 52035c4bbdfSmrg } else { 52135c4bbdfSmrg return FALSE; 52235c4bbdfSmrg } 52335c4bbdfSmrg} 52435c4bbdfSmrg 52535c4bbdfSmrg/** @brief Constructs a response about a single client, based on a certain 52635c4bbdfSmrg client id spec 52735c4bbdfSmrg 52835c4bbdfSmrg @param sendClient Which client wishes to receive this answer. Used for 52935c4bbdfSmrg byte endianess. 53035c4bbdfSmrg @param client Which client are we considering. 53135c4bbdfSmrg @param mask The client id spec mask indicating which information 53235c4bbdfSmrg we want about this client. 53335c4bbdfSmrg @param ctx The context record containing the constructed response 53435c4bbdfSmrg and information on which clients and masks have been 53535c4bbdfSmrg already handled. 53635c4bbdfSmrg 53735c4bbdfSmrg @return Return TRUE if everything went OK, otherwise FALSE which indicates 53835c4bbdfSmrg a memory allocation problem. 53935c4bbdfSmrg*/ 54035c4bbdfSmrgstatic Bool 54135c4bbdfSmrgConstructClientIdValue(ClientPtr sendClient, ClientPtr client, CARD32 mask, 54235c4bbdfSmrg ConstructClientIdCtx *ctx) 54335c4bbdfSmrg{ 54435c4bbdfSmrg xXResClientIdValue rep; 54535c4bbdfSmrg 54635c4bbdfSmrg rep.spec.client = client->clientAsMask; 54735c4bbdfSmrg if (client->swapped) { 54835c4bbdfSmrg swapl (&rep.spec.client); 54935c4bbdfSmrg } 55035c4bbdfSmrg 55135c4bbdfSmrg if (WillConstructMask(client, mask, ctx, X_XResClientXIDMask)) { 55235c4bbdfSmrg void *ptr = AddFragment(&ctx->response, sizeof(rep)); 55335c4bbdfSmrg if (!ptr) { 55435c4bbdfSmrg return FALSE; 55535c4bbdfSmrg } 55635c4bbdfSmrg 55735c4bbdfSmrg rep.spec.mask = X_XResClientXIDMask; 55835c4bbdfSmrg rep.length = 0; 55935c4bbdfSmrg if (sendClient->swapped) { 56035c4bbdfSmrg swapl (&rep.spec.mask); 56135c4bbdfSmrg /* swapl (&rep.length, n); - not required for rep.length = 0 */ 56235c4bbdfSmrg } 56335c4bbdfSmrg 56435c4bbdfSmrg memcpy(ptr, &rep, sizeof(rep)); 56535c4bbdfSmrg 56635c4bbdfSmrg ctx->resultBytes += sizeof(rep); 56735c4bbdfSmrg ++ctx->numIds; 56835c4bbdfSmrg } 56935c4bbdfSmrg if (WillConstructMask(client, mask, ctx, X_XResLocalClientPIDMask)) { 57035c4bbdfSmrg pid_t pid = GetClientPid(client); 57135c4bbdfSmrg 57235c4bbdfSmrg if (pid != -1) { 57335c4bbdfSmrg void *ptr = AddFragment(&ctx->response, 57435c4bbdfSmrg sizeof(rep) + sizeof(CARD32)); 57535c4bbdfSmrg CARD32 *value = (void*) ((char*) ptr + sizeof(rep)); 57635c4bbdfSmrg 57735c4bbdfSmrg if (!ptr) { 57835c4bbdfSmrg return FALSE; 57935c4bbdfSmrg } 58035c4bbdfSmrg 58135c4bbdfSmrg rep.spec.mask = X_XResLocalClientPIDMask; 58235c4bbdfSmrg rep.length = 4; 58335c4bbdfSmrg 58435c4bbdfSmrg if (sendClient->swapped) { 58535c4bbdfSmrg swapl (&rep.spec.mask); 58635c4bbdfSmrg swapl (&rep.length); 58735c4bbdfSmrg } 58835c4bbdfSmrg 58935c4bbdfSmrg if (sendClient->swapped) { 59035c4bbdfSmrg swapl (value); 59135c4bbdfSmrg } 59235c4bbdfSmrg memcpy(ptr, &rep, sizeof(rep)); 59335c4bbdfSmrg *value = pid; 59435c4bbdfSmrg 59535c4bbdfSmrg ctx->resultBytes += sizeof(rep) + sizeof(CARD32); 59635c4bbdfSmrg ++ctx->numIds; 59735c4bbdfSmrg } 59835c4bbdfSmrg } 59935c4bbdfSmrg 60035c4bbdfSmrg /* memory allocation errors earlier may return with FALSE */ 60135c4bbdfSmrg return TRUE; 60235c4bbdfSmrg} 60335c4bbdfSmrg 60435c4bbdfSmrg/** @brief Constructs a response about all clients, based on a client id specs 60535c4bbdfSmrg 60635c4bbdfSmrg @param client Which client which we are constructing the response for. 60735c4bbdfSmrg @param numSpecs Number of client id specs in specs 60835c4bbdfSmrg @param specs Client id specs 60935c4bbdfSmrg 61035c4bbdfSmrg @return Return Success if everything went OK, otherwise a Bad* (currently 61135c4bbdfSmrg BadAlloc or BadValue) 61235c4bbdfSmrg*/ 61335c4bbdfSmrgstatic int 61435c4bbdfSmrgConstructClientIds(ClientPtr client, 61535c4bbdfSmrg int numSpecs, xXResClientIdSpec* specs, 61635c4bbdfSmrg ConstructClientIdCtx *ctx) 61735c4bbdfSmrg{ 61835c4bbdfSmrg int specIdx; 61935c4bbdfSmrg 62035c4bbdfSmrg for (specIdx = 0; specIdx < numSpecs; ++specIdx) { 62135c4bbdfSmrg if (specs[specIdx].client == 0) { 62235c4bbdfSmrg int c; 62335c4bbdfSmrg for (c = 0; c < currentMaxClients; ++c) { 62435c4bbdfSmrg if (clients[c]) { 62535c4bbdfSmrg if (!ConstructClientIdValue(client, clients[c], 62635c4bbdfSmrg specs[specIdx].mask, ctx)) { 62735c4bbdfSmrg return BadAlloc; 62835c4bbdfSmrg } 62935c4bbdfSmrg } 63035c4bbdfSmrg } 63135c4bbdfSmrg } else { 63235c4bbdfSmrg int clientID = CLIENT_ID(specs[specIdx].client); 63335c4bbdfSmrg 63435c4bbdfSmrg if ((clientID < currentMaxClients) && clients[clientID]) { 63535c4bbdfSmrg if (!ConstructClientIdValue(client, clients[clientID], 63635c4bbdfSmrg specs[specIdx].mask, ctx)) { 63735c4bbdfSmrg return BadAlloc; 63835c4bbdfSmrg } 63935c4bbdfSmrg } 64035c4bbdfSmrg } 64135c4bbdfSmrg } 64235c4bbdfSmrg 64335c4bbdfSmrg /* memory allocation errors earlier may return with BadAlloc */ 64435c4bbdfSmrg return Success; 64535c4bbdfSmrg} 64635c4bbdfSmrg 64735c4bbdfSmrg/** @brief Response to XResQueryClientIds request introduced in XResProto v1.2 64835c4bbdfSmrg 64935c4bbdfSmrg @param client Which client which we are constructing the response for. 65035c4bbdfSmrg 65135c4bbdfSmrg @return Returns the value returned from ConstructClientIds with the same 65235c4bbdfSmrg semantics 65335c4bbdfSmrg*/ 65435c4bbdfSmrgstatic int 65535c4bbdfSmrgProcXResQueryClientIds (ClientPtr client) 65635c4bbdfSmrg{ 65735c4bbdfSmrg REQUEST(xXResQueryClientIdsReq); 65835c4bbdfSmrg 65935c4bbdfSmrg xXResClientIdSpec *specs = (void*) ((char*) stuff + sizeof(*stuff)); 66035c4bbdfSmrg int rc; 66135c4bbdfSmrg ConstructClientIdCtx ctx; 66235c4bbdfSmrg 66335c4bbdfSmrg InitConstructClientIdCtx(&ctx); 66435c4bbdfSmrg 66535c4bbdfSmrg REQUEST_AT_LEAST_SIZE(xXResQueryClientIdsReq); 66635c4bbdfSmrg REQUEST_FIXED_SIZE(xXResQueryClientIdsReq, 66735c4bbdfSmrg stuff->numSpecs * sizeof(specs[0])); 66835c4bbdfSmrg 66935c4bbdfSmrg rc = ConstructClientIds(client, stuff->numSpecs, specs, &ctx); 67035c4bbdfSmrg 67135c4bbdfSmrg if (rc == Success) { 67235c4bbdfSmrg xXResQueryClientIdsReply rep = { 67335c4bbdfSmrg .type = X_Reply, 67435c4bbdfSmrg .sequenceNumber = client->sequence, 67535c4bbdfSmrg .length = bytes_to_int32(ctx.resultBytes), 67635c4bbdfSmrg .numIds = ctx.numIds 67735c4bbdfSmrg }; 67835c4bbdfSmrg 67935c4bbdfSmrg assert((ctx.resultBytes & 3) == 0); 68035c4bbdfSmrg 68135c4bbdfSmrg if (client->swapped) { 68235c4bbdfSmrg swaps (&rep.sequenceNumber); 68335c4bbdfSmrg swapl (&rep.length); 68435c4bbdfSmrg swapl (&rep.numIds); 68535c4bbdfSmrg } 68635c4bbdfSmrg 68735c4bbdfSmrg WriteToClient(client, sizeof(rep), &rep); 68835c4bbdfSmrg WriteFragmentsToClient(client, &ctx.response); 68935c4bbdfSmrg } 69035c4bbdfSmrg 69135c4bbdfSmrg DestroyConstructClientIdCtx(&ctx); 69235c4bbdfSmrg 69335c4bbdfSmrg return rc; 69435c4bbdfSmrg} 69535c4bbdfSmrg 69635c4bbdfSmrg/** @brief Swaps xXResResourceIdSpec endianess */ 69735c4bbdfSmrgstatic void 69835c4bbdfSmrgSwapXResResourceIdSpec(xXResResourceIdSpec *spec) 69935c4bbdfSmrg{ 70035c4bbdfSmrg swapl(&spec->resource); 70135c4bbdfSmrg swapl(&spec->type); 70235c4bbdfSmrg} 70335c4bbdfSmrg 70435c4bbdfSmrg/** @brief Swaps xXResResourceSizeSpec endianess */ 70535c4bbdfSmrgstatic void 70635c4bbdfSmrgSwapXResResourceSizeSpec(xXResResourceSizeSpec *size) 70735c4bbdfSmrg{ 70835c4bbdfSmrg SwapXResResourceIdSpec(&size->spec); 70935c4bbdfSmrg swapl(&size->bytes); 71035c4bbdfSmrg swapl(&size->refCount); 71135c4bbdfSmrg swapl(&size->useCount); 71235c4bbdfSmrg} 71335c4bbdfSmrg 71435c4bbdfSmrg/** @brief Swaps xXResResourceSizeValue endianess */ 71535c4bbdfSmrgstatic void 71635c4bbdfSmrgSwapXResResourceSizeValue(xXResResourceSizeValue *rep) 71735c4bbdfSmrg{ 71835c4bbdfSmrg SwapXResResourceSizeSpec(&rep->size); 71935c4bbdfSmrg swapl(&rep->numCrossReferences); 72035c4bbdfSmrg} 72135c4bbdfSmrg 72235c4bbdfSmrg/** @brief Swaps the response bytes */ 72335c4bbdfSmrgstatic void 72435c4bbdfSmrgSwapXResQueryResourceBytes(struct xorg_list *response) 72535c4bbdfSmrg{ 72635c4bbdfSmrg struct xorg_list *it = response->next; 72735c4bbdfSmrg int c; 72835c4bbdfSmrg 72935c4bbdfSmrg while (it != response) { 73035c4bbdfSmrg xXResResourceSizeValue *value = FRAGMENT_DATA(it); 73135c4bbdfSmrg it = it->next; 73235c4bbdfSmrg for (c = 0; c < value->numCrossReferences; ++c) { 73335c4bbdfSmrg xXResResourceSizeSpec *spec = FRAGMENT_DATA(it); 73435c4bbdfSmrg SwapXResResourceSizeSpec(spec); 73535c4bbdfSmrg it = it->next; 73635c4bbdfSmrg } 73735c4bbdfSmrg SwapXResResourceSizeValue(value); 73835c4bbdfSmrg } 73935c4bbdfSmrg} 74035c4bbdfSmrg 74135c4bbdfSmrg/** @brief Adds xXResResourceSizeSpec describing a resource's size into 74235c4bbdfSmrg the buffer contained in the context. The resource is considered 74335c4bbdfSmrg to be a subresource. 74435c4bbdfSmrg 74535c4bbdfSmrg @see AddResourceSizeValue 74635c4bbdfSmrg 74735c4bbdfSmrg @param[in] value The X resource object on which to add information 74835c4bbdfSmrg about to the buffer 74935c4bbdfSmrg @param[in] id The ID of the X resource 75035c4bbdfSmrg @param[in] type The type of the X resource 75135c4bbdfSmrg @param[in/out] cdata The context object of type ConstructResourceBytesCtx. 75235c4bbdfSmrg Void pointer type is used here to satisfy the type 75335c4bbdfSmrg FindRes 75435c4bbdfSmrg*/ 75535c4bbdfSmrgstatic void 75635c4bbdfSmrgAddSubResourceSizeSpec(void *value, 75735c4bbdfSmrg XID id, 75835c4bbdfSmrg RESTYPE type, 75935c4bbdfSmrg void *cdata) 76035c4bbdfSmrg{ 76135c4bbdfSmrg ConstructResourceBytesCtx *ctx = cdata; 76235c4bbdfSmrg 76335c4bbdfSmrg if (ctx->status == Success) { 76435c4bbdfSmrg xXResResourceSizeSpec **prevCrossRef = 76535c4bbdfSmrg ht_find(ctx->visitedSubResources, &value); 76635c4bbdfSmrg if (!prevCrossRef) { 76735c4bbdfSmrg Bool ok = TRUE; 76835c4bbdfSmrg xXResResourceSizeSpec *crossRef = 76935c4bbdfSmrg AddFragment(&ctx->response, sizeof(xXResResourceSizeSpec)); 77035c4bbdfSmrg ok = ok && crossRef != NULL; 77135c4bbdfSmrg if (ok) { 77235c4bbdfSmrg xXResResourceSizeSpec **p; 77335c4bbdfSmrg p = ht_add(ctx->visitedSubResources, &value); 77435c4bbdfSmrg if (!p) { 77535c4bbdfSmrg ok = FALSE; 77635c4bbdfSmrg } else { 77735c4bbdfSmrg *p = crossRef; 77835c4bbdfSmrg } 77935c4bbdfSmrg } 78035c4bbdfSmrg if (!ok) { 78135c4bbdfSmrg ctx->status = BadAlloc; 78235c4bbdfSmrg } else { 78335c4bbdfSmrg SizeType sizeFunc = GetResourceTypeSizeFunc(type); 78435c4bbdfSmrg ResourceSizeRec size = { 0, 0, 0 }; 78535c4bbdfSmrg sizeFunc(value, id, &size); 78635c4bbdfSmrg 78735c4bbdfSmrg crossRef->spec.resource = id; 78835c4bbdfSmrg crossRef->spec.type = type; 78935c4bbdfSmrg crossRef->bytes = size.resourceSize; 79035c4bbdfSmrg crossRef->refCount = size.refCnt; 79135c4bbdfSmrg crossRef->useCount = 1; 79235c4bbdfSmrg 79335c4bbdfSmrg ++ctx->sizeValue->numCrossReferences; 79435c4bbdfSmrg 79535c4bbdfSmrg ctx->resultBytes += sizeof(*crossRef); 79635c4bbdfSmrg } 79735c4bbdfSmrg } else { 79835c4bbdfSmrg /* if we have visited the subresource earlier (from current parent 79935c4bbdfSmrg resource), just increase its use count by one */ 80035c4bbdfSmrg ++(*prevCrossRef)->useCount; 80135c4bbdfSmrg } 80235c4bbdfSmrg } 80335c4bbdfSmrg} 80435c4bbdfSmrg 80535c4bbdfSmrg/** @brief Adds xXResResourceSizeValue describing a resource's size into 80635c4bbdfSmrg the buffer contained in the context. In addition, the 80735c4bbdfSmrg subresources are iterated and added as xXResResourceSizeSpec's 80835c4bbdfSmrg by using AddSubResourceSizeSpec 80935c4bbdfSmrg 81035c4bbdfSmrg @see AddSubResourceSizeSpec 81135c4bbdfSmrg 81235c4bbdfSmrg @param[in] value The X resource object on which to add information 81335c4bbdfSmrg about to the buffer 81435c4bbdfSmrg @param[in] id The ID of the X resource 81535c4bbdfSmrg @param[in] type The type of the X resource 81635c4bbdfSmrg @param[in/out] cdata The context object of type ConstructResourceBytesCtx. 81735c4bbdfSmrg Void pointer type is used here to satisfy the type 81835c4bbdfSmrg FindRes 81935c4bbdfSmrg*/ 82035c4bbdfSmrgstatic void 82135c4bbdfSmrgAddResourceSizeValue(void *ptr, XID id, RESTYPE type, void *cdata) 82235c4bbdfSmrg{ 82335c4bbdfSmrg ConstructResourceBytesCtx *ctx = cdata; 82435c4bbdfSmrg if (ctx->status == Success && 82535c4bbdfSmrg !ht_find(ctx->visitedResources, &id)) { 82635c4bbdfSmrg Bool ok = TRUE; 82735c4bbdfSmrg HashTable ht; 82835c4bbdfSmrg HtGenericHashSetupRec htSetup = { 82935c4bbdfSmrg .keySize = sizeof(void*) 83035c4bbdfSmrg }; 83135c4bbdfSmrg 83235c4bbdfSmrg /* it doesn't matter that we don't undo the work done here 83335c4bbdfSmrg * immediately. All but ht_init will be undone at the end 83435c4bbdfSmrg * of the request and there can happen no failure after 83535c4bbdfSmrg * ht_init, so we don't need to clean it up here in any 83635c4bbdfSmrg * special way */ 83735c4bbdfSmrg 83835c4bbdfSmrg xXResResourceSizeValue *value = 83935c4bbdfSmrg AddFragment(&ctx->response, sizeof(xXResResourceSizeValue)); 84035c4bbdfSmrg if (!value) { 84135c4bbdfSmrg ok = FALSE; 84235c4bbdfSmrg } 84335c4bbdfSmrg ok = ok && ht_add(ctx->visitedResources, &id); 84435c4bbdfSmrg if (ok) { 84535c4bbdfSmrg ht = ht_create(htSetup.keySize, 84635c4bbdfSmrg sizeof(xXResResourceSizeSpec*), 84735c4bbdfSmrg ht_generic_hash, ht_generic_compare, 84835c4bbdfSmrg &htSetup); 84935c4bbdfSmrg ok = ok && ht; 85035c4bbdfSmrg } 85135c4bbdfSmrg 85235c4bbdfSmrg if (!ok) { 85335c4bbdfSmrg ctx->status = BadAlloc; 85435c4bbdfSmrg } else { 85535c4bbdfSmrg SizeType sizeFunc = GetResourceTypeSizeFunc(type); 85635c4bbdfSmrg ResourceSizeRec size = { 0, 0, 0 }; 85735c4bbdfSmrg 85835c4bbdfSmrg sizeFunc(ptr, id, &size); 85935c4bbdfSmrg 86035c4bbdfSmrg value->size.spec.resource = id; 86135c4bbdfSmrg value->size.spec.type = type; 86235c4bbdfSmrg value->size.bytes = size.resourceSize; 86335c4bbdfSmrg value->size.refCount = size.refCnt; 86435c4bbdfSmrg value->size.useCount = 1; 86535c4bbdfSmrg value->numCrossReferences = 0; 86635c4bbdfSmrg 86735c4bbdfSmrg ctx->sizeValue = value; 86835c4bbdfSmrg ctx->visitedSubResources = ht; 86935c4bbdfSmrg FindSubResources(ptr, type, AddSubResourceSizeSpec, ctx); 87035c4bbdfSmrg ctx->visitedSubResources = NULL; 87135c4bbdfSmrg ctx->sizeValue = NULL; 87235c4bbdfSmrg 87335c4bbdfSmrg ctx->resultBytes += sizeof(*value); 87435c4bbdfSmrg ++ctx->numSizes; 87535c4bbdfSmrg 87635c4bbdfSmrg ht_destroy(ht); 87735c4bbdfSmrg } 87835c4bbdfSmrg } 87935c4bbdfSmrg} 88035c4bbdfSmrg 88135c4bbdfSmrg/** @brief A variant of AddResourceSizeValue that passes the resource type 88235c4bbdfSmrg through the context object to satisfy the type FindResType 88335c4bbdfSmrg 88435c4bbdfSmrg @see AddResourceSizeValue 88535c4bbdfSmrg 88635c4bbdfSmrg @param[in] ptr The resource 88735c4bbdfSmrg @param[in] id The resource ID 88835c4bbdfSmrg @param[in/out] cdata The context object that contains the resource type 88935c4bbdfSmrg*/ 89035c4bbdfSmrgstatic void 89135c4bbdfSmrgAddResourceSizeValueWithResType(void *ptr, XID id, void *cdata) 89235c4bbdfSmrg{ 89335c4bbdfSmrg ConstructResourceBytesCtx *ctx = cdata; 89435c4bbdfSmrg AddResourceSizeValue(ptr, id, ctx->resType, cdata); 89535c4bbdfSmrg} 89635c4bbdfSmrg 89735c4bbdfSmrg/** @brief Adds the information of a resource into the buffer if it matches 89835c4bbdfSmrg the match condition. 89935c4bbdfSmrg 90035c4bbdfSmrg @see AddResourceSizeValue 90135c4bbdfSmrg 90235c4bbdfSmrg @param[in] ptr The resource 90335c4bbdfSmrg @param[in] id The resource ID 90435c4bbdfSmrg @param[in] type The resource type 90535c4bbdfSmrg @param[in/out] cdata The context object as a void pointer to satisfy the 90635c4bbdfSmrg type FindAllRes 90735c4bbdfSmrg*/ 90835c4bbdfSmrgstatic void 90935c4bbdfSmrgAddResourceSizeValueByResource(void *ptr, XID id, RESTYPE type, void *cdata) 91035c4bbdfSmrg{ 91135c4bbdfSmrg ConstructResourceBytesCtx *ctx = cdata; 91235c4bbdfSmrg xXResResourceIdSpec *spec = ctx->curSpec; 91335c4bbdfSmrg 91435c4bbdfSmrg if ((!spec->type || spec->type == type) && 91535c4bbdfSmrg (!spec->resource || spec->resource == id)) { 91635c4bbdfSmrg AddResourceSizeValue(ptr, id, type, ctx); 91735c4bbdfSmrg } 91835c4bbdfSmrg} 91935c4bbdfSmrg 92035c4bbdfSmrg/** @brief Add all resources of the client into the result buffer 92135c4bbdfSmrg disregarding all those specifications that specify the 92235c4bbdfSmrg resource by its ID. Those are handled by 92335c4bbdfSmrg ConstructResourceBytesByResource 92435c4bbdfSmrg 92535c4bbdfSmrg @see ConstructResourceBytesByResource 92635c4bbdfSmrg 92735c4bbdfSmrg @param[in] aboutClient Which client is being considered 92835c4bbdfSmrg @param[in/out] ctx The context that contains the resource id 92935c4bbdfSmrg specifications as well as the result buffer 93035c4bbdfSmrg*/ 93135c4bbdfSmrgstatic void 93235c4bbdfSmrgConstructClientResourceBytes(ClientPtr aboutClient, 93335c4bbdfSmrg ConstructResourceBytesCtx *ctx) 93435c4bbdfSmrg{ 93535c4bbdfSmrg int specIdx; 93635c4bbdfSmrg for (specIdx = 0; specIdx < ctx->numSpecs; ++specIdx) { 93735c4bbdfSmrg xXResResourceIdSpec* spec = ctx->specs + specIdx; 93835c4bbdfSmrg if (spec->resource) { 93935c4bbdfSmrg /* these specs are handled elsewhere */ 94035c4bbdfSmrg } else if (spec->type) { 94135c4bbdfSmrg ctx->resType = spec->type; 94235c4bbdfSmrg FindClientResourcesByType(aboutClient, spec->type, 94335c4bbdfSmrg AddResourceSizeValueWithResType, ctx); 94435c4bbdfSmrg } else { 94535c4bbdfSmrg FindAllClientResources(aboutClient, AddResourceSizeValue, ctx); 94635c4bbdfSmrg } 94735c4bbdfSmrg } 94835c4bbdfSmrg} 94935c4bbdfSmrg 95035c4bbdfSmrg/** @brief Add the sizes of all such resources that can are specified by 95135c4bbdfSmrg their ID in the resource id specification. The scan can 95235c4bbdfSmrg by limited to a client with the aboutClient parameter 95335c4bbdfSmrg 95435c4bbdfSmrg @see ConstructResourceBytesByResource 95535c4bbdfSmrg 95635c4bbdfSmrg @param[in] aboutClient Which client is being considered. This may be None 95735c4bbdfSmrg to mean all clients. 95835c4bbdfSmrg @param[in/out] ctx The context that contains the resource id 95935c4bbdfSmrg specifications as well as the result buffer. In 96035c4bbdfSmrg addition this function uses the curSpec field to 96135c4bbdfSmrg keep a pointer to the current resource id 96235c4bbdfSmrg specification in it, which can be used by 96335c4bbdfSmrg AddResourceSizeValueByResource . 96435c4bbdfSmrg*/ 96535c4bbdfSmrgstatic void 96635c4bbdfSmrgConstructResourceBytesByResource(XID aboutClient, ConstructResourceBytesCtx *ctx) 96735c4bbdfSmrg{ 96835c4bbdfSmrg int specIdx; 96935c4bbdfSmrg for (specIdx = 0; specIdx < ctx->numSpecs; ++specIdx) { 97035c4bbdfSmrg xXResResourceIdSpec *spec = ctx->specs + specIdx; 97135c4bbdfSmrg if (spec->resource) { 97235c4bbdfSmrg int cid = CLIENT_ID(spec->resource); 97335c4bbdfSmrg if (cid < currentMaxClients && 97435c4bbdfSmrg (aboutClient == None || cid == aboutClient)) { 97535c4bbdfSmrg ClientPtr client = clients[cid]; 97635c4bbdfSmrg if (client) { 97735c4bbdfSmrg ctx->curSpec = spec; 97835c4bbdfSmrg FindAllClientResources(client, 97935c4bbdfSmrg AddResourceSizeValueByResource, 98035c4bbdfSmrg ctx); 98135c4bbdfSmrg } 98235c4bbdfSmrg } 98335c4bbdfSmrg } 98435c4bbdfSmrg } 98535c4bbdfSmrg} 98635c4bbdfSmrg 98735c4bbdfSmrg/** @brief Build the resource size response for the given client 98835c4bbdfSmrg (or all if not specified) per the parameters set up 98935c4bbdfSmrg in the context object. 99035c4bbdfSmrg 99135c4bbdfSmrg @param[in] aboutClient Which client to consider or None for all clients 99235c4bbdfSmrg @param[in/out] ctx The context object that contains the request as well 99335c4bbdfSmrg as the response buffer. 99435c4bbdfSmrg*/ 99505b261ecSmrgstatic int 99635c4bbdfSmrgConstructResourceBytes(XID aboutClient, 99735c4bbdfSmrg ConstructResourceBytesCtx *ctx) 99835c4bbdfSmrg{ 99935c4bbdfSmrg if (aboutClient) { 100035c4bbdfSmrg int clientIdx = CLIENT_ID(aboutClient); 100135c4bbdfSmrg ClientPtr client = NullClient; 100235c4bbdfSmrg 100335c4bbdfSmrg if ((clientIdx >= currentMaxClients) || !clients[clientIdx]) { 100435c4bbdfSmrg ctx->sendClient->errorValue = aboutClient; 100535c4bbdfSmrg return BadValue; 100635c4bbdfSmrg } 100735c4bbdfSmrg 100835c4bbdfSmrg client = clients[clientIdx]; 100935c4bbdfSmrg 101035c4bbdfSmrg ConstructClientResourceBytes(client, ctx); 101135c4bbdfSmrg ConstructResourceBytesByResource(aboutClient, ctx); 101235c4bbdfSmrg } else { 101335c4bbdfSmrg int clientIdx; 101435c4bbdfSmrg 101535c4bbdfSmrg ConstructClientResourceBytes(NULL, ctx); 101635c4bbdfSmrg 101735c4bbdfSmrg for (clientIdx = 0; clientIdx < currentMaxClients; ++clientIdx) { 101835c4bbdfSmrg ClientPtr client = clients[clientIdx]; 101935c4bbdfSmrg 102035c4bbdfSmrg if (client) { 102135c4bbdfSmrg ConstructClientResourceBytes(client, ctx); 102235c4bbdfSmrg } 102335c4bbdfSmrg } 102435c4bbdfSmrg 102535c4bbdfSmrg ConstructResourceBytesByResource(None, ctx); 102635c4bbdfSmrg } 102735c4bbdfSmrg 102835c4bbdfSmrg 102935c4bbdfSmrg return ctx->status; 103035c4bbdfSmrg} 103135c4bbdfSmrg 103235c4bbdfSmrg/** @brief Implements the XResQueryResourceBytes of XResProto v1.2 */ 103335c4bbdfSmrgstatic int 103435c4bbdfSmrgProcXResQueryResourceBytes (ClientPtr client) 103535c4bbdfSmrg{ 103635c4bbdfSmrg REQUEST(xXResQueryResourceBytesReq); 103735c4bbdfSmrg 103835c4bbdfSmrg int rc; 103935c4bbdfSmrg ConstructResourceBytesCtx ctx; 104035c4bbdfSmrg 104135c4bbdfSmrg REQUEST_AT_LEAST_SIZE(xXResQueryResourceBytesReq); 104235c4bbdfSmrg REQUEST_FIXED_SIZE(xXResQueryResourceBytesReq, 104335c4bbdfSmrg stuff->numSpecs * sizeof(ctx.specs[0])); 104435c4bbdfSmrg 104535c4bbdfSmrg if (!InitConstructResourceBytesCtx(&ctx, client, 104635c4bbdfSmrg stuff->numSpecs, 104735c4bbdfSmrg (void*) ((char*) stuff + 104835c4bbdfSmrg sz_xXResQueryResourceBytesReq))) { 104935c4bbdfSmrg return BadAlloc; 105035c4bbdfSmrg } 105135c4bbdfSmrg 105235c4bbdfSmrg rc = ConstructResourceBytes(stuff->client, &ctx); 105335c4bbdfSmrg 105435c4bbdfSmrg if (rc == Success) { 105535c4bbdfSmrg xXResQueryResourceBytesReply rep = { 105635c4bbdfSmrg .type = X_Reply, 105735c4bbdfSmrg .sequenceNumber = client->sequence, 105835c4bbdfSmrg .length = bytes_to_int32(ctx.resultBytes), 105935c4bbdfSmrg .numSizes = ctx.numSizes 106035c4bbdfSmrg }; 106135c4bbdfSmrg 106235c4bbdfSmrg if (client->swapped) { 106335c4bbdfSmrg swaps (&rep.sequenceNumber); 106435c4bbdfSmrg swapl (&rep.length); 106535c4bbdfSmrg swapl (&rep.numSizes); 106635c4bbdfSmrg 106735c4bbdfSmrg SwapXResQueryResourceBytes(&ctx.response); 106835c4bbdfSmrg } 106935c4bbdfSmrg 107035c4bbdfSmrg WriteToClient(client, sizeof(rep), &rep); 107135c4bbdfSmrg WriteFragmentsToClient(client, &ctx.response); 107235c4bbdfSmrg } 107335c4bbdfSmrg 107435c4bbdfSmrg DestroyConstructResourceBytesCtx(&ctx); 107535c4bbdfSmrg 107635c4bbdfSmrg return rc; 107735c4bbdfSmrg} 107835c4bbdfSmrg 107935c4bbdfSmrgstatic int 108035c4bbdfSmrgProcResDispatch(ClientPtr client) 108105b261ecSmrg{ 108205b261ecSmrg REQUEST(xReq); 108305b261ecSmrg switch (stuff->data) { 108405b261ecSmrg case X_XResQueryVersion: 108505b261ecSmrg return ProcXResQueryVersion(client); 108605b261ecSmrg case X_XResQueryClients: 108705b261ecSmrg return ProcXResQueryClients(client); 108805b261ecSmrg case X_XResQueryClientResources: 108905b261ecSmrg return ProcXResQueryClientResources(client); 109005b261ecSmrg case X_XResQueryClientPixmapBytes: 109105b261ecSmrg return ProcXResQueryClientPixmapBytes(client); 109235c4bbdfSmrg case X_XResQueryClientIds: 109335c4bbdfSmrg return ProcXResQueryClientIds(client); 109435c4bbdfSmrg case X_XResQueryResourceBytes: 109535c4bbdfSmrg return ProcXResQueryResourceBytes(client); 109605b261ecSmrg default: break; 109705b261ecSmrg } 109805b261ecSmrg 109905b261ecSmrg return BadRequest; 110005b261ecSmrg} 110105b261ecSmrg 110205b261ecSmrgstatic int 110335c4bbdfSmrgSProcXResQueryVersion(ClientPtr client) 110405b261ecSmrg{ 110535c4bbdfSmrg REQUEST_SIZE_MATCH(xXResQueryVersionReq); 110605b261ecSmrg return ProcXResQueryVersion(client); 110705b261ecSmrg} 110805b261ecSmrg 110905b261ecSmrgstatic int 111035c4bbdfSmrgSProcXResQueryClientResources(ClientPtr client) 111105b261ecSmrg{ 111205b261ecSmrg REQUEST(xXResQueryClientResourcesReq); 111335c4bbdfSmrg REQUEST_SIZE_MATCH(xXResQueryClientResourcesReq); 111435c4bbdfSmrg swapl(&stuff->xid); 111505b261ecSmrg return ProcXResQueryClientResources(client); 111605b261ecSmrg} 111705b261ecSmrg 111805b261ecSmrgstatic int 111935c4bbdfSmrgSProcXResQueryClientPixmapBytes(ClientPtr client) 112005b261ecSmrg{ 112105b261ecSmrg REQUEST(xXResQueryClientPixmapBytesReq); 112235c4bbdfSmrg REQUEST_SIZE_MATCH(xXResQueryClientPixmapBytesReq); 112335c4bbdfSmrg swapl(&stuff->xid); 112405b261ecSmrg return ProcXResQueryClientPixmapBytes(client); 112505b261ecSmrg} 112605b261ecSmrg 112735c4bbdfSmrgstatic int 112835c4bbdfSmrgSProcXResQueryClientIds (ClientPtr client) 112935c4bbdfSmrg{ 113035c4bbdfSmrg REQUEST(xXResQueryClientIdsReq); 113135c4bbdfSmrg 113235c4bbdfSmrg REQUEST_AT_LEAST_SIZE (xXResQueryClientIdsReq); 113335c4bbdfSmrg swapl(&stuff->numSpecs); 113435c4bbdfSmrg return ProcXResQueryClientIds(client); 113535c4bbdfSmrg} 113635c4bbdfSmrg 113735c4bbdfSmrg/** @brief Implements the XResQueryResourceBytes of XResProto v1.2. 113835c4bbdfSmrg This variant byteswaps request contents before issuing the 113935c4bbdfSmrg rest of the work to ProcXResQueryResourceBytes */ 114035c4bbdfSmrgstatic int 114135c4bbdfSmrgSProcXResQueryResourceBytes (ClientPtr client) 114235c4bbdfSmrg{ 114335c4bbdfSmrg REQUEST(xXResQueryResourceBytesReq); 114435c4bbdfSmrg int c; 114535c4bbdfSmrg xXResResourceIdSpec *specs = (void*) ((char*) stuff + sizeof(*stuff)); 114635c4bbdfSmrg 114735c4bbdfSmrg swapl(&stuff->numSpecs); 114835c4bbdfSmrg REQUEST_AT_LEAST_SIZE(xXResQueryResourceBytesReq); 114935c4bbdfSmrg REQUEST_FIXED_SIZE(xXResQueryResourceBytesReq, 115035c4bbdfSmrg stuff->numSpecs * sizeof(specs[0])); 115135c4bbdfSmrg 115235c4bbdfSmrg for (c = 0; c < stuff->numSpecs; ++c) { 115335c4bbdfSmrg SwapXResResourceIdSpec(specs + c); 115435c4bbdfSmrg } 115535c4bbdfSmrg 115635c4bbdfSmrg return ProcXResQueryResourceBytes(client); 115735c4bbdfSmrg} 115835c4bbdfSmrg 115905b261ecSmrgstatic int 116005b261ecSmrgSProcResDispatch (ClientPtr client) 116105b261ecSmrg{ 116205b261ecSmrg REQUEST(xReq); 116335c4bbdfSmrg swaps(&stuff->length); 116405b261ecSmrg 116505b261ecSmrg switch (stuff->data) { 116605b261ecSmrg case X_XResQueryVersion: 116705b261ecSmrg return SProcXResQueryVersion(client); 116835c4bbdfSmrg case X_XResQueryClients: /* nothing to swap */ 116905b261ecSmrg return ProcXResQueryClients(client); 117005b261ecSmrg case X_XResQueryClientResources: 117105b261ecSmrg return SProcXResQueryClientResources(client); 117205b261ecSmrg case X_XResQueryClientPixmapBytes: 117305b261ecSmrg return SProcXResQueryClientPixmapBytes(client); 117435c4bbdfSmrg case X_XResQueryClientIds: 117535c4bbdfSmrg return SProcXResQueryClientIds(client); 117635c4bbdfSmrg case X_XResQueryResourceBytes: 117735c4bbdfSmrg return SProcXResQueryResourceBytes(client); 117805b261ecSmrg default: break; 117905b261ecSmrg } 118005b261ecSmrg 118105b261ecSmrg return BadRequest; 118205b261ecSmrg} 118305b261ecSmrg 118405b261ecSmrgvoid 118535c4bbdfSmrgResExtensionInit(void) 118605b261ecSmrg{ 118705b261ecSmrg (void) AddExtension(XRES_NAME, 0, 0, 118835c4bbdfSmrg ProcResDispatch, SProcResDispatch, 118935c4bbdfSmrg NULL, StandardMinorOpcode); 119005b261ecSmrg} 1191