#define NEED_REPLIES
#define NEED_EVENTS
#ifdef HAVE_DIX_CONFIG_H
#include <dix-config.h>
#endif
#include <X11/X.h>
#include <X11/Xproto.h>
#include "misc.h"
#include "dixstruct.h"
#include "extnsionst.h"
#include "scrnintstr.h"
#include "windowstr.h"
#include "colormapst.h"
#include "servermd.h"
#define _XAG_SERVER_
#include <X11/extensions/Xagstr.h>
#include "xacestr.h"
#include "securitysrv.h"
#include <X11/Xfuncproto.h>
#define XSERV_t
#include <X11/Xtrans/Xtrans.h>
#include "../os/osdep.h"
#include <stdio.h>
#include "modinit.h"
#include "appgroup.h"
typedef struct _AppGroupRec {
struct _AppGroupRec* next;
XID appgroupId;
ClientPtr* clients;
int nclients;
ClientPtr leader;
Bool single_screen;
Window default_root;
VisualID root_visual;
Colormap default_colormap;
Pixel black_pixel;
Pixel white_pixel;
xConnSetupPrefix connSetupPrefix;
char* ConnectionInfo;
} AppGroupRec, *AppGroupPtr;
static int ProcXagDispatch(ClientPtr client);
static int SProcXagDispatch(ClientPtr client);
static void XagResetProc(ExtensionEntry* extEntry);
static int XagCallbackRefCount = 0;
static RESTYPE RT_APPGROUP;
static AppGroupPtr appGrpList = NULL;
extern xConnSetupPrefix connSetupPrefix;
extern char* ConnectionInfo;
extern int connBlockScreenStart;
static
int XagAppGroupFree(
pointer what,
XID id)
{
int i;
AppGroupPtr pAppGrp = (AppGroupPtr) what;
if (pAppGrp->leader)
for (i = 0; i < pAppGrp->nclients; i++) {
if (pAppGrp->clients[i] == NULL) continue;
CloseDownClient (pAppGrp->clients[i]);
}
if (pAppGrp == appGrpList)
appGrpList = appGrpList->next;
else {
AppGroupPtr tpAppGrp;
for (tpAppGrp = appGrpList;
tpAppGrp->next != NULL;
tpAppGrp = tpAppGrp->next) {
if (tpAppGrp->next == pAppGrp) {
tpAppGrp->next = tpAppGrp->next->next;
break;
}
}
}
(void) xfree (pAppGrp->clients);
(void) xfree (pAppGrp->ConnectionInfo);
(void) xfree (what);
return Success;
}
void XagClientStateChange(
CallbackListPtr* pcbl,
pointer nulldata,
pointer calldata)
{
NewClientInfoRec* pci = (NewClientInfoRec*) calldata;
ClientPtr pClient = pci->client;
AppGroupPtr pAppGrp = pClient->appgroup;
int slot;
if (!pAppGrp)
return;
switch (pClient->clientState) {
case ClientStateAuthenticating:
case ClientStateRunning:
case ClientStateCheckingSecurity:
break;
case ClientStateInitial:
case ClientStateCheckedSecurity:
slot = -1;
if (pAppGrp->nclients != 0) {
int i;
for (i = 0; i < pAppGrp->nclients; i++)
if (pClient == pAppGrp->clients[i]) return;
if (slot == -1 && pAppGrp->clients[i] == NULL)
slot = i;
}
if (slot == -1) {
slot = pAppGrp->nclients++;
pAppGrp->clients = (ClientPtr*) xrealloc (pAppGrp->clients,
pAppGrp->nclients * sizeof (ClientPtr));
}
pAppGrp->clients[slot] = pClient;
pClient->appgroup = pAppGrp;
break;
case ClientStateGone:
case ClientStateRetained:
{
int i;
for (i = 0; i < pAppGrp->nclients; i++)
if (pAppGrp->clients[i] == pClient) {
pAppGrp->clients[i] = NULL;
break;
}
}
pClient->appgroup = NULL;
break;
}
}
void
XagExtensionInit(INITARGS)
{
if (AddExtension (XAGNAME,
0,
XagNumberErrors,
ProcXagDispatch,
SProcXagDispatch,
XagResetProc,
StandardMinorOpcode)) {
RT_APPGROUP = CreateNewResourceType (XagAppGroupFree);
XaceRegisterCallback(XACE_AUTH_AVAIL, XagCallClientStateChange, NULL);
}
}
static
void XagResetProc(
ExtensionEntry* extEntry)
{
DeleteCallback (&ClientStateCallback, XagClientStateChange, NULL);
XagCallbackRefCount = 0;
while (appGrpList) XagAppGroupFree ((pointer) appGrpList, 0);
}
static
int ProcXagQueryVersion(
register ClientPtr client)
{
xXagQueryVersionReply rep;
register int n;
REQUEST_SIZE_MATCH (xXagQueryVersionReq);
rep.type = X_Reply;
rep.length = 0;
rep.sequence_number = client->sequence;
rep.server_major_version = XAG_MAJOR_VERSION;
rep.server_minor_version = XAG_MINOR_VERSION;
if (client->swapped) {
swaps (&rep.sequence_number, n);
swapl (&rep.length, n);
swaps (&rep.server_major_version, n);
swaps (&rep.server_minor_version, n);
}
WriteToClient (client, sizeof (xXagQueryVersionReply), (char *)&rep);
return client->noClientException;
}
static
void ProcessAttr(
AppGroupPtr pAppGrp,
ClientPtr client,
unsigned int attrib_mask,
CARD32* attribs)
{
int i;
for (i = 0; i <= XagNappGroupLeader; i++) {
switch (attrib_mask & (1 << i)) {
case XagSingleScreenMask:
pAppGrp->single_screen = *attribs;
break;
case XagDefaultRootMask:
pAppGrp->default_root = *attribs;
break;
case XagRootVisualMask:
pAppGrp->root_visual = *attribs;
break;
case XagDefaultColormapMask:
pAppGrp->default_colormap = *attribs;
break;
case XagBlackPixelMask:
pAppGrp->black_pixel = *attribs;
break;
case XagWhitePixelMask:
pAppGrp->white_pixel = *attribs;
break;
case XagAppGroupLeaderMask:
pAppGrp->leader = client;
break;
default: continue;
}
attribs++;
}
}
static
void CreateConnectionInfo(
AppGroupPtr pAppGrp)
{
xWindowRoot* rootp;
xWindowRoot* roots[MAXSCREENS];
unsigned int rootlens[MAXSCREENS];
xDepth* depth;
int olen;
int snum, i;
rootp = (xWindowRoot*) (ConnectionInfo + connBlockScreenStart);
for (snum = 0; snum < screenInfo.numScreens; snum++) {
rootlens[snum] = sizeof (xWindowRoot);
roots[snum] = rootp;
depth = (xDepth*) (rootp + 1);
for (i = 0; i < rootp->nDepths; i++) {
rootlens[snum] += sizeof (xDepth) +
depth->nVisuals * sizeof (xVisualType);
depth = (xDepth *)(((char*)(depth + 1)) +
depth->nVisuals * sizeof (xVisualType));
}
rootp = (xWindowRoot*) depth;
}
snum = 0;
if (pAppGrp->default_root) {
for (; snum < screenInfo.numVideoScreens; snum++) {
if (roots[snum]->windowId == pAppGrp->default_root)
break;
}
}
olen = connBlockScreenStart + rootlens[snum];
for (i = screenInfo.numVideoScreens; i < screenInfo.numScreens; i++)
olen += rootlens[i];
pAppGrp->ConnectionInfo = (char*) xalloc (olen);
if (!pAppGrp->ConnectionInfo)
return;
memmove (pAppGrp->ConnectionInfo, ConnectionInfo, connBlockScreenStart);
((xConnSetup*) (pAppGrp->ConnectionInfo))->numRoots =
1 + screenInfo.numScreens - screenInfo.numVideoScreens;
memmove (pAppGrp->ConnectionInfo + connBlockScreenStart,
(void*) roots[snum], rootlens[snum]);
rootp = (xWindowRoot*) (pAppGrp->ConnectionInfo + connBlockScreenStart);
if (pAppGrp->default_colormap) {
rootp->defaultColormap = pAppGrp->default_colormap;
rootp->whitePixel = pAppGrp->white_pixel;
rootp->blackPixel = pAppGrp->black_pixel;
}
if (pAppGrp->root_visual)
rootp->rootVisualID = pAppGrp->root_visual;
rootp = (xWindowRoot*) (((char*)rootp) + rootlens[snum]);
for (i = screenInfo.numVideoScreens; i < screenInfo.numScreens; i++) {
memmove ((void*) rootp, (void*) roots[i], rootlens[i]);
rootp = (xWindowRoot*) (((char*) rootp) + rootlens[i]);
}
pAppGrp->connSetupPrefix = connSetupPrefix;
pAppGrp->connSetupPrefix.length = olen >> 2;
}
static
AppGroupPtr CreateAppGroup(
ClientPtr client,
XID appgroupId,
unsigned int attrib_mask,
CARD32* attribs)
{
AppGroupPtr pAppGrp;
pAppGrp = (AppGroupPtr) xalloc (sizeof(AppGroupRec));
if (pAppGrp) {
pAppGrp->next = appGrpList;
appGrpList = pAppGrp;
pAppGrp->appgroupId = appgroupId;
pAppGrp->clients = (ClientPtr*) xalloc (0);
pAppGrp->nclients = 0;
pAppGrp->leader = NULL;
pAppGrp->default_root = 0;
pAppGrp->root_visual = 0;
pAppGrp->default_colormap = 0;
pAppGrp->black_pixel = -1;
pAppGrp->white_pixel = -1;
pAppGrp->ConnectionInfo = NULL;
ProcessAttr (pAppGrp, client, attrib_mask, attribs);
}
return pAppGrp;
}
static
int AttrValidate(
ClientPtr client,
int attrib_mask,
AppGroupPtr pAppGrp)
{
WindowPtr pWin;
int idepth, ivids, found;
ScreenPtr pScreen;
DepthPtr pDepth;
ColormapPtr pColormap;
pWin = LookupWindow (pAppGrp->default_root, client);
pScreen = pWin->drawable.pScreen;
if (WindowTable[pScreen->myNum]->drawable.id != pAppGrp->default_root)
return BadWindow;
pDepth = pScreen->allowedDepths;
if (pAppGrp->root_visual) {
found = FALSE;
for (idepth = 0; idepth < pScreen->numDepths; idepth++, pDepth++) {
for (ivids = 0; ivids < pDepth->numVids; ivids++) {
if (pAppGrp->root_visual == pDepth->vids[ivids]) {
found = TRUE;
break;
}
}
}
if (!found)
return BadMatch;
}
if (pAppGrp->default_colormap) {
pColormap = (ColormapPtr)LookupIDByType (pAppGrp->default_colormap, RT_COLORMAP);
if (pColormap->pScreen != pScreen)
return BadColor;
if (pColormap->pVisual->vid != (pAppGrp->root_visual ? pAppGrp->root_visual : pScreen->rootVisual))
return BadMatch;
}
return client->noClientException;
}
int ProcXagCreate (
register ClientPtr client)
{
REQUEST (xXagCreateReq);
AppGroupPtr pAppGrp;
int ret;
REQUEST_AT_LEAST_SIZE (xXagCreateReq);
LEGAL_NEW_RESOURCE (stuff->app_group, client);
pAppGrp = CreateAppGroup (client, stuff->app_group,
stuff->attrib_mask, (CARD32*) &stuff[1]);
if (!pAppGrp)
return BadAlloc;
ret = AttrValidate (client, stuff->attrib_mask, pAppGrp);
if (ret != Success) {
XagAppGroupFree ((pointer)pAppGrp, (XID)0);
return ret;
}
if (pAppGrp->single_screen) {
CreateConnectionInfo (pAppGrp);
if (!pAppGrp->ConnectionInfo)
return BadAlloc;
}
if (!AddResource (stuff->app_group, RT_APPGROUP, (pointer)pAppGrp))
return BadAlloc;
if (XagCallbackRefCount++ == 0)
(void) AddCallback (&ClientStateCallback, XagClientStateChange, NULL);
return client->noClientException;
}
int ProcXagDestroy(
register ClientPtr client)
{
AppGroupPtr pAppGrp;
REQUEST (xXagDestroyReq);
REQUEST_SIZE_MATCH (xXagDestroyReq);
pAppGrp = (AppGroupPtr)SecurityLookupIDByType (client,
(XID)stuff->app_group, RT_APPGROUP, SecurityReadAccess);
if (!pAppGrp) return XagBadAppGroup;
FreeResource ((XID)stuff->app_group, RT_NONE);
if (--XagCallbackRefCount == 0)
(void) DeleteCallback (&ClientStateCallback, XagClientStateChange, NULL);
return client->noClientException;
}
static
int ProcXagGetAttr(
register ClientPtr client)
{
AppGroupPtr pAppGrp;
REQUEST (xXagGetAttrReq);
xXagGetAttrReply rep;
int n;
REQUEST_SIZE_MATCH (xXagGetAttrReq);
pAppGrp = (AppGroupPtr)SecurityLookupIDByType (client,
(XID)stuff->app_group, RT_APPGROUP, SecurityReadAccess);
if (!pAppGrp) return XagBadAppGroup;
rep.type = X_Reply;
rep.length = 0;
rep.sequence_number = client->sequence;
rep.default_root = pAppGrp->default_root;
rep.root_visual = pAppGrp->root_visual;
rep.default_colormap = pAppGrp->default_colormap;
rep.black_pixel = pAppGrp->black_pixel;
rep.white_pixel = pAppGrp->white_pixel;
rep.single_screen = pAppGrp->single_screen;
rep.app_group_leader = (pAppGrp->leader) ? 1 : 0;
if (client->swapped) {
swaps (&rep.sequence_number, n);
swapl (&rep.length, n);
swapl (&rep.default_root, n);
swapl (&rep.root_visual, n);
swapl (&rep.default_colormap, n);
swapl (&rep.black_pixel, n);
swapl (&rep.white_pixel, n);
}
WriteToClient (client, sizeof (xXagGetAttrReply), (char *)&rep);
return client->noClientException;
}
static
int ProcXagQuery(
register ClientPtr client)
{
ClientPtr pClient;
AppGroupPtr pAppGrp;
REQUEST (xXagQueryReq);
int n;
REQUEST_SIZE_MATCH (xXagQueryReq);
pClient = LookupClient (stuff->resource, client);
for (pAppGrp = appGrpList; pAppGrp != NULL; pAppGrp = pAppGrp->next)
for (n = 0; n < pAppGrp->nclients; n++)
if (pAppGrp->clients[n] == pClient) {
xXagQueryReply rep;
rep.type = X_Reply;
rep.length = 0;
rep.sequence_number = client->sequence;
rep.app_group = pAppGrp->appgroupId;
if (client->swapped) {
swaps (&rep.sequence_number, n);
swapl (&rep.length, n);
swapl (&rep.app_group, n);
}
WriteToClient (client, sizeof (xXagQueryReply), (char *)&rep);
return client->noClientException;
}
return BadMatch;
}
static
int ProcXagCreateAssoc(
register ClientPtr client)
{
REQUEST (xXagCreateAssocReq);
REQUEST_SIZE_MATCH (xXagCreateAssocReq);
#ifdef WIN32
if (stuff->window_type != XagWindowTypeWin32)
#else
if (stuff->window_type != XagWindowTypeX11)
#endif
return BadMatch;
#if defined(WIN32) || defined(__CYGWIN__)
if (!LocalClient (client))
return BadAccess;
#endif
return client->noClientException;
}
static
int ProcXagDestroyAssoc(
register ClientPtr client)
{
REQUEST_SIZE_MATCH (xXagDestroyAssocReq);
return client->noClientException;
}
static
int ProcXagDispatch (
register ClientPtr client)
{
REQUEST (xReq);
switch (stuff->data)
{
case X_XagQueryVersion:
return ProcXagQueryVersion (client);
case X_XagCreate:
return ProcXagCreate (client);
case X_XagDestroy:
return ProcXagDestroy (client);
case X_XagGetAttr:
return ProcXagGetAttr (client);
case X_XagQuery:
return ProcXagQuery (client);
case X_XagCreateAssoc:
return ProcXagCreateAssoc (client);
case X_XagDestroyAssoc:
return ProcXagDestroyAssoc (client);
default:
return BadRequest;
}
}
static
int SProcXagQueryVersion(
register ClientPtr client)
{
register int n;
REQUEST(xXagQueryVersionReq);
swaps(&stuff->length, n);
return ProcXagQueryVersion(client);
}
static
int SProcXagCreate(
ClientPtr client)
{
register int n;
REQUEST (xXagCreateReq);
swaps (&stuff->length, n);
REQUEST_AT_LEAST_SIZE (xXagCreateReq);
swapl (&stuff->app_group, n);
swapl (&stuff->attrib_mask, n);
SwapRestL (stuff);
return ProcXagCreate (client);
}
static
int SProcXagDestroy(
ClientPtr client)
{
register int n;
REQUEST (xXagDestroyReq);
swaps (&stuff->length, n);
REQUEST_SIZE_MATCH (xXagDestroyReq);
swapl (&stuff->app_group, n);
return ProcXagDestroy (client);
}
static
int SProcXagGetAttr(
ClientPtr client)
{
register int n;
REQUEST (xXagGetAttrReq);
swaps (&stuff->length, n);
REQUEST_SIZE_MATCH (xXagGetAttrReq);
swapl (&stuff->app_group, n);
return ProcXagGetAttr (client);
}
static
int SProcXagQuery(
ClientPtr client)
{
register int n;
REQUEST (xXagQueryReq);
swaps (&stuff->length, n);
REQUEST_SIZE_MATCH (xXagQueryReq);
swapl (&stuff->resource, n);
return ProcXagQuery (client);
}
static
int SProcXagCreateAssoc(
ClientPtr client)
{
register int n;
REQUEST (xXagCreateAssocReq);
swaps (&stuff->length, n);
REQUEST_SIZE_MATCH (xXagCreateAssocReq);
swapl (&stuff->window, n);
swapl (&stuff->window_type, n);
swaps (&stuff->system_window_len, n);
return ProcXagCreateAssoc (client);
}
static
int SProcXagDestroyAssoc(
ClientPtr client)
{
register int n;
REQUEST (xXagDestroyAssocReq);
swaps (&stuff->length, n);
REQUEST_SIZE_MATCH (xXagDestroyAssocReq);
swapl (&stuff->window, n);
return ProcXagDestroyAssoc (client);
}
static
int SProcXagDispatch(
register ClientPtr client)
{
REQUEST(xReq);
switch (stuff->data)
{
case X_XagQueryVersion:
return SProcXagQueryVersion (client);
case X_XagCreate:
return SProcXagCreate (client);
case X_XagDestroy:
return SProcXagDestroy (client);
case X_XagGetAttr:
return SProcXagGetAttr (client);
case X_XagQuery:
return SProcXagQuery (client);
case X_XagCreateAssoc:
return SProcXagCreateAssoc (client);
case X_XagDestroyAssoc:
return SProcXagDestroyAssoc (client);
default:
return BadRequest;
}
}
Colormap XagDefaultColormap(
ClientPtr client)
{
return (client->appgroup ? client->appgroup->default_colormap : None);
}
VisualID XagRootVisual(
ClientPtr client)
{
return (client->appgroup ? client->appgroup->root_visual : 0);
}
ClientPtr XagLeader(
ClientPtr client)
{
return (client->appgroup ? client->appgroup->leader : NULL);
}
Bool XagIsControlledRoot(
ClientPtr client,
WindowPtr pParent)
{
if (client->appgroup) {
if (client->appgroup->single_screen &&
pParent->drawable.id == client->appgroup->default_root)
return TRUE;
else if (!pParent->parent)
return TRUE;
else
return FALSE;
}
return FALSE;
}
void XagConnectionInfo(
ClientPtr client,
xConnSetupPrefix** conn_prefix,
char** conn_info,
int* num_screen)
{
if (client->appgroup && client->appgroup->ConnectionInfo) {
*conn_prefix = &client->appgroup->connSetupPrefix;
*conn_info = client->appgroup->ConnectionInfo;
*num_screen = ((xConnSetup*)(client->appgroup->ConnectionInfo))->numRoots;
}
}
XID XagId(
ClientPtr client)
{
return (client->appgroup ? client->appgroup->appgroupId : 0);
}
void XagGetDeltaInfo(
ClientPtr client,
CARD32* buf)
{
*buf++ = (CARD32) client->appgroup->default_root;
*buf++ = (CARD32) client->appgroup->root_visual;
*buf++ = (CARD32) client->appgroup->default_colormap;
*buf++ = (CARD32) client->appgroup->black_pixel;
*buf = (CARD32) client->appgroup->white_pixel;
}
void XagCallClientStateChange(
CallbackListPtr *pcbl,
pointer nulldata,
pointer calldata)
{
XaceAuthAvailRec* rec = (XaceAuthAvailRec*) calldata;
ClientPtr pClient = rec->client;
if (!pClient->appgroup) {
SecurityAuthorizationPtr pAuth;
XID authId = rec->authId;
pAuth = (SecurityAuthorizationPtr)LookupIDByType(authId,
SecurityAuthorizationResType);
if (!pAuth)
return;
pClient->appgroup = (AppGroupPtr)LookupIDByType(pAuth->group,
RT_APPGROUP);
}
if (pClient->appgroup) {
NewClientInfoRec clientinfo;
clientinfo.client = pClient;
XagClientStateChange (NULL, NULL, (pointer)&clientinfo);
}
}