--- ./nx-X11/programs/Xserver/hw/nxagent/X/NXresource.c.X.original 2015-02-13 14:03:44.748441432 +0100 +++ ./nx-X11/programs/Xserver/hw/nxagent/X/NXresource.c 2015-02-10 19:13:13.820685287 +0100 @@ -1,3 +1,20 @@ +/**************************************************************************/ +/* */ +/* Copyright (c) 2001, 2011 NoMachine, http://www.nomachine.com/. */ +/* */ +/* NXAGENT, NX protocol compression and NX extensions to this software */ +/* are copyright of NoMachine. Redistribution and use of the present */ +/* software is allowed according to terms specified in the file LICENSE */ +/* which comes in the source distribution. */ +/* */ +/* Check http://www.nomachine.com/licensing.html for applicability. */ +/* */ +/* NX and NoMachine are trademarks of Medialogic S.p.A. */ +/* */ +/* All rights reserved. */ +/* */ +/**************************************************************************/ + /************************************************************ Copyright 1987, 1998 The Open Group @@ -125,6 +142,20 @@ #endif #include +#ifdef NXAGENT_SERVER + +#include "Agent.h" +#include "Font.h" +#include "Pixmaps.h" +#include "GCs.h" + +#define PANIC +#define WARNING +#undef TEST +#undef DEBUG + +#endif + static void RebuildTable( int /*client*/ ); @@ -170,6 +201,10 @@ #endif +#ifdef NXAGENT_SERVER +static int nxagentResChangedFlag = 0; +#endif + RESTYPE CreateNewResourceType(DeleteType deleteFunc) { @@ -422,13 +457,107 @@ return id; } +#ifdef NXAGENT_SERVER + +int nxagentFindClientResource(int client, RESTYPE type, pointer value) +{ + ResourcePtr pResource; + ResourcePtr *resources; + + int i; + + for (i = 0; i < clientTable[client].buckets; i++) + { + resources = clientTable[client].resources; + + for (pResource = resources[i]; pResource; pResource = pResource -> next) + { + if (pResource -> type == type && pResource -> value == value) + { + #ifdef TEST + fprintf(stderr, "nxagentFindClientResource: Found resource [%p] type [%lu] " + "for client [%d].\n", (void *) value, + pResource -> type, client); + #endif + + return 1; + } + } + } + + return 0; +} + +int nxagentSwitchResourceType(int client, RESTYPE type, pointer value) +{ + ResourcePtr pResource; + ResourcePtr *resources; + + RESTYPE internalType = 0; + + int i; + + if (type == RT_PIXMAP) + { + internalType = RT_NX_PIXMAP; + } + else if (type == RT_GC) + { + internalType = RT_NX_GC; + } + else if (type == RT_FONT) + { + internalType = RT_NX_FONT; + } + else + { + return 0; + } + + if (client == serverClient -> index) + { + #ifdef TEST + fprintf(stderr, "nxagentSwitchResourceType: Requesting client is [%d]. Skipping the resource switch.\n", + client); + #endif + + return 0; + } + + for (i = 0; i < clientTable[serverClient -> index].buckets; i++) + { + resources = clientTable[serverClient -> index].resources; + + for (pResource = resources[i]; pResource; pResource = pResource -> next) + { + if (pResource -> type == internalType && + pResource -> value == value) + { + #ifdef TEST + fprintf(stderr, "nxagentSwitchResourceType: Changing resource [%p] type from [%lu] to " + "[%lu] for server client [%d].\n", (void *) value, + (unsigned long) pResource -> type, (unsigned long) type, serverClient -> index); + #endif + + FreeResource(pResource -> id, RT_NONE); + + return 1; + } + } + } + + return 0; +} + +#endif + Bool AddResource(XID id, RESTYPE type, pointer value) { int client; register ClientResourceRec *rrec; register ResourcePtr res, *head; - + client = CLIENT_ID(id); rrec = &clientTable[client]; if (!rrec->buckets) @@ -437,6 +566,18 @@ (unsigned long)id, type, (unsigned long)value, client); FatalError("client not in use\n"); } + +#ifdef NXAGENT_SERVER + + nxagentSwitchResourceType(client, type, value); + + #ifdef TEST + fprintf(stderr, "AddResource: Adding resource for client [%d] type [%lu] value [%p] id [%lu].\n", + client, (unsigned long) type, (void *) value, (unsigned long) id); + #endif + +#endif + if ((rrec->elements >= 4*rrec->buckets) && (rrec->hashsize < MAXHASHSIZE)) RebuildTable(client); @@ -453,6 +594,9 @@ res->value = value; *head = res; rrec->elements++; + #ifdef NXAGENT_SERVER + nxagentResChangedFlag = 1; + #endif if (!(id & SERVER_BIT) && (id >= rrec->expectID)) rrec->expectID = id + 1; return TRUE; @@ -517,6 +661,14 @@ int elements; Bool gotOne = FALSE; +#ifdef NXAGENT_SERVER + + #ifdef TEST + fprintf(stderr, "FreeResource: Freeing resource id [%lu].\n", (unsigned long) id); + #endif + +#endif + if (((cid = CLIENT_ID(id)) < MAXCLIENTS) && clientTable[cid].buckets) { head = &clientTable[cid].resources[Hash(cid, id)]; @@ -530,6 +682,9 @@ RESTYPE rtype = res->type; *prev = res->next; elements = --*eltptr; + #ifdef NXAGENT_SERVER + nxagentResChangedFlag = 1; + #endif if (rtype & RC_CACHED) FlushClientCaches(res->id); if (rtype != skipDeleteFuncType) @@ -570,6 +725,9 @@ if (res->id == id && res->type == type) { *prev = res->next; + #ifdef NXAGENT_SERVER + nxagentResChangedFlag = 1; + #endif if (type & RC_CACHED) FlushClientCaches(res->id); if (!skipFree) @@ -634,10 +792,28 @@ int i, elements; register int *eltptr; + #ifdef NXAGENT_SERVER + register ResourcePtr **resptr; + #endif + if (!client) client = serverClient; +/* + * If func triggers a resource table + * rebuild then restart the loop. + */ + +#ifdef NXAGENT_SERVER +RestartLoop: +#endif + resources = clientTable[client->index].resources; + + #ifdef NXAGENT_SERVER + resptr = &clientTable[client->index].resources; + #endif + eltptr = &clientTable[client->index].elements; for (i = 0; i < clientTable[client->index].buckets; i++) { @@ -646,8 +822,44 @@ next = this->next; if (!type || this->type == type) { elements = *eltptr; + + /* + * FIXME: + * It is not safe to let a function change the resource + * table we are reading! + */ + + #ifdef NXAGENT_SERVER + nxagentResChangedFlag = 0; + #endif (*func)(this->value, this->id, cdata); + + /* + * Avoid that a call to RebuildTable() could invalidate the + * pointer. This is safe enough, because in RebuildTable() + * the new pointer is allocated just before the old one is + * freed, so it can't point to the same address. + */ + + #ifdef NXAGENT_SERVER + if (*resptr != resources) + goto RestartLoop; + #endif + + /* + * It's not enough to check if the number of elements has + * changed, beacause it could happen that the number of + * resources that have been added matches the number of + * the freed ones. + * 'nxagentResChangedFlag' is set if a resource has been + * added or freed. + */ + + #ifdef NXAGENT_SERVER + if (*eltptr != elements || nxagentResChangedFlag) + #else if (*eltptr != elements) + #endif next = resources[i]; /* start over */ } } @@ -665,10 +877,28 @@ int i, elements; register int *eltptr; + #ifdef NXAGENT_SERVER + register ResourcePtr **resptr; + #endif + if (!client) client = serverClient; +/* + * If func triggers a resource table + * rebuild then restart the loop. + */ + +#ifdef NXAGENT_SERVER +RestartLoop: +#endif + resources = clientTable[client->index].resources; + + #ifdef NXAGENT_SERVER + resptr = &clientTable[client->index].resources; + #endif + eltptr = &clientTable[client->index].elements; for (i = 0; i < clientTable[client->index].buckets; i++) { @@ -676,8 +906,44 @@ { next = this->next; elements = *eltptr; + + /* + * FIXME: + * It is not safe to let a function change the resource + * table we are reading! + */ + + #ifdef NXAGENT_SERVER + nxagentResChangedFlag = 0; + #endif (*func)(this->value, this->id, this->type, cdata); + + /* + * Avoid that a call to RebuildTable() could invalidate the + * pointer. This is safe enough, because in RebuildTable() + * the new pointer is allocated just before the old one is + * freed, so it can't point to the same address. + */ + + #ifdef NXAGENT_SERVER + if (*resptr != resources) + goto RestartLoop; + #endif + + /* + * It's not enough to check if the number of elements has + * changed, beacause it could happen that the number of + * resources that have been added matches the number of + * the freed ones. + * 'nxagentResChangedFlag' is set if a resource has been + * added or freed. + */ + + #ifdef NXAGENT_SERVER + if (*eltptr != elements || nxagentResChangedFlag) + #else if (*eltptr != elements) + #endif next = resources[i]; /* start over */ } } @@ -695,15 +961,44 @@ ResourcePtr this; int i; + #ifdef NXAGENT_SERVER + ResourcePtr **resptr; + Bool res; + #endif + if (!client) client = serverClient; +/* + * If func triggers a resource table + * rebuild then restart the loop. + */ + +#ifdef NXAGENT_SERVER +RestartLoop: +#endif + resources = clientTable[client->index].resources; + + #ifdef NXAGENT_SERVER + resptr = &clientTable[client->index].resources; + #endif + for (i = 0; i < clientTable[client->index].buckets; i++) { for (this = resources[i]; this; this = this->next) { if (!type || this->type == type) { + #ifdef NXAGENT_SERVER + res = (*func)(this->value, this->id, cdata); + + if (*resptr != resources) + goto RestartLoop; + + if (res) + return this->value; + #else if((*func)(this->value, this->id, cdata)) return this->value; + #endif } } } @@ -952,3 +1247,4 @@ } #endif /* XCSECURITY */ +