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 755a112b11Smrg handling cross-references */ 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 2777e31ba66Smrgstatic CARD32 2787e31ba66SmrgresourceTypeAtom(int i) 2797e31ba66Smrg{ 2807e31ba66Smrg CARD32 ret; 2817e31ba66Smrg 2827e31ba66Smrg const char *name = LookupResourceName(i); 2837e31ba66Smrg if (strcmp(name, XREGISTRY_UNKNOWN)) 2847e31ba66Smrg ret = MakeAtom(name, strlen(name), TRUE); 2857e31ba66Smrg else { 2867e31ba66Smrg char buf[40]; 2877e31ba66Smrg 2887e31ba66Smrg snprintf(buf, sizeof(buf), "Unregistered resource %i", i + 1); 2897e31ba66Smrg ret = MakeAtom(buf, strlen(buf), TRUE); 2907e31ba66Smrg } 2917e31ba66Smrg 2927e31ba66Smrg return ret; 2937e31ba66Smrg} 2947e31ba66Smrg 29505b261ecSmrgstatic int 29635c4bbdfSmrgProcXResQueryClientResources(ClientPtr client) 29705b261ecSmrg{ 29805b261ecSmrg REQUEST(xXResQueryClientResourcesReq); 29905b261ecSmrg xXResQueryClientResourcesReply rep; 30005b261ecSmrg int i, clientID, num_types; 30105b261ecSmrg int *counts; 30205b261ecSmrg 30305b261ecSmrg REQUEST_SIZE_MATCH(xXResQueryClientResourcesReq); 30405b261ecSmrg 30505b261ecSmrg clientID = CLIENT_ID(stuff->xid); 30605b261ecSmrg 30735c4bbdfSmrg if ((clientID >= currentMaxClients) || !clients[clientID]) { 30805b261ecSmrg client->errorValue = stuff->xid; 30905b261ecSmrg return BadValue; 31005b261ecSmrg } 31105b261ecSmrg 3126747b715Smrg counts = calloc(lastResourceType + 1, sizeof(int)); 31305b261ecSmrg 31405b261ecSmrg FindAllClientResources(clients[clientID], ResFindAllRes, counts); 31505b261ecSmrg 31605b261ecSmrg num_types = 0; 31705b261ecSmrg 31835c4bbdfSmrg for (i = 0; i <= lastResourceType; i++) { 31935c4bbdfSmrg if (counts[i]) 32035c4bbdfSmrg num_types++; 32105b261ecSmrg } 32205b261ecSmrg 32335c4bbdfSmrg rep = (xXResQueryClientResourcesReply) { 32435c4bbdfSmrg .type = X_Reply, 32535c4bbdfSmrg .sequenceNumber = client->sequence, 32635c4bbdfSmrg .length = bytes_to_int32(num_types * sz_xXResType), 32735c4bbdfSmrg .num_types = num_types 32835c4bbdfSmrg }; 32905b261ecSmrg if (client->swapped) { 33035c4bbdfSmrg swaps(&rep.sequenceNumber); 33135c4bbdfSmrg swapl(&rep.length); 33235c4bbdfSmrg swapl(&rep.num_types); 33335c4bbdfSmrg } 33405b261ecSmrg 33535c4bbdfSmrg WriteToClient(client, sizeof(xXResQueryClientResourcesReply), &rep); 33605b261ecSmrg 33735c4bbdfSmrg if (num_types) { 33805b261ecSmrg xXResType scratch; 33905b261ecSmrg 34035c4bbdfSmrg for (i = 0; i < lastResourceType; i++) { 34135c4bbdfSmrg if (!counts[i]) 34235c4bbdfSmrg continue; 34305b261ecSmrg 3447e31ba66Smrg scratch.resource_type = resourceTypeAtom(i + 1); 34505b261ecSmrg scratch.count = counts[i]; 34605b261ecSmrg 34735c4bbdfSmrg if (client->swapped) { 34835c4bbdfSmrg swapl(&scratch.resource_type); 34935c4bbdfSmrg swapl(&scratch.count); 35005b261ecSmrg } 35135c4bbdfSmrg WriteToClient(client, sz_xXResType, &scratch); 35205b261ecSmrg } 35305b261ecSmrg } 35405b261ecSmrg 3556747b715Smrg free(counts); 35635c4bbdfSmrg 3576747b715Smrg return Success; 35805b261ecSmrg} 35905b261ecSmrg 36035c4bbdfSmrgstatic void 36135c4bbdfSmrgResFindResourcePixmaps(void *value, XID id, RESTYPE type, void *cdata) 36205b261ecSmrg{ 36335c4bbdfSmrg SizeType sizeFunc = GetResourceTypeSizeFunc(type); 36435c4bbdfSmrg ResourceSizeRec size = { 0, 0, 0 }; 36535c4bbdfSmrg unsigned long *bytes = cdata; 36605b261ecSmrg 36735c4bbdfSmrg sizeFunc(value, id, &size); 36835c4bbdfSmrg *bytes += size.pixmapRefSize; 36905b261ecSmrg} 37005b261ecSmrg 37105b261ecSmrgstatic int 37235c4bbdfSmrgProcXResQueryClientPixmapBytes(ClientPtr client) 37305b261ecSmrg{ 37405b261ecSmrg REQUEST(xXResQueryClientPixmapBytesReq); 37505b261ecSmrg xXResQueryClientPixmapBytesReply rep; 37605b261ecSmrg int clientID; 37705b261ecSmrg unsigned long bytes; 37805b261ecSmrg 37905b261ecSmrg REQUEST_SIZE_MATCH(xXResQueryClientPixmapBytesReq); 38005b261ecSmrg 38105b261ecSmrg clientID = CLIENT_ID(stuff->xid); 38205b261ecSmrg 38335c4bbdfSmrg if ((clientID >= currentMaxClients) || !clients[clientID]) { 38405b261ecSmrg client->errorValue = stuff->xid; 38505b261ecSmrg return BadValue; 38605b261ecSmrg } 38705b261ecSmrg 38805b261ecSmrg bytes = 0; 38905b261ecSmrg 3907e31ba66Smrg FindAllClientResources(clients[clientID], ResFindResourcePixmaps, 3917e31ba66Smrg (void *) (&bytes)); 39205b261ecSmrg 39335c4bbdfSmrg rep = (xXResQueryClientPixmapBytesReply) { 39435c4bbdfSmrg .type = X_Reply, 39535c4bbdfSmrg .sequenceNumber = client->sequence, 39635c4bbdfSmrg .length = 0, 39735c4bbdfSmrg .bytes = bytes, 39805b261ecSmrg#ifdef _XSERVER64 39935c4bbdfSmrg .bytes_overflow = bytes >> 32 40005b261ecSmrg#else 40135c4bbdfSmrg .bytes_overflow = 0 40205b261ecSmrg#endif 40335c4bbdfSmrg }; 40405b261ecSmrg if (client->swapped) { 40535c4bbdfSmrg swaps(&rep.sequenceNumber); 40635c4bbdfSmrg swapl(&rep.length); 40735c4bbdfSmrg swapl(&rep.bytes); 40835c4bbdfSmrg swapl(&rep.bytes_overflow); 40905b261ecSmrg } 41035c4bbdfSmrg WriteToClient(client, sizeof(xXResQueryClientPixmapBytesReply), &rep); 41105b261ecSmrg 4126747b715Smrg return Success; 41305b261ecSmrg} 41405b261ecSmrg 41535c4bbdfSmrg/** @brief Finds out if a client's information need to be put into the 41635c4bbdfSmrg response; marks client having been handled, if that is the case. 41735c4bbdfSmrg 41835c4bbdfSmrg @param client The client to send information about 41935c4bbdfSmrg @param mask The request mask (0 to send everything, otherwise a 42035c4bbdfSmrg bitmask of X_XRes*Mask) 42135c4bbdfSmrg @param ctx The context record that tells which clients and id types 42235c4bbdfSmrg have been already handled 42335c4bbdfSmrg @param sendMask Which id type are we now considering. One of X_XRes*Mask. 42435c4bbdfSmrg 42535c4bbdfSmrg @return Returns TRUE if the client information needs to be on the 42635c4bbdfSmrg response, otherwise FALSE. 42735c4bbdfSmrg*/ 42835c4bbdfSmrgstatic Bool 42935c4bbdfSmrgWillConstructMask(ClientPtr client, CARD32 mask, 43035c4bbdfSmrg ConstructClientIdCtx *ctx, int sendMask) 43135c4bbdfSmrg{ 43235c4bbdfSmrg if ((!mask || (mask & sendMask)) 43335c4bbdfSmrg && !(ctx->sentClientMasks[client->index] & sendMask)) { 43435c4bbdfSmrg ctx->sentClientMasks[client->index] |= sendMask; 43535c4bbdfSmrg return TRUE; 43635c4bbdfSmrg } else { 43735c4bbdfSmrg return FALSE; 43835c4bbdfSmrg } 43935c4bbdfSmrg} 44035c4bbdfSmrg 44135c4bbdfSmrg/** @brief Constructs a response about a single client, based on a certain 44235c4bbdfSmrg client id spec 44335c4bbdfSmrg 44435c4bbdfSmrg @param sendClient Which client wishes to receive this answer. Used for 4455a112b11Smrg byte endianness. 44635c4bbdfSmrg @param client Which client are we considering. 44735c4bbdfSmrg @param mask The client id spec mask indicating which information 44835c4bbdfSmrg we want about this client. 44935c4bbdfSmrg @param ctx The context record containing the constructed response 45035c4bbdfSmrg and information on which clients and masks have been 45135c4bbdfSmrg already handled. 45235c4bbdfSmrg 45335c4bbdfSmrg @return Return TRUE if everything went OK, otherwise FALSE which indicates 45435c4bbdfSmrg a memory allocation problem. 45535c4bbdfSmrg*/ 45635c4bbdfSmrgstatic Bool 45735c4bbdfSmrgConstructClientIdValue(ClientPtr sendClient, ClientPtr client, CARD32 mask, 45835c4bbdfSmrg ConstructClientIdCtx *ctx) 45935c4bbdfSmrg{ 46035c4bbdfSmrg xXResClientIdValue rep; 46135c4bbdfSmrg 46235c4bbdfSmrg rep.spec.client = client->clientAsMask; 46335c4bbdfSmrg if (client->swapped) { 46435c4bbdfSmrg swapl (&rep.spec.client); 46535c4bbdfSmrg } 46635c4bbdfSmrg 46735c4bbdfSmrg if (WillConstructMask(client, mask, ctx, X_XResClientXIDMask)) { 46835c4bbdfSmrg void *ptr = AddFragment(&ctx->response, sizeof(rep)); 46935c4bbdfSmrg if (!ptr) { 47035c4bbdfSmrg return FALSE; 47135c4bbdfSmrg } 47235c4bbdfSmrg 47335c4bbdfSmrg rep.spec.mask = X_XResClientXIDMask; 47435c4bbdfSmrg rep.length = 0; 47535c4bbdfSmrg if (sendClient->swapped) { 47635c4bbdfSmrg swapl (&rep.spec.mask); 47735c4bbdfSmrg /* swapl (&rep.length, n); - not required for rep.length = 0 */ 47835c4bbdfSmrg } 47935c4bbdfSmrg 48035c4bbdfSmrg memcpy(ptr, &rep, sizeof(rep)); 48135c4bbdfSmrg 48235c4bbdfSmrg ctx->resultBytes += sizeof(rep); 48335c4bbdfSmrg ++ctx->numIds; 48435c4bbdfSmrg } 48535c4bbdfSmrg if (WillConstructMask(client, mask, ctx, X_XResLocalClientPIDMask)) { 48635c4bbdfSmrg pid_t pid = GetClientPid(client); 48735c4bbdfSmrg 48835c4bbdfSmrg if (pid != -1) { 48935c4bbdfSmrg void *ptr = AddFragment(&ctx->response, 49035c4bbdfSmrg sizeof(rep) + sizeof(CARD32)); 49135c4bbdfSmrg CARD32 *value = (void*) ((char*) ptr + sizeof(rep)); 49235c4bbdfSmrg 49335c4bbdfSmrg if (!ptr) { 49435c4bbdfSmrg return FALSE; 49535c4bbdfSmrg } 49635c4bbdfSmrg 49735c4bbdfSmrg rep.spec.mask = X_XResLocalClientPIDMask; 49835c4bbdfSmrg rep.length = 4; 49935c4bbdfSmrg 50035c4bbdfSmrg if (sendClient->swapped) { 50135c4bbdfSmrg swapl (&rep.spec.mask); 50235c4bbdfSmrg swapl (&rep.length); 50335c4bbdfSmrg } 50435c4bbdfSmrg 50535c4bbdfSmrg if (sendClient->swapped) { 50635c4bbdfSmrg swapl (value); 50735c4bbdfSmrg } 50835c4bbdfSmrg memcpy(ptr, &rep, sizeof(rep)); 50935c4bbdfSmrg *value = pid; 51035c4bbdfSmrg 51135c4bbdfSmrg ctx->resultBytes += sizeof(rep) + sizeof(CARD32); 51235c4bbdfSmrg ++ctx->numIds; 51335c4bbdfSmrg } 51435c4bbdfSmrg } 51535c4bbdfSmrg 51635c4bbdfSmrg /* memory allocation errors earlier may return with FALSE */ 51735c4bbdfSmrg return TRUE; 51835c4bbdfSmrg} 51935c4bbdfSmrg 52035c4bbdfSmrg/** @brief Constructs a response about all clients, based on a client id specs 52135c4bbdfSmrg 52235c4bbdfSmrg @param client Which client which we are constructing the response for. 52335c4bbdfSmrg @param numSpecs Number of client id specs in specs 52435c4bbdfSmrg @param specs Client id specs 52535c4bbdfSmrg 52635c4bbdfSmrg @return Return Success if everything went OK, otherwise a Bad* (currently 52735c4bbdfSmrg BadAlloc or BadValue) 52835c4bbdfSmrg*/ 52935c4bbdfSmrgstatic int 53035c4bbdfSmrgConstructClientIds(ClientPtr client, 53135c4bbdfSmrg int numSpecs, xXResClientIdSpec* specs, 53235c4bbdfSmrg ConstructClientIdCtx *ctx) 53335c4bbdfSmrg{ 53435c4bbdfSmrg int specIdx; 53535c4bbdfSmrg 53635c4bbdfSmrg for (specIdx = 0; specIdx < numSpecs; ++specIdx) { 53735c4bbdfSmrg if (specs[specIdx].client == 0) { 53835c4bbdfSmrg int c; 53935c4bbdfSmrg for (c = 0; c < currentMaxClients; ++c) { 54035c4bbdfSmrg if (clients[c]) { 54135c4bbdfSmrg if (!ConstructClientIdValue(client, clients[c], 54235c4bbdfSmrg specs[specIdx].mask, ctx)) { 54335c4bbdfSmrg return BadAlloc; 54435c4bbdfSmrg } 54535c4bbdfSmrg } 54635c4bbdfSmrg } 54735c4bbdfSmrg } else { 54835c4bbdfSmrg int clientID = CLIENT_ID(specs[specIdx].client); 54935c4bbdfSmrg 55035c4bbdfSmrg if ((clientID < currentMaxClients) && clients[clientID]) { 55135c4bbdfSmrg if (!ConstructClientIdValue(client, clients[clientID], 55235c4bbdfSmrg specs[specIdx].mask, ctx)) { 55335c4bbdfSmrg return BadAlloc; 55435c4bbdfSmrg } 55535c4bbdfSmrg } 55635c4bbdfSmrg } 55735c4bbdfSmrg } 55835c4bbdfSmrg 55935c4bbdfSmrg /* memory allocation errors earlier may return with BadAlloc */ 56035c4bbdfSmrg return Success; 56135c4bbdfSmrg} 56235c4bbdfSmrg 56335c4bbdfSmrg/** @brief Response to XResQueryClientIds request introduced in XResProto v1.2 56435c4bbdfSmrg 56535c4bbdfSmrg @param client Which client which we are constructing the response for. 56635c4bbdfSmrg 56735c4bbdfSmrg @return Returns the value returned from ConstructClientIds with the same 56835c4bbdfSmrg semantics 56935c4bbdfSmrg*/ 57035c4bbdfSmrgstatic int 57135c4bbdfSmrgProcXResQueryClientIds (ClientPtr client) 57235c4bbdfSmrg{ 57335c4bbdfSmrg REQUEST(xXResQueryClientIdsReq); 57435c4bbdfSmrg 57535c4bbdfSmrg xXResClientIdSpec *specs = (void*) ((char*) stuff + sizeof(*stuff)); 57635c4bbdfSmrg int rc; 57735c4bbdfSmrg ConstructClientIdCtx ctx; 57835c4bbdfSmrg 57935c4bbdfSmrg InitConstructClientIdCtx(&ctx); 58035c4bbdfSmrg 58135c4bbdfSmrg REQUEST_AT_LEAST_SIZE(xXResQueryClientIdsReq); 58235c4bbdfSmrg REQUEST_FIXED_SIZE(xXResQueryClientIdsReq, 58335c4bbdfSmrg stuff->numSpecs * sizeof(specs[0])); 58435c4bbdfSmrg 58535c4bbdfSmrg rc = ConstructClientIds(client, stuff->numSpecs, specs, &ctx); 58635c4bbdfSmrg 58735c4bbdfSmrg if (rc == Success) { 58835c4bbdfSmrg xXResQueryClientIdsReply rep = { 58935c4bbdfSmrg .type = X_Reply, 59035c4bbdfSmrg .sequenceNumber = client->sequence, 59135c4bbdfSmrg .length = bytes_to_int32(ctx.resultBytes), 59235c4bbdfSmrg .numIds = ctx.numIds 59335c4bbdfSmrg }; 59435c4bbdfSmrg 59535c4bbdfSmrg assert((ctx.resultBytes & 3) == 0); 59635c4bbdfSmrg 59735c4bbdfSmrg if (client->swapped) { 59835c4bbdfSmrg swaps (&rep.sequenceNumber); 59935c4bbdfSmrg swapl (&rep.length); 60035c4bbdfSmrg swapl (&rep.numIds); 60135c4bbdfSmrg } 60235c4bbdfSmrg 60335c4bbdfSmrg WriteToClient(client, sizeof(rep), &rep); 60435c4bbdfSmrg WriteFragmentsToClient(client, &ctx.response); 60535c4bbdfSmrg } 60635c4bbdfSmrg 60735c4bbdfSmrg DestroyConstructClientIdCtx(&ctx); 60835c4bbdfSmrg 60935c4bbdfSmrg return rc; 61035c4bbdfSmrg} 61135c4bbdfSmrg 6125a112b11Smrg/** @brief Swaps xXResResourceIdSpec endianness */ 61335c4bbdfSmrgstatic void 61435c4bbdfSmrgSwapXResResourceIdSpec(xXResResourceIdSpec *spec) 61535c4bbdfSmrg{ 61635c4bbdfSmrg swapl(&spec->resource); 61735c4bbdfSmrg swapl(&spec->type); 61835c4bbdfSmrg} 61935c4bbdfSmrg 6205a112b11Smrg/** @brief Swaps xXResResourceSizeSpec endianness */ 62135c4bbdfSmrgstatic void 62235c4bbdfSmrgSwapXResResourceSizeSpec(xXResResourceSizeSpec *size) 62335c4bbdfSmrg{ 62435c4bbdfSmrg SwapXResResourceIdSpec(&size->spec); 62535c4bbdfSmrg swapl(&size->bytes); 62635c4bbdfSmrg swapl(&size->refCount); 62735c4bbdfSmrg swapl(&size->useCount); 62835c4bbdfSmrg} 62935c4bbdfSmrg 6305a112b11Smrg/** @brief Swaps xXResResourceSizeValue endianness */ 63135c4bbdfSmrgstatic void 63235c4bbdfSmrgSwapXResResourceSizeValue(xXResResourceSizeValue *rep) 63335c4bbdfSmrg{ 63435c4bbdfSmrg SwapXResResourceSizeSpec(&rep->size); 63535c4bbdfSmrg swapl(&rep->numCrossReferences); 63635c4bbdfSmrg} 63735c4bbdfSmrg 63835c4bbdfSmrg/** @brief Swaps the response bytes */ 63935c4bbdfSmrgstatic void 64035c4bbdfSmrgSwapXResQueryResourceBytes(struct xorg_list *response) 64135c4bbdfSmrg{ 64235c4bbdfSmrg struct xorg_list *it = response->next; 64335c4bbdfSmrg int c; 64435c4bbdfSmrg 64535c4bbdfSmrg while (it != response) { 64635c4bbdfSmrg xXResResourceSizeValue *value = FRAGMENT_DATA(it); 64735c4bbdfSmrg it = it->next; 64835c4bbdfSmrg for (c = 0; c < value->numCrossReferences; ++c) { 64935c4bbdfSmrg xXResResourceSizeSpec *spec = FRAGMENT_DATA(it); 65035c4bbdfSmrg SwapXResResourceSizeSpec(spec); 65135c4bbdfSmrg it = it->next; 65235c4bbdfSmrg } 65335c4bbdfSmrg SwapXResResourceSizeValue(value); 65435c4bbdfSmrg } 65535c4bbdfSmrg} 65635c4bbdfSmrg 65735c4bbdfSmrg/** @brief Adds xXResResourceSizeSpec describing a resource's size into 65835c4bbdfSmrg the buffer contained in the context. The resource is considered 65935c4bbdfSmrg to be a subresource. 66035c4bbdfSmrg 66135c4bbdfSmrg @see AddResourceSizeValue 66235c4bbdfSmrg 66335c4bbdfSmrg @param[in] value The X resource object on which to add information 66435c4bbdfSmrg about to the buffer 66535c4bbdfSmrg @param[in] id The ID of the X resource 66635c4bbdfSmrg @param[in] type The type of the X resource 66735c4bbdfSmrg @param[in/out] cdata The context object of type ConstructResourceBytesCtx. 66835c4bbdfSmrg Void pointer type is used here to satisfy the type 66935c4bbdfSmrg FindRes 67035c4bbdfSmrg*/ 67135c4bbdfSmrgstatic void 67235c4bbdfSmrgAddSubResourceSizeSpec(void *value, 67335c4bbdfSmrg XID id, 67435c4bbdfSmrg RESTYPE type, 67535c4bbdfSmrg void *cdata) 67635c4bbdfSmrg{ 67735c4bbdfSmrg ConstructResourceBytesCtx *ctx = cdata; 67835c4bbdfSmrg 67935c4bbdfSmrg if (ctx->status == Success) { 68035c4bbdfSmrg xXResResourceSizeSpec **prevCrossRef = 68135c4bbdfSmrg ht_find(ctx->visitedSubResources, &value); 68235c4bbdfSmrg if (!prevCrossRef) { 68335c4bbdfSmrg Bool ok = TRUE; 68435c4bbdfSmrg xXResResourceSizeSpec *crossRef = 68535c4bbdfSmrg AddFragment(&ctx->response, sizeof(xXResResourceSizeSpec)); 68635c4bbdfSmrg ok = ok && crossRef != NULL; 68735c4bbdfSmrg if (ok) { 68835c4bbdfSmrg xXResResourceSizeSpec **p; 68935c4bbdfSmrg p = ht_add(ctx->visitedSubResources, &value); 69035c4bbdfSmrg if (!p) { 69135c4bbdfSmrg ok = FALSE; 69235c4bbdfSmrg } else { 69335c4bbdfSmrg *p = crossRef; 69435c4bbdfSmrg } 69535c4bbdfSmrg } 69635c4bbdfSmrg if (!ok) { 69735c4bbdfSmrg ctx->status = BadAlloc; 69835c4bbdfSmrg } else { 69935c4bbdfSmrg SizeType sizeFunc = GetResourceTypeSizeFunc(type); 70035c4bbdfSmrg ResourceSizeRec size = { 0, 0, 0 }; 70135c4bbdfSmrg sizeFunc(value, id, &size); 70235c4bbdfSmrg 70335c4bbdfSmrg crossRef->spec.resource = id; 7047e31ba66Smrg crossRef->spec.type = resourceTypeAtom(type); 70535c4bbdfSmrg crossRef->bytes = size.resourceSize; 70635c4bbdfSmrg crossRef->refCount = size.refCnt; 70735c4bbdfSmrg crossRef->useCount = 1; 70835c4bbdfSmrg 70935c4bbdfSmrg ++ctx->sizeValue->numCrossReferences; 71035c4bbdfSmrg 71135c4bbdfSmrg ctx->resultBytes += sizeof(*crossRef); 71235c4bbdfSmrg } 71335c4bbdfSmrg } else { 71435c4bbdfSmrg /* if we have visited the subresource earlier (from current parent 71535c4bbdfSmrg resource), just increase its use count by one */ 71635c4bbdfSmrg ++(*prevCrossRef)->useCount; 71735c4bbdfSmrg } 71835c4bbdfSmrg } 71935c4bbdfSmrg} 72035c4bbdfSmrg 72135c4bbdfSmrg/** @brief Adds xXResResourceSizeValue describing a resource's size into 72235c4bbdfSmrg the buffer contained in the context. In addition, the 72335c4bbdfSmrg subresources are iterated and added as xXResResourceSizeSpec's 72435c4bbdfSmrg by using AddSubResourceSizeSpec 72535c4bbdfSmrg 72635c4bbdfSmrg @see AddSubResourceSizeSpec 72735c4bbdfSmrg 72835c4bbdfSmrg @param[in] value The X resource object on which to add information 72935c4bbdfSmrg about to the buffer 73035c4bbdfSmrg @param[in] id The ID of the X resource 73135c4bbdfSmrg @param[in] type The type of the X resource 73235c4bbdfSmrg @param[in/out] cdata The context object of type ConstructResourceBytesCtx. 73335c4bbdfSmrg Void pointer type is used here to satisfy the type 73435c4bbdfSmrg FindRes 73535c4bbdfSmrg*/ 73635c4bbdfSmrgstatic void 73735c4bbdfSmrgAddResourceSizeValue(void *ptr, XID id, RESTYPE type, void *cdata) 73835c4bbdfSmrg{ 73935c4bbdfSmrg ConstructResourceBytesCtx *ctx = cdata; 74035c4bbdfSmrg if (ctx->status == Success && 74135c4bbdfSmrg !ht_find(ctx->visitedResources, &id)) { 74235c4bbdfSmrg Bool ok = TRUE; 74335c4bbdfSmrg HashTable ht; 74435c4bbdfSmrg HtGenericHashSetupRec htSetup = { 74535c4bbdfSmrg .keySize = sizeof(void*) 74635c4bbdfSmrg }; 74735c4bbdfSmrg 74835c4bbdfSmrg /* it doesn't matter that we don't undo the work done here 74935c4bbdfSmrg * immediately. All but ht_init will be undone at the end 75035c4bbdfSmrg * of the request and there can happen no failure after 75135c4bbdfSmrg * ht_init, so we don't need to clean it up here in any 75235c4bbdfSmrg * special way */ 75335c4bbdfSmrg 75435c4bbdfSmrg xXResResourceSizeValue *value = 75535c4bbdfSmrg AddFragment(&ctx->response, sizeof(xXResResourceSizeValue)); 75635c4bbdfSmrg if (!value) { 75735c4bbdfSmrg ok = FALSE; 75835c4bbdfSmrg } 75935c4bbdfSmrg ok = ok && ht_add(ctx->visitedResources, &id); 76035c4bbdfSmrg if (ok) { 76135c4bbdfSmrg ht = ht_create(htSetup.keySize, 76235c4bbdfSmrg sizeof(xXResResourceSizeSpec*), 76335c4bbdfSmrg ht_generic_hash, ht_generic_compare, 76435c4bbdfSmrg &htSetup); 76535c4bbdfSmrg ok = ok && ht; 76635c4bbdfSmrg } 76735c4bbdfSmrg 76835c4bbdfSmrg if (!ok) { 76935c4bbdfSmrg ctx->status = BadAlloc; 77035c4bbdfSmrg } else { 77135c4bbdfSmrg SizeType sizeFunc = GetResourceTypeSizeFunc(type); 77235c4bbdfSmrg ResourceSizeRec size = { 0, 0, 0 }; 77335c4bbdfSmrg 77435c4bbdfSmrg sizeFunc(ptr, id, &size); 77535c4bbdfSmrg 77635c4bbdfSmrg value->size.spec.resource = id; 7777e31ba66Smrg value->size.spec.type = resourceTypeAtom(type); 77835c4bbdfSmrg value->size.bytes = size.resourceSize; 77935c4bbdfSmrg value->size.refCount = size.refCnt; 78035c4bbdfSmrg value->size.useCount = 1; 78135c4bbdfSmrg value->numCrossReferences = 0; 78235c4bbdfSmrg 78335c4bbdfSmrg ctx->sizeValue = value; 78435c4bbdfSmrg ctx->visitedSubResources = ht; 78535c4bbdfSmrg FindSubResources(ptr, type, AddSubResourceSizeSpec, ctx); 78635c4bbdfSmrg ctx->visitedSubResources = NULL; 78735c4bbdfSmrg ctx->sizeValue = NULL; 78835c4bbdfSmrg 78935c4bbdfSmrg ctx->resultBytes += sizeof(*value); 79035c4bbdfSmrg ++ctx->numSizes; 79135c4bbdfSmrg 79235c4bbdfSmrg ht_destroy(ht); 79335c4bbdfSmrg } 79435c4bbdfSmrg } 79535c4bbdfSmrg} 79635c4bbdfSmrg 79735c4bbdfSmrg/** @brief A variant of AddResourceSizeValue that passes the resource type 79835c4bbdfSmrg through the context object to satisfy the type FindResType 79935c4bbdfSmrg 80035c4bbdfSmrg @see AddResourceSizeValue 80135c4bbdfSmrg 80235c4bbdfSmrg @param[in] ptr The resource 80335c4bbdfSmrg @param[in] id The resource ID 80435c4bbdfSmrg @param[in/out] cdata The context object that contains the resource type 80535c4bbdfSmrg*/ 80635c4bbdfSmrgstatic void 80735c4bbdfSmrgAddResourceSizeValueWithResType(void *ptr, XID id, void *cdata) 80835c4bbdfSmrg{ 80935c4bbdfSmrg ConstructResourceBytesCtx *ctx = cdata; 81035c4bbdfSmrg AddResourceSizeValue(ptr, id, ctx->resType, cdata); 81135c4bbdfSmrg} 81235c4bbdfSmrg 81335c4bbdfSmrg/** @brief Adds the information of a resource into the buffer if it matches 81435c4bbdfSmrg the match condition. 81535c4bbdfSmrg 81635c4bbdfSmrg @see AddResourceSizeValue 81735c4bbdfSmrg 81835c4bbdfSmrg @param[in] ptr The resource 81935c4bbdfSmrg @param[in] id The resource ID 82035c4bbdfSmrg @param[in] type The resource type 82135c4bbdfSmrg @param[in/out] cdata The context object as a void pointer to satisfy the 82235c4bbdfSmrg type FindAllRes 82335c4bbdfSmrg*/ 82435c4bbdfSmrgstatic void 82535c4bbdfSmrgAddResourceSizeValueByResource(void *ptr, XID id, RESTYPE type, void *cdata) 82635c4bbdfSmrg{ 82735c4bbdfSmrg ConstructResourceBytesCtx *ctx = cdata; 82835c4bbdfSmrg xXResResourceIdSpec *spec = ctx->curSpec; 82935c4bbdfSmrg 83035c4bbdfSmrg if ((!spec->type || spec->type == type) && 83135c4bbdfSmrg (!spec->resource || spec->resource == id)) { 83235c4bbdfSmrg AddResourceSizeValue(ptr, id, type, ctx); 83335c4bbdfSmrg } 83435c4bbdfSmrg} 83535c4bbdfSmrg 83635c4bbdfSmrg/** @brief Add all resources of the client into the result buffer 83735c4bbdfSmrg disregarding all those specifications that specify the 83835c4bbdfSmrg resource by its ID. Those are handled by 83935c4bbdfSmrg ConstructResourceBytesByResource 84035c4bbdfSmrg 84135c4bbdfSmrg @see ConstructResourceBytesByResource 84235c4bbdfSmrg 84335c4bbdfSmrg @param[in] aboutClient Which client is being considered 84435c4bbdfSmrg @param[in/out] ctx The context that contains the resource id 84535c4bbdfSmrg specifications as well as the result buffer 84635c4bbdfSmrg*/ 84735c4bbdfSmrgstatic void 84835c4bbdfSmrgConstructClientResourceBytes(ClientPtr aboutClient, 84935c4bbdfSmrg ConstructResourceBytesCtx *ctx) 85035c4bbdfSmrg{ 85135c4bbdfSmrg int specIdx; 85235c4bbdfSmrg for (specIdx = 0; specIdx < ctx->numSpecs; ++specIdx) { 85335c4bbdfSmrg xXResResourceIdSpec* spec = ctx->specs + specIdx; 85435c4bbdfSmrg if (spec->resource) { 85535c4bbdfSmrg /* these specs are handled elsewhere */ 85635c4bbdfSmrg } else if (spec->type) { 85735c4bbdfSmrg ctx->resType = spec->type; 85835c4bbdfSmrg FindClientResourcesByType(aboutClient, spec->type, 85935c4bbdfSmrg AddResourceSizeValueWithResType, ctx); 86035c4bbdfSmrg } else { 86135c4bbdfSmrg FindAllClientResources(aboutClient, AddResourceSizeValue, ctx); 86235c4bbdfSmrg } 86335c4bbdfSmrg } 86435c4bbdfSmrg} 86535c4bbdfSmrg 86635c4bbdfSmrg/** @brief Add the sizes of all such resources that can are specified by 86735c4bbdfSmrg their ID in the resource id specification. The scan can 86835c4bbdfSmrg by limited to a client with the aboutClient parameter 86935c4bbdfSmrg 87035c4bbdfSmrg @see ConstructResourceBytesByResource 87135c4bbdfSmrg 87235c4bbdfSmrg @param[in] aboutClient Which client is being considered. This may be None 87335c4bbdfSmrg to mean all clients. 87435c4bbdfSmrg @param[in/out] ctx The context that contains the resource id 87535c4bbdfSmrg specifications as well as the result buffer. In 87635c4bbdfSmrg addition this function uses the curSpec field to 87735c4bbdfSmrg keep a pointer to the current resource id 87835c4bbdfSmrg specification in it, which can be used by 87935c4bbdfSmrg AddResourceSizeValueByResource . 88035c4bbdfSmrg*/ 88135c4bbdfSmrgstatic void 88235c4bbdfSmrgConstructResourceBytesByResource(XID aboutClient, ConstructResourceBytesCtx *ctx) 88335c4bbdfSmrg{ 88435c4bbdfSmrg int specIdx; 88535c4bbdfSmrg for (specIdx = 0; specIdx < ctx->numSpecs; ++specIdx) { 88635c4bbdfSmrg xXResResourceIdSpec *spec = ctx->specs + specIdx; 88735c4bbdfSmrg if (spec->resource) { 88835c4bbdfSmrg int cid = CLIENT_ID(spec->resource); 88935c4bbdfSmrg if (cid < currentMaxClients && 89035c4bbdfSmrg (aboutClient == None || cid == aboutClient)) { 89135c4bbdfSmrg ClientPtr client = clients[cid]; 89235c4bbdfSmrg if (client) { 89335c4bbdfSmrg ctx->curSpec = spec; 89435c4bbdfSmrg FindAllClientResources(client, 89535c4bbdfSmrg AddResourceSizeValueByResource, 89635c4bbdfSmrg ctx); 89735c4bbdfSmrg } 89835c4bbdfSmrg } 89935c4bbdfSmrg } 90035c4bbdfSmrg } 90135c4bbdfSmrg} 90235c4bbdfSmrg 90335c4bbdfSmrg/** @brief Build the resource size response for the given client 90435c4bbdfSmrg (or all if not specified) per the parameters set up 90535c4bbdfSmrg in the context object. 90635c4bbdfSmrg 90735c4bbdfSmrg @param[in] aboutClient Which client to consider or None for all clients 90835c4bbdfSmrg @param[in/out] ctx The context object that contains the request as well 90935c4bbdfSmrg as the response buffer. 91035c4bbdfSmrg*/ 91105b261ecSmrgstatic int 91235c4bbdfSmrgConstructResourceBytes(XID aboutClient, 91335c4bbdfSmrg ConstructResourceBytesCtx *ctx) 91435c4bbdfSmrg{ 91535c4bbdfSmrg if (aboutClient) { 91635c4bbdfSmrg int clientIdx = CLIENT_ID(aboutClient); 91735c4bbdfSmrg ClientPtr client = NullClient; 91835c4bbdfSmrg 91935c4bbdfSmrg if ((clientIdx >= currentMaxClients) || !clients[clientIdx]) { 92035c4bbdfSmrg ctx->sendClient->errorValue = aboutClient; 92135c4bbdfSmrg return BadValue; 92235c4bbdfSmrg } 92335c4bbdfSmrg 92435c4bbdfSmrg client = clients[clientIdx]; 92535c4bbdfSmrg 92635c4bbdfSmrg ConstructClientResourceBytes(client, ctx); 92735c4bbdfSmrg ConstructResourceBytesByResource(aboutClient, ctx); 92835c4bbdfSmrg } else { 92935c4bbdfSmrg int clientIdx; 93035c4bbdfSmrg 93135c4bbdfSmrg ConstructClientResourceBytes(NULL, ctx); 93235c4bbdfSmrg 93335c4bbdfSmrg for (clientIdx = 0; clientIdx < currentMaxClients; ++clientIdx) { 93435c4bbdfSmrg ClientPtr client = clients[clientIdx]; 93535c4bbdfSmrg 93635c4bbdfSmrg if (client) { 93735c4bbdfSmrg ConstructClientResourceBytes(client, ctx); 93835c4bbdfSmrg } 93935c4bbdfSmrg } 94035c4bbdfSmrg 94135c4bbdfSmrg ConstructResourceBytesByResource(None, ctx); 94235c4bbdfSmrg } 94335c4bbdfSmrg 94435c4bbdfSmrg 94535c4bbdfSmrg return ctx->status; 94635c4bbdfSmrg} 94735c4bbdfSmrg 94835c4bbdfSmrg/** @brief Implements the XResQueryResourceBytes of XResProto v1.2 */ 94935c4bbdfSmrgstatic int 95035c4bbdfSmrgProcXResQueryResourceBytes (ClientPtr client) 95135c4bbdfSmrg{ 95235c4bbdfSmrg REQUEST(xXResQueryResourceBytesReq); 95335c4bbdfSmrg 95435c4bbdfSmrg int rc; 95535c4bbdfSmrg ConstructResourceBytesCtx ctx; 95635c4bbdfSmrg 95735c4bbdfSmrg REQUEST_AT_LEAST_SIZE(xXResQueryResourceBytesReq); 9586e78d31fSmrg if (stuff->numSpecs > UINT32_MAX / sizeof(ctx.specs[0])) 9596e78d31fSmrg return BadLength; 96035c4bbdfSmrg REQUEST_FIXED_SIZE(xXResQueryResourceBytesReq, 96135c4bbdfSmrg stuff->numSpecs * sizeof(ctx.specs[0])); 96235c4bbdfSmrg 96335c4bbdfSmrg if (!InitConstructResourceBytesCtx(&ctx, client, 96435c4bbdfSmrg stuff->numSpecs, 96535c4bbdfSmrg (void*) ((char*) stuff + 96635c4bbdfSmrg sz_xXResQueryResourceBytesReq))) { 96735c4bbdfSmrg return BadAlloc; 96835c4bbdfSmrg } 96935c4bbdfSmrg 97035c4bbdfSmrg rc = ConstructResourceBytes(stuff->client, &ctx); 97135c4bbdfSmrg 97235c4bbdfSmrg if (rc == Success) { 97335c4bbdfSmrg xXResQueryResourceBytesReply rep = { 97435c4bbdfSmrg .type = X_Reply, 97535c4bbdfSmrg .sequenceNumber = client->sequence, 97635c4bbdfSmrg .length = bytes_to_int32(ctx.resultBytes), 97735c4bbdfSmrg .numSizes = ctx.numSizes 97835c4bbdfSmrg }; 97935c4bbdfSmrg 98035c4bbdfSmrg if (client->swapped) { 98135c4bbdfSmrg swaps (&rep.sequenceNumber); 98235c4bbdfSmrg swapl (&rep.length); 98335c4bbdfSmrg swapl (&rep.numSizes); 98435c4bbdfSmrg 98535c4bbdfSmrg SwapXResQueryResourceBytes(&ctx.response); 98635c4bbdfSmrg } 98735c4bbdfSmrg 98835c4bbdfSmrg WriteToClient(client, sizeof(rep), &rep); 98935c4bbdfSmrg WriteFragmentsToClient(client, &ctx.response); 99035c4bbdfSmrg } 99135c4bbdfSmrg 99235c4bbdfSmrg DestroyConstructResourceBytesCtx(&ctx); 99335c4bbdfSmrg 99435c4bbdfSmrg return rc; 99535c4bbdfSmrg} 99635c4bbdfSmrg 99735c4bbdfSmrgstatic int 99835c4bbdfSmrgProcResDispatch(ClientPtr client) 99905b261ecSmrg{ 100005b261ecSmrg REQUEST(xReq); 100105b261ecSmrg switch (stuff->data) { 100205b261ecSmrg case X_XResQueryVersion: 100305b261ecSmrg return ProcXResQueryVersion(client); 100405b261ecSmrg case X_XResQueryClients: 100505b261ecSmrg return ProcXResQueryClients(client); 100605b261ecSmrg case X_XResQueryClientResources: 100705b261ecSmrg return ProcXResQueryClientResources(client); 100805b261ecSmrg case X_XResQueryClientPixmapBytes: 100905b261ecSmrg return ProcXResQueryClientPixmapBytes(client); 101035c4bbdfSmrg case X_XResQueryClientIds: 101135c4bbdfSmrg return ProcXResQueryClientIds(client); 101235c4bbdfSmrg case X_XResQueryResourceBytes: 101335c4bbdfSmrg return ProcXResQueryResourceBytes(client); 101405b261ecSmrg default: break; 101505b261ecSmrg } 101605b261ecSmrg 101705b261ecSmrg return BadRequest; 101805b261ecSmrg} 101905b261ecSmrg 10207e31ba66Smrgstatic int _X_COLD 102135c4bbdfSmrgSProcXResQueryVersion(ClientPtr client) 102205b261ecSmrg{ 102335c4bbdfSmrg REQUEST_SIZE_MATCH(xXResQueryVersionReq); 102405b261ecSmrg return ProcXResQueryVersion(client); 102505b261ecSmrg} 102605b261ecSmrg 10277e31ba66Smrgstatic int _X_COLD 102835c4bbdfSmrgSProcXResQueryClientResources(ClientPtr client) 102905b261ecSmrg{ 103005b261ecSmrg REQUEST(xXResQueryClientResourcesReq); 103135c4bbdfSmrg REQUEST_SIZE_MATCH(xXResQueryClientResourcesReq); 103235c4bbdfSmrg swapl(&stuff->xid); 103305b261ecSmrg return ProcXResQueryClientResources(client); 103405b261ecSmrg} 103505b261ecSmrg 10367e31ba66Smrgstatic int _X_COLD 103735c4bbdfSmrgSProcXResQueryClientPixmapBytes(ClientPtr client) 103805b261ecSmrg{ 103905b261ecSmrg REQUEST(xXResQueryClientPixmapBytesReq); 104035c4bbdfSmrg REQUEST_SIZE_MATCH(xXResQueryClientPixmapBytesReq); 104135c4bbdfSmrg swapl(&stuff->xid); 104205b261ecSmrg return ProcXResQueryClientPixmapBytes(client); 104305b261ecSmrg} 104405b261ecSmrg 10457e31ba66Smrgstatic int _X_COLD 104635c4bbdfSmrgSProcXResQueryClientIds (ClientPtr client) 104735c4bbdfSmrg{ 104835c4bbdfSmrg REQUEST(xXResQueryClientIdsReq); 104935c4bbdfSmrg 105035c4bbdfSmrg REQUEST_AT_LEAST_SIZE (xXResQueryClientIdsReq); 105135c4bbdfSmrg swapl(&stuff->numSpecs); 105235c4bbdfSmrg return ProcXResQueryClientIds(client); 105335c4bbdfSmrg} 105435c4bbdfSmrg 105535c4bbdfSmrg/** @brief Implements the XResQueryResourceBytes of XResProto v1.2. 105635c4bbdfSmrg This variant byteswaps request contents before issuing the 105735c4bbdfSmrg rest of the work to ProcXResQueryResourceBytes */ 10587e31ba66Smrgstatic int _X_COLD 105935c4bbdfSmrgSProcXResQueryResourceBytes (ClientPtr client) 106035c4bbdfSmrg{ 106135c4bbdfSmrg REQUEST(xXResQueryResourceBytesReq); 106235c4bbdfSmrg int c; 106335c4bbdfSmrg xXResResourceIdSpec *specs = (void*) ((char*) stuff + sizeof(*stuff)); 106435c4bbdfSmrg 106535c4bbdfSmrg REQUEST_AT_LEAST_SIZE(xXResQueryResourceBytesReq); 10666e78d31fSmrg swapl(&stuff->numSpecs); 106735c4bbdfSmrg REQUEST_FIXED_SIZE(xXResQueryResourceBytesReq, 106835c4bbdfSmrg stuff->numSpecs * sizeof(specs[0])); 106935c4bbdfSmrg 107035c4bbdfSmrg for (c = 0; c < stuff->numSpecs; ++c) { 107135c4bbdfSmrg SwapXResResourceIdSpec(specs + c); 107235c4bbdfSmrg } 107335c4bbdfSmrg 107435c4bbdfSmrg return ProcXResQueryResourceBytes(client); 107535c4bbdfSmrg} 107635c4bbdfSmrg 10777e31ba66Smrgstatic int _X_COLD 107805b261ecSmrgSProcResDispatch (ClientPtr client) 107905b261ecSmrg{ 108005b261ecSmrg REQUEST(xReq); 108135c4bbdfSmrg swaps(&stuff->length); 108205b261ecSmrg 108305b261ecSmrg switch (stuff->data) { 108405b261ecSmrg case X_XResQueryVersion: 108505b261ecSmrg return SProcXResQueryVersion(client); 108635c4bbdfSmrg case X_XResQueryClients: /* nothing to swap */ 108705b261ecSmrg return ProcXResQueryClients(client); 108805b261ecSmrg case X_XResQueryClientResources: 108905b261ecSmrg return SProcXResQueryClientResources(client); 109005b261ecSmrg case X_XResQueryClientPixmapBytes: 109105b261ecSmrg return SProcXResQueryClientPixmapBytes(client); 109235c4bbdfSmrg case X_XResQueryClientIds: 109335c4bbdfSmrg return SProcXResQueryClientIds(client); 109435c4bbdfSmrg case X_XResQueryResourceBytes: 109535c4bbdfSmrg return SProcXResQueryResourceBytes(client); 109605b261ecSmrg default: break; 109705b261ecSmrg } 109805b261ecSmrg 109905b261ecSmrg return BadRequest; 110005b261ecSmrg} 110105b261ecSmrg 110205b261ecSmrgvoid 110335c4bbdfSmrgResExtensionInit(void) 110405b261ecSmrg{ 110505b261ecSmrg (void) AddExtension(XRES_NAME, 0, 0, 110635c4bbdfSmrg ProcResDispatch, SProcResDispatch, 110735c4bbdfSmrg NULL, StandardMinorOpcode); 110805b261ecSmrg} 1109