windowing/windowserver/nga/SERVER/openwfc/CLIENT.CPP
changeset 0 5d03bc08d59c
child 13 1cb83e7796ad
child 19 ac96196b945c
child 36 01a6848ebfd7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/windowing/windowserver/nga/SERVER/openwfc/CLIENT.CPP	Tue Feb 02 01:47:50 2010 +0200
@@ -0,0 +1,2241 @@
+// Copyright (c) 1994-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+// Client handling
+// 
+//
+
+#include "CLIENT.H"
+
+#include "ANIM.H"
+#include "Direct.H"
+#include "EVENT.H"
+#include "KEYCLICK.H"
+#include "server.h"
+#include "gc.h"
+#include "rootwin.h"
+#include "windowgroup.h"
+#include "wstop.h"
+#include "panics.h"
+#include "../CLIENT/w32comm.h"
+#include "password.h"
+#include "pointer.h"
+#include <u32hal.h> // EHalGroupEmulator
+#include "WsMemMgr.h"
+#include <e32hashtab.h>  // for RHashMap
+#include "registeredsurfacemap.h"
+#include <graphics/wselement.h>
+
+#include "windowelementset.h"
+#include "drawresource.h"
+
+extern CDebugLogBase* wsDebugLog;
+_LIT(KWSERVSessionPanicCategory,"WSERV");
+
+GLREF_D TPtr nullDescriptor;
+
+TWsCmdHeaderBase CWsClient::iCurrentCommand;
+TBuf8<EClientBufferMaxSize> CWsClient::iCmdBuf;
+TInt CWsClient::iReply;
+TInt CWsClient::iReplyOffset;
+CWsClient* CWsClient::iCurrentClient;
+CWsObject* CWsClient::iDestObj;
+const TUint8* CWsClient::iNextCmd;
+CIdle* CWsClient::iMoreCommands=NULL;
+
+TUint CWsClient::iConnectionId = CDebugLogBase::EDummyConnectionId+1;
+CArrayFixFlat<CWsClient::TWsCursorArrayItem>* CWsClient::iSystemPointerCursors = NULL;
+TInt CWsClient::iDefaultSystemPointerCursorIndex = 0;		//Negative when there isn't one
+CWsPointerCursor* CWsClient::iDefaultSystemPointerCursor;
+CWsClient* CWsClient::iSystemPointerCursorListOwner = NULL;
+CArrayFixFlat<CWsClient::TWsCursorArrayItem>* CWsClient::iTextCursorArray = NULL;
+
+TKeyArrayFix CWsClient::iCursorKey(_FOFF(CWsClient::TWsCursorArrayItem,iIndex), ECmpTInt);
+
+/**
+Used for enforcing the redraw calling convention in emulator builds.
+When enabled this will panic any client calling a CWindowGc draw operation outside a 
+RWindow::BeginRedraw() / RWindow::EndRedraw() pair (known as non-redraw drawing).
+
+Enable by adding "debug_wserv_exe_EnforceRedrawCallingConvention X" to epoc.ini 
+where X is either 0 (zero) for "off" or 1 (one) for "on". 
+
+Then enable globally in WServ AutoFlush by defining __AUTO_FLUSH in ../client/client.h 
+or locally by calling RWsSession::SetAutoFlush(ETrue) for a specific client programatically, 
+or locally pressing Ctrl-Alt-Shift-F in the emulator.
+*/
+TBool CWsClient::iDebug_EnforceRedrawCallingConvention = EFalse;
+
+// Security policy stings
+static _LIT_SECURITY_POLICY_C1(KSecurityPolicy_WriteDeviceData,ECapabilityWriteDeviceData);
+static _LIT_SECURITY_POLICY_C1(KSecurityPolicy_SwEvent,ECapabilitySwEvent);
+static _LIT_SECURITY_POLICY_C1(KSecurityPolicy_PowerMgmt,ECapabilityPowerMgmt);
+
+//
+// class CWsClient
+// 
+
+CWsClient::CWsClient(RThread aClient) : iClient(aClient), iGraphicMessageQueue(this), iInternalFlags(ERemoveKeyCode|EFinishedProcessingCommands)
+	{
+	iScreen = CWsTop::Screen();
+	}
+
+CWsClient::~CWsClient()
+	{
+	CWsTop::WindowServer()->RemoveAllGraphicDrawers(*this); // deindexes all graphic drawers owned by this client
+
+	delete iTempCustomTextCursor.iCursor;
+	FreeSystemPointerCursorList();
+	CWsTop::ClientDestroyed(this);
+	if (wsDebugLog)
+		{
+		_LIT(ClientDestuct,"Client %d destructing");
+		wsDebugLog->MiscMessage(CDebugLogBase::ELogIntermediate,ClientDestuct, iConnectionHandle);
+		}
+		
+	iInternalFlags |= EClientIsClosing;
+	delete iObjectIndex;
+	delete iEventQueue;
+	delete iRedrawQueue;
+	delete iPriorityKeyEvent;
+	CWsTop::ClearSurfaceMap(this);
+
+	CWsTop::SessionExited(this);
+	iClient.Close();
+	}
+
+void CWsClient::CompleteInitializationL()
+	{
+	iObjectIndex = new(ELeave) CWsObjectIx();
+	iObjectIndex->ConstructL();
+	
+    iEventQueue = new(ELeave) CEventQueue(this);
+	iEventQueue->ConstructL();
+    
+    iRedrawQueue = new(ELeave) CRedrawQueue(this);
+	iRedrawQueue->ConstructL();
+    
+    iPriorityKeyEvent = new(ELeave) CPriorityKey(this);
+	
+	CWsCliObj::NewL(this);
+	
+	iComputeMode = RWsSession::EPriorityControlComputeOff;
+	
+	CWsTop::NewSession(this);
+	
+#ifdef __WINS__
+	TBool halValue = EFalse;
+	if (UserSvr::HalFunction(EHalGroupEmulator, EEmulatorHalIntProperty, 
+		(TAny*)"debug_wserv_exe_EnforceRedrawCallingConvention", &halValue) == KErrNone)
+		{
+		iDebug_EnforceRedrawCallingConvention = halValue;
+		}
+#endif
+	
+	iInternalFlags |= EIsInitialised;
+	}
+
+TBool CWsClient::DebugEnforceRedrawCallingConvention()
+	{
+	return iDebug_EnforceRedrawCallingConvention;
+	}
+
+void CWsClient::StartInitializationL(TUint aConnectionHandle)
+	{
+	if (wsDebugLog)
+		wsDebugLog->NewClient(aConnectionHandle);
+	
+	if (iObjectIndex)
+		PPanic(EWservPanicReInitialise);
+	else
+		{
+		iConnectionHandle = aConnectionHandle;
+		CompleteInitializationL();
+		}
+	}
+
+//
+// Convert a handle to object checking it is of the correct type.
+//
+void CWsClient::HandleToWindow(TInt aHandle,CWsWindowBase** pWin)
+	{
+	if ((*pWin=(CWsWindowBase* )HandleToObjUntyped(aHandle))==NULL ||
+		((*pWin)->Type()!=WS_HANDLE_WINDOW && (*pWin)->Type()!=WS_HANDLE_GROUP_WINDOW))
+		PPanic(EWservPanicWindow);
+	}
+
+//
+// Convert a handle to object checking it is of the correct type.
+//
+void CWsClient::HandleToClientWindow(TInt aHandle,CWsClientWindow** pWin)
+	{
+	if ((*pWin=(CWsClientWindow*)HandleToObj(aHandle, WS_HANDLE_WINDOW))==NULL)
+		PPanic(EWservPanicWindow);
+	}
+
+void CWsClient::CreateNewPointerCursorL(const TWsClCmdCreatePointerCursor &aCmd)
+	{
+	CWsPointerCursor* pc=new(ELeave) CWsPointerCursor(this);
+	CleanupStack::PushL(pc);
+	pc->ConstructL(aCmd);
+	CleanupStack::Pop();
+	}
+
+// Create a new custom text cursor
+void CWsClient::StartSetCustomTextCursorL(const TWsClCmdCustomTextCursorData& aCmd)
+	{
+	if (!iTextCursorArray)
+		{
+		const TInt textCursorArrayGranularity = 4;
+		iTextCursorArray = new(ELeave) CArrayFixFlat<TWsCursorArrayItem>(textCursorArrayGranularity);
+		}
+		
+	TInt arrayIndex = KErrNotFound;
+	if (FindCursorArrayItem(iTextCursorArray, aCmd.identifier, arrayIndex))
+		User::Leave(KErrAlreadyExists);
+	
+	delete iTempCustomTextCursor.iCursor;
+	iTempCustomTextCursor.iCursor = NULL;
+	iTempCustomTextCursor.iCursor = new(ELeave) CWsCustomTextCursor(this, aCmd.alignment);
+	
+	static_cast<CWsCustomTextCursor*>(iTempCustomTextCursor.iCursor)->ConstructL(aCmd.flags);
+	iTempCustomTextCursor.iIndex = aCmd.identifier;
+	}
+
+// Add new custom text cursor to global list
+void CWsClient::CompleteSetCustomTextCursorL(TInt aError)
+	{
+	if (aError)
+		{
+		delete iTempCustomTextCursor.iCursor;
+		iTempCustomTextCursor.iCursor = NULL;
+		User::Leave(aError);
+		}
+
+	TWsCursorArrayItem entry = iTempCustomTextCursor;
+	iTempCustomTextCursor.iCursor = NULL;
+	CleanupStack::PushL(entry.iCursor);
+
+	TInt arrayIndex;
+	if (FindCursorArrayItem(iTextCursorArray, entry.iIndex, arrayIndex))
+		User::Leave(KErrAlreadyExists);
+	else
+		iTextCursorArray->InsertIsqL(entry, iCursorKey);
+
+	CleanupStack::Pop(entry.iCursor);
+	}
+
+CWsCustomTextCursor* CWsClient::FindCustomTextCursor(TInt aIdentifier)
+	{
+	TInt arrayIndex;
+	if (!FindCursorArrayItem(iTextCursorArray, aIdentifier, arrayIndex))
+		return NULL;
+
+	return TextCursor(arrayIndex);
+	}
+
+void CWsClient::CreateNewSpriteL(const TWsClCmdCreateSprite &aCmd)
+	{
+	CWsSprite* sprite = new(ELeave) CWsSprite(this);
+	CleanupStack::PushL(sprite);
+	sprite->ConstructL(aCmd);
+	CleanupStack::Pop();
+	}
+
+void CWsClient::CreateNewBitmapL(const TWsClCmdCreateBitmap &aCmd)
+	{
+	DWsBitmap* bitmap = new(ELeave) DWsBitmap(this);
+	CleanupStack::PushL(bitmap);
+	bitmap->ConstructL(aCmd);
+	CleanupStack::Pop();
+	}
+
+/** Creates a new window.
+
+If the parent is a window group then a new CWsTopClientWindow instance is created. If the parent is
+a window then a new CWsClientWindow instance is created.
+
+@param aCmd The command received from the client
+@internalComponent
+@released
+*/
+void CWsClient::CreateNewWindowL(const TWsClCmdCreateWindow &aCmd)
+	{
+	CWsWindowBase* parent;
+	HandleToWindow(aCmd.parent,&parent);
+	CWsClientWindow* win = NULL;
+	TBool deviceIsInvalid = EFalse;
+	CScreen* screen = parent->Screen();
+	if (parent->WinType()==EWinTypeGroup)
+		{
+		__ASSERT_DEBUG(!((CWsWindowGroup*)parent)->ScreenDeviceDeleted(),PPanic(EWservPanicGroupWinScreenDeviceDeleted));
+		win=new(ELeave) CWsTopClientWindow(this, screen);
+		deviceIsInvalid=!((CWsWindowGroup*)parent)->ScreenDeviceValid();
+		}
+	else
+		win=new(ELeave) CWsClientWindow(this, screen);
+
+	CleanupStack::PushL(win);
+	win->ConstructL(aCmd,parent,deviceIsInvalid);
+	CleanupStack::Pop(win);
+	}
+
+void CWsClient::CreateNewWindowGroupL(const TWsClCmdCreateWindowGroup &aCmd)
+	{
+	CWsWindowGroup::NewL(this, NULL, aCmd); //screen is initialised inside the constructL
+	}
+
+void CWsClient::CreateNewAnimDllL(const TWsClCmdUnion &aParams)
+	{
+	CWsAnimDll* animDll = new(ELeave) CWsAnimDll(this);
+	CleanupStack::PushL(animDll);
+	animDll->LoadL(BufferTPtr((TText*)(aParams.LoadAnimDll+1),aParams.LoadAnimDll->length));
+	CleanupStack::Pop();
+	}	
+
+void CWsClient::CreateNewScreenDeviceL(TInt aDefaultScreenNumber, TUint aClientScreenDevicePointer)
+	{
+	DWsScreenDevice* screenDevice = new(ELeave) DWsScreenDevice(this, aDefaultScreenNumber,aClientScreenDevicePointer);
+	CleanupStack::PushL(screenDevice);
+	screenDevice->ConstructL();
+	CleanupStack::Pop(screenDevice);
+	if (iPrimaryScreenDevice==NULL)
+		{
+		iPrimaryScreenDevice=screenDevice;
+		// When client create screen device, change default screen to the one specified.
+		// Client should do this immediately after establishing session
+		iScreen = iPrimaryScreenDevice->Screen();
+		InitialiseScreenDevices();
+		}
+	}
+
+void CWsClient::InitialiseScreenDevices()
+	{
+	const TWsObject* ptr = iObjectIndex->FirstObject();
+	const TWsObject* end = ptr+iObjectIndex->Length();
+	WS_ASSERT_DEBUG(ptr->iObject==NULL, EWsPanicObjectIndexError);
+	while(++ptr<end)
+		{
+		if (ptr->iObject && ptr->iObject->Type()==WS_HANDLE_GROUP_WINDOW)
+			{
+			CWsWindowGroup* gw = static_cast<CWsWindowGroup*>(ptr->iObject);
+			if(!gw->Device())
+				gw->SetScreenDevice(iPrimaryScreenDevice);
+			}
+		}
+	}
+
+void CWsClient::CreateNewClickHandlerL(const TUid& aUid)
+	{
+	CClick* click = new(ELeave) CClick(this);
+	CleanupStack::PushL(click);
+	click->ConstructL(aUid);
+	CleanupStack::Pop(click);
+	}
+
+void CWsClient::RequestComplete(TRequestStatus*  &aStatus, TInt aErr)
+	{
+	Client().RequestComplete(aStatus,aErr);
+	}
+
+void CWsClient::PanicCurrentClient(TClientPanic aPanic)
+	{
+	iCurrentClient->PPanic(aPanic);
+	}
+
+void CWsClient::PPanic(TClientPanic aPanic) const
+//This function is allowed to leave with out the 'L' convention for special reasons
+	{
+	SessionPanic(aPanic);
+	User::Leave(EPanicLeave);
+	}
+
+void CWsClient::SessionPanic(TClientPanic aReason) const
+	{
+	if (wsDebugLog)
+		wsDebugLog->Panic(iConnectionHandle, aReason);
+	
+	if (!(iInternalFlags&EPanicClientAsSoonAsPossible)) // keep the first error code
+		{
+		iInternalFlags |= EPanicClientAsSoonAsPossible;
+		iPanicReason = aReason;
+		}
+	}
+
+void CWsClient::SessionTerminate()
+	{
+	if (wsDebugLog)
+		wsDebugLog->Panic(iConnectionHandle, 0);
+
+	const RThread thread=Client();
+	RProcess process;
+	if (thread.Process(process)==KErrNone)
+		{
+		process.Terminate(0);
+		process.Close();
+		}
+	}
+
+/**	
+Returns the remaining space in the descriptor
+*/
+TInt CWsClient::ReplyBufSpace() 
+	{
+	const TInt retVal = iCurrentClient->ClientMessage().GetDesLength(KReplyBufferMessageSlot);
+	
+	if (iReplyOffset>=0 && retVal>=iReplyOffset)
+		return retVal-iReplyOffset;
+	else
+		return (retVal<0 ? retVal : KErrBadDescriptor);
+	}
+
+void CWsClient::ReplyBuf(const TDesC16 &aDes)	// static
+	{
+	WS_ASSERT_DEBUG(!iCurrentClient->ClientMessage().IsNull(), EWsPanicInvalidMessageHandle);
+	
+	if(iCurrentClient->ClientMessage().Write(KReplyBufferMessageSlot,aDes,iReplyOffset) != KErrNone)
+		PanicCurrentClient(EWservPanicDescriptor);
+	
+	iReplyOffset += aDes.Length();
+	if (wsDebugLog)
+		wsDebugLog->ReplyBuf(aDes);
+	}
+
+void CWsClient::ReplyBuf(const TDesC8 &aDes)	// static
+	{
+	WS_ASSERT_DEBUG(!iCurrentClient->ClientMessage().IsNull(), EWsPanicInvalidMessageHandle);
+	
+	if(iCurrentClient->ClientMessage().Write(KReplyBufferMessageSlot, aDes, iReplyOffset) != KErrNone)
+		PanicCurrentClient(EWservPanicDescriptor);
+	
+	iReplyOffset += aDes.Length();
+	if (wsDebugLog)
+		wsDebugLog->ReplyBuf(aDes);
+	}
+
+void CWsClient::ReplyBuf(const TAny* aSource, TInt aLength)	// static
+//
+// Send a buffer to the client process.
+//
+	{
+	TPtrC8 src(reinterpret_cast<const TUint8*>(aSource),aLength);
+	ReplyBuf(src);
+	}
+
+void CWsClient::ReplySize(const TSize &aSize)	// static
+	{
+	ReplyBuf(&aSize, sizeof(aSize));
+	}
+
+void CWsClient::ReplyPoint(const TPoint &aPoint)	// static
+	{
+	ReplyBuf(&aPoint, sizeof(aPoint));
+	}
+
+void CWsClient::ReplyRect(const TRect &aRect)	// static
+	{
+	ReplyBuf(&aRect, sizeof(aRect));
+	}
+
+void CWsClient::SetReply(TInt reply)
+	{
+	iReply = reply;
+	if (wsDebugLog)
+		wsDebugLog->Reply(reply);
+	}
+
+const TUint8* CWsClient::EndOfCommandBuffer()
+	{
+	return(iCmdBuf.Ptr()+iCmdBuf.Size());
+	}
+
+const TPtrC CWsClient::BufferTPtr(TText *aStart,TInt aLen)
+	{
+	TPtrC ptr;
+	if (!BufferTPtrGc(aStart,aLen,ptr))
+		PanicCurrentClient(EWservPanicBufferPtr);
+	return(ptr);
+	}
+
+TBool CWsClient::BufferTPtrGc(TText* aStart,TInt aLen, TPtrC& aPtr)
+	{
+	if (iCurrentCommand.iOpcode>0)
+		{
+		if ((REINTERPRET_CAST(TUint8*,aStart)<iCmdBuf.Ptr()
+										|| REINTERPRET_CAST(TUint8*,aStart+aLen)>(iCmdBuf.Ptr()+iCmdBuf.Size())))
+			return(EFalse);
+		}
+	else
+		{
+		if (aLen>=iCurrentCommand.iCmdLength)
+			return(EFalse);
+		}
+	aPtr.Set(aStart,aLen);
+	return(ETrue);
+	}
+
+const TPtrC8 CWsClient::BufferTPtr8(TUint8* aStart,TInt aLen)
+	{
+	if (iCurrentCommand.iOpcode>0 && (REINTERPRET_CAST(TUint8*,aStart)<iCmdBuf.Ptr()
+										|| REINTERPRET_CAST(TUint8*,aStart+aLen)>(iCmdBuf.Ptr()+iCmdBuf.Size())))
+		PanicCurrentClient(EWservPanicBufferPtr);
+		
+	return(TPtrC8(aStart,aLen));
+	}
+
+/**
+Process a command buffer
+
+@internalComponent
+@released
+*/
+void CWsClient::DispatchCommandsInBufL()	// (step #4)
+	{		
+	if (wsDebugLog)
+		{
+ 		wsDebugLog->CommandBuf(iConnectionHandle);
+ 		RThread client = Client(); 
+ 		wsDebugLog->MiscMessage(CDebugLogBase::ELogEverything, client.FullName());
+		}
+	const TUint8* endCmd=iCmdBuf.Ptr()+iCmdBuf.Length();
+	do
+		{
+		const TWsCmdHeader* pCmd=
+				reinterpret_cast<const TWsCmdHeader*>(iNextCmd);
+		TUint opcode = pCmd->iBase.iOpcode;
+		TInt headerLen = sizeof(pCmd->iBase);
+		iCurrentCommand = pCmd->iBase;
+		
+		// For performance reasons the handle is only included
+		// if it is different from the previous command. The EWsOpcodeHandle
+		// flag indicates whether a new handle has been included in the
+		// current command. If not we use the same handle as the previous
+		// command.
+		if (opcode&EWsOpcodeHandle)
+			{
+			// Find the WServ object associated with this op code
+			opcode &= ~EWsOpcodeHandle;
+			iCurrentCommand.iOpcode = reinterpret_cast<TUint16&>(opcode);
+			iDestObj=HandleToObjUntyped(pCmd->iDestHandle);
+			headerLen = sizeof(*pCmd);
+			}
+			
+		iNextCmd += headerLen;
+		const TAny* cmdParams = iNextCmd;
+		iNextCmd += pCmd->iBase.iCmdLength;
+		if (!iDestObj || iNextCmd>endCmd)		// Invalid handle or Corrupt buffer
+			{
+			SessionPanic(iDestObj==NULL ? EWservPanicHandle : EWservPanicBuffer);
+			iInternalFlags|=EFinishedProcessingCommands;
+			break;
+			}
+
+		if (iNextCmd==endCmd)
+			iInternalFlags|=EFinishedProcessingCommands;
+			
+		if (wsDebugLog)
+			wsDebugLog->Command(iDestObj->Type(), opcode, cmdParams, iDestObj->LogHandle());
+		
+		// Dispatch the command to the WServ object that will process it
+		iDestObj->CommandL(opcode, cmdParams);	// (call #5)
+		} 
+	while(iNextCmd<endCmd && !TWindowServerEvent::EventReceiver()->IsReadyToRun());
+	
+	}
+
+void CWsClient::DoServiceCommandBuf() // (step #3.1)
+	{
+	iCurrentClient=this;
+	iInternalFlags&=~EFinishedProcessingCommands;
+	TRAPD(err, DispatchCommandsInBufL());	// (call #4)
+	
+#if defined(_DEBUG)
+	if (err!=KErrNone && !(iInternalFlags&(EFinishedProcessingCommands|EPanicClientAsSoonAsPossible)))
+		SessionPanic(EWservPanicFunctionLeave);
+#endif
+
+	if (err<KErrNone)
+		SetReply(err);
+
+	if (iInternalFlags&(EFinishedProcessingCommands|EPanicClientAsSoonAsPossible))
+		CompleteMessage(iClientMessage,iReply);	// (finish)
+	else
+		iMoreCommands->Start(TCallBack(CWsClient::DoContinueDeferredServiceOfCommandBuf,this));	// (call #3.1.1)
+	
+	iCurrentClient=NULL;
+#if defined(_DEBUG)
+	User::Heap().Check();
+#endif
+	}
+
+TInt CWsClient::DoContinueDeferredServiceOfCommandBuf(TAny* aClient)	// (step #3.1.1)
+	{
+	static_cast<CWsClient*>(aClient)->DoServiceCommandBuf();	// (call #3.1)
+	return KErrNone;
+	}
+
+
+void CWsClient::ExecuteAsyncClientCommandL(TInt aOpcode, const RMessage2& aMessage)	// (step #3.2)
+	{
+	switch(aOpcode)
+		{
+		case EWsClOpEventReady:
+			EventReady(aMessage);
+			break;
+		case EWsClOpPriorityKeyReady:
+			PriorityKeyEventReady(aMessage);
+			break;
+		case EWsClOpRedrawReady:
+			RedrawEventReady(aMessage);
+			break;
+		case EWsClOpGraphicMessageReady:
+			iGraphicMessageQueue.EventReady(aMessage);
+			break;
+		default:
+			{
+			PPanic(EWservPanicOpcode);
+			break;
+			}
+		}
+	}
+
+
+
+void CWsClient::ExecuteCommandL(TInt aOpcode, const TAny* aCmdData)	// (step #6)
+	{
+	TWsClCmdUnion pData;
+	pData.any=aCmdData;
+	switch(aOpcode)
+		{
+		case EWsClOpCreateWindowGroup:
+			CreateNewWindowGroupL(*pData.CreateWindowGroup);
+			break;
+		case EWsClOpCreateWindow:
+			CreateNewWindowL(*pData.CreateWindow);
+			break;
+		case EWsClOpCreateGc:
+			CWsGc::NewL(this);
+			break;
+		case EWsClOpCreateAnimDll:
+			if (!CheckBuffer(pData.LoadAnimDll->length, KMaxFileName))
+				PanicCurrentClient(EWservPanicBufferPtr);
+			CreateNewAnimDllL(pData);
+			break;
+		case EWsClOpCreateGraphic:
+			CWsGraphicDrawerObject::NewL(this,pData);
+			break;
+		case EWsClOpCreateScreenDevice:
+			{
+			const TInt screenNumber = pData.CreateScreenDevice->screenNumber;
+			const TUint clientScreenDevicePointer = pData.CreateScreenDevice->clientScreenDevicePointer;
+			if (screenNumber<0 || screenNumber>=CWsTop::NumberOfScreens())
+				{
+				PPanic(EWservPanicScreenNumber);
+				}
+			else
+				{
+				CreateNewScreenDeviceL(screenNumber,clientScreenDevicePointer);
+				}
+			}
+			break;
+		case EWsClOpCreateSprite:
+			CreateNewSpriteL(*pData.CreateSprite);
+			break;
+		case EWsClOpCreatePointerCursor:
+			CreateNewPointerCursorL(*pData.CreatePointerCursor);
+			break;
+		case EWsClOpStartSetCustomTextCursor:
+			StartSetCustomTextCursorL(*pData.CustomTextCursorData);
+			break;
+		case EWsClOpCompleteSetCustomTextCursor:
+			CompleteSetCustomTextCursorL(*pData.Int);
+			break;
+		case EWsClOpCreateBitmap:
+			CreateNewBitmapL(*pData.CreateBitmap);
+			break;
+		case EWsClOpCreateDirectScreenAccess:
+			CWsDirectScreenAccess::NewL(this,EFalse);
+			break;
+		case EWsClOpCreateDirectScreenAccessRegionTrackingOnly:
+			CWsDirectScreenAccess::NewL(this,ETrue);	//creates a DSA object that will not draw to the screen, but will use just the region tracking functionality
+			break;
+		case EWsClOpCreateClick:
+			CreateNewClickHandlerL(*pData.Uid);
+			break;
+		case EWsClOpSetHotKey:
+			{
+			if(!KSecurityPolicy_SwEvent().CheckPolicy(ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWsSession::SetHotKey API")))
+				{
+				User::Leave(KErrPermissionDenied);
+				}
+			TWindowServerEvent::SetHotKeyL(*pData.SetHotKey);
+			}
+			break;
+		case EWsClOpClearHotKeys:
+			{
+			if(!KSecurityPolicy_SwEvent().CheckPolicy(ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWsSession::ClearHotKeys API")))
+				{
+				User::Leave(KErrPermissionDenied);
+				}
+			TWindowServerEvent::ClearHotKeysL(*pData.UInt);
+			}
+			break;
+		case EWsClOpRestoreDefaultHotKey:
+			TWindowServerEvent::ResetDefaultHotKeyL(*pData.UInt);
+			break;
+		case EWsClOpSetShadowVector:
+			PPanic(EWservPanicOpcode); //this op code is deprecated, should never be generated by the client
+			break;
+		case EWsClOpShadowVector:
+			PPanic(EWservPanicOpcode); //this op code is deprecated, should never be generated by the client
+			break;
+		case EWsClOpSetKeyboardRepeatRate:
+			{
+			if(!KSecurityPolicy_WriteDeviceData().CheckPolicy(ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWsSession::SetKeyboardRepeatRate API")))
+				{
+				User::Leave(KErrPermissionDenied);
+				}
+			if ((pData.SetKeyboardRepeatRate->initial.Int()<0) || (pData.SetKeyboardRepeatRate->time.Int()<0))
+				{
+				User::Leave(KErrArgument);
+				}
+			CKeyboardRepeat::SetRepeatTime(pData.SetKeyboardRepeatRate->initial,pData.SetKeyboardRepeatRate->time);
+			}
+			break;
+		case EWsClOpGetKeyboardRepeatRate:
+			{
+			SKeyRepeatSettings settings;
+			CKeyboardRepeat::GetRepeatTime(settings.iInitialTime,settings.iTime);
+			ReplyBuf(&settings,sizeof(settings));
+			}
+			break;
+		case EWsClOpSetDoubleClick:
+			{
+			if(!KSecurityPolicy_WriteDeviceData().CheckPolicy(ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWsSession::SetDoubleClick API")))
+				{
+				User::Leave(KErrPermissionDenied);
+				}
+			TWsPointer::SetDoubleClick(pData.SetDoubleClick->interval,pData.SetDoubleClick->distance);
+			}
+			break;
+		case EWsClOpGetDoubleClickSettings:
+			{
+			SDoubleClickSettings settings;
+			TWsPointer::GetDoubleClickSettings(settings.iInterval,settings.iDistance);
+			ReplyBuf(&settings,sizeof(settings));
+			}
+			break;
+		case EWsClOpEventReady:
+			// No need to do anything
+			break;
+		case EWsClOpGetEvent:
+			HandleClientRequestForEventData();
+			// Check flag if the group message queue is overflow and has pended messages  
+			if (iInternalFlags & EWgMsgQueueOverflow)
+				{
+				iInternalFlags &= ~EWgMsgQueueOverflow;
+				CWsWindowGroup::ReleasePendedMessagesToAllGroups(this);
+				}
+			break;
+		case EWsClOpPurgePointerEvents:
+			PurgePointerEvents();
+			break;
+		case EWsClOpEventReadyCancel:
+			CancelClientRequestForEventData();
+			break;
+		case EWsClOpRedrawReady:
+			iInternalFlags&=~EIsPerformingRedrawEvent;
+			break;
+		case EWsClOpRedrawReadyCancel:
+			CancelClientRequestForRedrawEvent();
+			break;
+		case EWsClOpGetRedraw:
+			HandleClientRequestForRedrawData();
+			break;
+		case EWsClOpPriorityKeyReady:
+			// No need to do anything
+			break;
+		case EWsClOpPriorityKeyReadyCancel:
+			CancelClientRequestForPriorityKeyEvent();
+			break;
+		case EWsClOpGetPriorityKey:
+			HandleClientRequestForPriorityKeyData();
+			break;
+		case EWsClOpNumWindowGroups:
+			SetReply(CWsWindowGroup::NumWindowGroups(EFalse,* pData.Int));
+			break;
+		case EWsClOpNumWindowGroupsAllPriorities:
+			SetReply(CWsWindowGroup::NumWindowGroups(ETrue, 0));
+			break;
+		case EWsClOpNumWindowGroupsOnScreen:
+			{
+			const TInt screenNumber=pData.NumWinGroups->screenNumber;
+			if (screenNumber<0 || screenNumber>=CWsTop::NumberOfScreens())
+				PPanic(EWservPanicScreenNumber);
+			else
+				SetReply(CWsWindowGroup::NumWindowGroupsOnScreen(CWsTop::Screen(screenNumber)->RootWindow()->Child(),(pData.NumWinGroups->priority==EAllPriorities),pData.NumWinGroups->priority));
+			}
+			break;
+		case EWsClOpWindowGroupList:
+			{
+			const TInt screenNumber=pData.WindowGroupList->screenNumber;
+			if (screenNumber<KDummyScreenNumber || screenNumber>=CWsTop::NumberOfScreens())
+				PPanic(EWservPanicScreenNumber);
+			else
+				SetReply(CWsWindowGroup::SendWindowGroupListL(screenNumber,(pData.WindowGroupList->priority==EAllPriorities), pData.WindowGroupList->priority, pData.WindowGroupList->count));
+			}
+			break;
+		case EWsClOpWindowGroupListAllPriorities:
+			{
+			const TInt screenNumber=pData.WindowGroupList->screenNumber;
+			if (screenNumber<KDummyScreenNumber || screenNumber>=CWsTop::NumberOfScreens())
+				PPanic(EWservPanicScreenNumber);
+			else
+				SetReply(CWsWindowGroup::SendWindowGroupListL(screenNumber,ETrue, 0, pData.WindowGroupList->count));
+			}
+			break;
+		case EWsClOpWindowGroupListAndChain:
+			SetReply(CWsWindowGroup::SendWindowGroupListAndChainL(EFalse, pData.WindowGroupList->priority, pData.WindowGroupList->count));
+			break;
+		case EWsClOpWindowGroupListAndChainAllPriorities:
+			SetReply(CWsWindowGroup::SendWindowGroupListAndChainL(ETrue, 0, pData.WindowGroupList->count));
+			break;
+		case EWsClOpGetDefaultOwningWindow:
+			{
+			const TInt screenNumber = *pData.Int;
+			if (screenNumber<KDummyScreenNumber || screenNumber>=CWsTop::NumberOfScreens())
+				PPanic(EWservPanicScreenNumber);
+			else
+				{
+				CScreen* screen = (screenNumber ==KDummyScreenNumber) ? iScreen : CWsTop::Screen(screenNumber);
+				SetReply(screen->DefaultOwningWindowGroup() ? screen->DefaultOwningWindowGroup()->Identifier():0);
+				}
+			}
+			break;
+		case EWsClOpGetFocusWindowGroup:
+			{
+			const TInt screenNumber = *pData.Int;
+			if (screenNumber<KDummyScreenNumber || screenNumber>=CWsTop::NumberOfScreens())
+				PPanic(EWservPanicScreenNumber);
+			else
+				CWsWindowGroup::GetFocusWindowGroupL(screenNumber);
+			}
+			break;
+		case EWsClOpSetWindowGroupOrdinalPosition:
+			CWsWindowGroup::WindowGroupFromIdentifierL(pData.SetWindowGroupOrdinalPosition->identifier)->SetOrdinalPosition(pData.SetWindowGroupOrdinalPosition->position);
+			break;
+		case EWsClOpGetWindowGroupHandle:
+			SetReply(CWsWindowGroup::WindowGroupFromIdentifierL(*pData.Int)->ClientHandle());
+			break;
+		case EWsClOpGetWindowGroupOrdinalPriority:
+			SetReply(CWsWindowGroup::WindowGroupFromIdentifierL(*pData.Int)->OrdinalPriority());
+			break;
+		case EWsClOpGetWindowGroupClientThreadId:
+			{
+			TThreadId id=CWsWindowGroup::WindowGroupFromIdentifierL(*pData.Int)->WsOwner()->Client().Id();
+			ReplyBuf(&id,sizeof(id));
+			}
+			break;
+		case EWsClOpSendEventToWindowGroup:
+			{
+			CWsWindowGroup* group=CWsWindowGroup::WindowGroupFromIdentifierL(pData.SendEventToWindowGroup->parameter);
+			TWsEvent event=pData.SendEventToWindowGroup->event;
+			event.SetHandle(group->ClientHandle());
+			// Events in enum TEventCode is protected by capabilities
+			if (group->WsOwner()!=this && event.Type()>=EEventNull && event.Type()<EEventUser)
+				{
+				if (event.Type()<EEventPowerMgmt || event.Type()>=EEventReserved)
+					{
+					if(!KSecurityPolicy_SwEvent().CheckPolicy(ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWsSession::SendEventToWindowGroup API")))
+						User::Leave(KErrPermissionDenied);
+					}
+				else
+					{
+					if (!KSecurityPolicy_PowerMgmt().CheckPolicy(ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWsSession::SendEventToWindowGroup API")))
+						User::Leave(KErrPermissionDenied);
+					}
+				}
+			if (event.Type()==EEventKey && event.Key()->iRepeats!=0)
+				CKeyboardRepeat::CancelRepeat(NULL);		//Otherwise we will trip an invarient
+			if (!group->EventQueue()->QueueEvent(event))
+				User::Leave(KErrNoMemory);
+			}
+			break;
+		case EWsClOpSendEventToAllWindowGroup:
+		case EWsClOpSendEventToAllWindowGroupPriority:
+		case EWsClOpSendEventToOneWindowGroupPerClient:
+			{
+			TWsEvent event=pData.SendEventToWindowGroup->event;
+			if (event.Type()<0)
+				User::Leave(KErrArgument);
+			if(event.Type()<EEventUser)
+				{
+				if (event.Type()<EEventPowerMgmt || event.Type()>=EEventReserved)
+					{
+					if(!KSecurityPolicy_SwEvent().CheckPolicy(ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWsSession::SendEventToAllWindowGroup API")))
+						User::Leave(KErrPermissionDenied);
+					}
+				else 
+					{
+					if (!KSecurityPolicy_PowerMgmt().CheckPolicy(ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWsSession::SendEventToAllWindowGroup API")))
+						User::Leave(KErrPermissionDenied);
+					}
+				}
+			if (!CWsWindowGroup::SendEventToAllGroups(aOpcode!=EWsClOpSendEventToAllWindowGroupPriority
+													,aOpcode==EWsClOpSendEventToOneWindowGroupPerClient,*pData.SendEventToWindowGroup))
+				User::Leave(KErrNoMemory);
+			}
+			break;
+		case EWsClOpSendMessageToWindowGroup:
+			{
+			CWsWindowGroup* group=CWsWindowGroup::WindowGroupFromIdentifierL(pData.SendMessageToWindowGroup->identifierOrPriority);
+			if (group->WsOwner()!=this)
+				{
+				if (!KSecurityPolicy_SwEvent().CheckPolicy(ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWsSession::SendMessageToWindowGroup API")))
+					{
+					User::Leave(KErrPermissionDenied);
+					}
+				}
+			group->QueueMessageL(pData.SendMessageToWindowGroup->uid, pData.SendMessageToWindowGroup->dataLength,* this);
+			}
+			break;
+		case EWsClOpSendMessageToAllWindowGroups:
+		case EWsClOpSendMessageToAllWindowGroupsPriority:
+			{
+			if ((pData.SendMessageToWindowGroup->dataLength<0) || (pData.SendMessageToWindowGroup->dataLength>=(KMaxTInt/2)))
+				{
+				User::Leave(KErrArgument);
+				}
+			CWsWindowGroup::SendMessageToAllGroupsL(*this,aOpcode==EWsClOpSendMessageToAllWindowGroups,*pData.SendMessageToWindowGroup);
+			}
+			break;
+		case EWsClOpFetchMessage:
+			CWsWindowGroup::WindowGroupFromIdentifierL(pData.FetchMessage->windowGroupIdentifier)->FetchMessageL();
+			break;
+		case EWsClOpGetWindowGroupNameFromIdentifier:
+			ReplyGroupName(CWsWindowGroup::WindowGroupFromIdentifierL(pData.GetWindowGroupNameFromIdentifier->identifier)->GroupName(),pData.GetWindowGroupNameFromIdentifier->maxLength);
+			break;
+		case EWsClOpFindWindowGroupIdentifier:
+			{
+			if (pData.FindWindowGroupIdentifier->length<0)
+				User::Leave(KErrArgument);
+			TPtrC ptr(BufferTPtr((TText*)(pData.FindWindowGroupIdentifier+1),pData.FindWindowGroupIdentifier->length));
+			SetReply(CWsWindowGroup::FindWindowGroupL(this, pData.FindWindowGroupIdentifier->identifier,
+							pData.FindWindowGroupIdentifier->offset,&ptr,NULL)->Identifier());
+			}
+			break;
+		case EWsClOpFindWindowGroupIdentifierThread:
+			SetReply(CWsWindowGroup::FindWindowGroupL(this, pData.FindWindowGroupIdentifierThread->identifier,0,NULL,
+											&pData.FindWindowGroupIdentifierThread->threadId)->Identifier());
+			break;
+		case EWsClOpSetBackgroundColor:
+			for(TInt i=0;i<CWsTop::NumberOfScreens();i++)
+				{
+				CWsTop::Screen(i)->RootWindow()->SetColor(*pData.rgb);
+				}
+			break;
+		case EWsClOpGetBackgroundColor:
+			SetReply(iScreen->RootWindow()->BackColor().Internal());
+			break;
+		case EWsClOpClaimSystemPointerCursorList:
+			{
+			if(!KSecurityPolicy_WriteDeviceData().CheckPolicy(ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWsSession::ClaimSystemPointerCursorList API")))
+				{
+				User::Leave(KErrPermissionDenied);
+				}
+			ClaimSystemPointerCursorListL();
+			}
+			break;
+		case EWsClOpFreeSystemPointerCursorList:
+			FreeSystemPointerCursorList();
+			break;
+		case EWsClOpSetSystemPointerCursor:
+			{
+			CWsObject* pointercursor = NULL;
+			if ((pointercursor=HandleToObj(pData.SetSystemPointerCursor->handle, WS_HANDLE_POINTER_CURSOR))==NULL)
+				PPanic(EWservPanicSprite);
+			
+			SetSystemPointerCursorL(pData.SetSystemPointerCursor->number, (CWsPointerCursor* )pointercursor);
+			}
+			break;
+		case EWsClOpClearSystemPointerCursor:
+			ClearSystemPointerCursor(*pData.Int);
+			break;
+		case EWsClOpSetPointerCursorArea:
+			{
+			if(KSecurityPolicy_WriteDeviceData().CheckPolicy(ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWsSession::SetPointerCursorArea API")))
+				{
+				if (!iScreen->IsValidScreenSizeMode(*pData.Int))
+					PPanic(EWservPanicScreenModeNumber);
+				iScreen->SetPointerCursorArea(pData.SetPointerCursorArea->mode,pData.SetPointerCursorArea->area);
+				}
+			}
+			break;
+		case EWsClOpPointerCursorArea:
+			if (!iScreen->IsValidScreenSizeMode(*pData.Int))
+				PPanic(EWservPanicScreenModeNumber);
+			
+			ReplyRect(iScreen->GetPointerCursorArea(*pData.Int));
+			break;
+		case EWsClOpSetPointerCursorMode:
+			{
+			CWsWindowGroup* focusWinGp=CWsTop::FocusWindowGroup();
+			if (focusWinGp && focusWinGp->WsOwner()==this)
+				{
+				TWsPointer::SetPointerCursorMode(*pData.Mode);
+				TWsPointer::UpdatePointerCursor();
+				}
+			}
+			break;
+		case EWsClOpSetClientCursorMode :
+			{
+			if(!KSecurityPolicy_WriteDeviceData().CheckPolicy(ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWsSession::SetPointerCursorModeIfFocused API")))
+				{
+				User::Leave(KErrPermissionDenied);
+				}
+			TWsPointer::SetPointerCursorMode(*pData.Mode);
+			TWsPointer::UpdatePointerCursor();
+			}
+			break;
+		case EWsClOpPointerCursorMode:
+			SetReply(TWsPointer::PointerCursorMode());
+			break;
+		case EWsClOpSetDefaultSystemPointerCursor:
+			SetDefaultSystemPointerCursor(*pData.Int);
+			break;
+		case EWsClOpClearDefaultSystemPointerCursor:
+			SetDefaultSystemPointerCursor(ENoDefaultSystemPointerCursor);
+			break;
+		case EWsClOpSetPointerCursorPosition:
+			{
+			CWsWindowGroup* focusWinGp=CWsTop::FocusWindowGroup();
+			if ((!focusWinGp || focusWinGp->WsOwner()!=this)&&
+				(!KSecurityPolicy_WriteDeviceData().CheckPolicy(ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWsSession::SetPointerCursorPosition API"))))
+				{
+				User::Leave(KErrPermissionDenied);
+				}
+			TWsPointer::SetPointerCursorPos(*pData.Point);
+			}
+			break;
+		case EWsClOpPointerCursorPosition:
+			ReplyPoint(TWsPointer::PointerCursorPos());
+			break;
+		case EWsClOpSetModifierState:
+			{
+			if(!KSecurityPolicy_WriteDeviceData().CheckPolicy(ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWsSession::SetModifierState API")))
+				{
+				User::Leave(KErrPermissionDenied);
+				}
+			TWindowServerEvent::SetModifierState(pData.SetModifierState->modifier,pData.SetModifierState->state);
+			}
+			break;
+		case EWsClOpGetModifierState:
+			SetReply(TWindowServerEvent::GetModifierState());
+			break;
+		case EWsClOpHeapCount:
+			SetReply(CWsMemoryManager::Static()->Count());
+			break;
+ 		case EWsClOpDebugInfo:
+			DebugInfoL(pData.DebugInfo->iFunction,pData.DebugInfo->iParam,EFalse);
+ 			break;
+ 		case EWsClOpDebugInfoReplyBuf:
+			DebugInfoL(pData.DebugInfo->iFunction,pData.DebugInfo->iParam,ETrue);
+ 			break;
+		case EWsClOpResourceCount:
+			SetReply(iObjectIndex->Count());
+			break;
+		case EWsClOpHeapSetFail:
+			{
+			if(!KSecurityPolicy_WriteDeviceData().CheckPolicy(ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWsSession::HeapSetFail API")))
+				{
+				PPanic(EWservPanicPermissionDenied);
+				}
+#if !defined(_DEBUG)
+			if (pData.HeapSetFail->type!=RHeap::ENone)
+				TWindowServerEvent::NotifyOom();
+#endif
+			// if there is a memory manager and we are making the allocator fail next or 
+			// deteministic we want to make sure we test both when the memory manager
+			// succeeds and fails in allocating after freeing up memory. we do that by
+			// remapping the rate and explicitly telling the memory manager to fail:
+			// requested rate  | fail on retry, actual rate
+			//        1        |    true      ,    1
+			//        2        |    false     ,    1
+			//        3        |    true      ,    2
+			CWsMemoryManager* memoryManager = NULL;
+			TInt rate = pData.HeapSetFail->value;
+			TBool memoryManagerRetryFail = EFalse;
+			if((pData.HeapSetFail->type == RAllocator::EFailNext || pData.HeapSetFail->type == RAllocator::EDeterministic))
+				{
+				memoryManager = CWsMemoryManager::Static();
+				if(memoryManager)
+					{
+					memoryManagerRetryFail = (rate % 2 == 1);
+					rate = rate / 2 + (memoryManagerRetryFail ? 1 : 0);
+					}
+				}
+
+			switch (pData.HeapSetFail->type)
+				{	//This log message means you can safely ignore the allocation failures in between
+					//see CWindowServer::ReleaseMemory()
+				case RAllocator::ENone:
+					RDebug::Printf("WSERV Heap: __DbgSetAllocFail() <<<ENone");
+					break;
+				case RAllocator::EReset:
+					RDebug::Printf("WSERV Heap: __DbgSetAllocFail() <<<EReset");
+					break;
+				default:	
+					if (memoryManagerRetryFail)
+						RDebug::Printf("WSERV Heap: Memory Manager set to fail on retry");
+					RDebug::Printf("WSERV Heap: __DbgSetAllocFail(EUser,%i,%i)>>>", pData.HeapSetFail->type, rate);
+					break;
+				}
+
+			if (memoryManager && memoryManagerRetryFail)
+				memoryManager->SetFailNextRetry();
+			
+			if (pData.HeapSetFail->burst >= 0)
+				User::__DbgSetBurstAllocFail(RHeap::EUser, pData.HeapSetFail->type, rate, pData.HeapSetFail->burst);
+			else
+				User::__DbgSetAllocFail(RHeap::EUser, pData.HeapSetFail->type, rate);
+			break;
+			}
+		case EWsClOpRawEvent:
+			{
+			if(!KSecurityPolicy_SwEvent().CheckPolicy(ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWsSession::SimulateRawEvent API")))
+				{
+				PPanic(EWservPanicPermissionDenied);
+				}
+			TRawEvent event(*pData.RawEvent);
+			if (TWsPointer::PreProcessDriverEvent(event))
+				TWindowServerEvent::ProcessRawEvent(event);
+			}
+			break;
+		case EWsClOpKeyEvent:
+			{
+			if(!KSecurityPolicy_SwEvent().CheckPolicy(ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWsSession::SimulateKeyEvent API")))
+				{
+				PPanic(EWservPanicPermissionDenied);
+				}
+			TWindowServerEvent::ProcessKeyEvent(*pData.KeyEvent,0);
+			}
+			break;
+		case EWsClOpLogMessage:
+			if (wsDebugLog)
+				{
+				if (CheckBuffer(*pData.Int, KLogMessageLength))
+					wsDebugLog->MiscMessage(CDebugLogBase::ELogImportant,BufferTPtr((TText* )(pData.Int+1),*pData.Int),0);
+				}
+			break;
+		case EWsClOpPasswordEntered:
+			CWsPassword::PasswordEntered(this);
+			break;
+		case EWsClOpComputeMode:
+			SetComputeMode(*pData.ComputeMode);
+			break;
+		case EWsClOpSendOffEventsToShell:
+			{
+			if(!KSecurityPolicy_PowerMgmt().CheckPolicy(ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWsSession::RequestOffEvents API")))
+				{
+				User::Leave(KErrPermissionDenied);
+				}
+			SetReply(CWsTop::SetSendOffEventsToShell(this,*pData.OffEventsToShell));
+			}
+			break;
+		case EWsClOpGetDefModeMaxNumColors:
+			{
+			SDefModeMaxNumColors colors;
+			const TInt screenNumber = *pData.Int;
+			if (screenNumber<KDummyScreenNumber || screenNumber>=CWsTop::NumberOfScreens())
+				PPanic(EWservPanicScreenNumber);
+			else
+				{
+				CScreen* screen = (screenNumber==KDummyScreenNumber)?iScreen:CWsTop::Screen(screenNumber);
+				screen->MaxNumColors(colors.iColors,colors.iGrays);
+				colors.iDisplayMode=screen->FirstDefaultDisplayMode();
+				}
+			ReplyBuf(&colors,sizeof(colors));
+			}
+			break;
+		case EWsClOpGetColorModeList:
+			{
+			const TInt screenNumber = *pData.Int;
+			if (screenNumber<KDummyScreenNumber || screenNumber>=CWsTop::NumberOfScreens())
+				PPanic(EWservPanicScreenNumber);
+			else
+				SetReply((screenNumber==KDummyScreenNumber) ? iScreen->ColorModesFlag() : CWsTop::Screen(screenNumber)->ColorModesFlag());
+			}
+			break;
+		case EWsClOpSetDefaultFadingParams:
+			{
+			if(KSecurityPolicy_WriteDeviceData().CheckPolicy(ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWsSession::SetDefaultFadingParameters API")))
+				{
+				iScreen->SetFadingParams(WservEncoding::ExtractFirst8BitValue(*pData.UInt),WservEncoding::ExtractSecond8BitValue(*pData.UInt));
+				}
+			}
+			break;
+		case EWsClOpPrepareForSwitchOff:
+			{
+			if(KSecurityPolicy_PowerMgmt().CheckPolicy(ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWsSession::PrepareForSwitchOff API")))
+				{
+				}
+			}
+			break;
+		case EWsClOpSetFaded:
+			{
+			// Deprecated - retained for BC with applications that retrieve the fade count
+			if(!KSecurityPolicy_WriteDeviceData().CheckPolicy(ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWsSession::SetSystemFaded API")))
+				User::Leave(KErrPermissionDenied);
+
+			TUint8 blackMap;
+			TUint8 whiteMap;
+			if (pData.SetSystemFaded->UseDefaultMap())
+				iScreen->GetFadingParams(blackMap,whiteMap);
+			else
+				pData.SetSystemFaded->GetFadingParams(blackMap,whiteMap);
+			
+			iScreen->RootWindow()->SetSystemFaded(pData.SetSystemFaded->Faded(),blackMap,whiteMap);
+			}
+		break;
+		case EWsClOpLogCommand:
+			CWsTop::LogCommand(*pData.LogCommand);
+			break;
+#if defined(__WINS__)
+		case EWsClOpRemoveKeyCode:
+			iInternalFlags&=~ERemoveKeyCode;
+			if (*pData.Bool)
+				iInternalFlags|=ERemoveKeyCode;
+			break;
+		case EWsClOpSimulateXyInput:
+			TWsPointer::SetXyInputType(*pData.XyInput);
+			break;
+#endif
+		case EWsClOpNoFlickerFree:
+			PPanic(EWservPanicOpcode); //not supported anymore
+			break;
+		case EWsClOpSetFocusScreen:
+			{
+			if(!KSecurityPolicy_WriteDeviceData().CheckPolicy(ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWsSession::SetFocusScreen API")))
+				{
+				User::Leave(KErrPermissionDenied);
+				}
+			TInt focusScreen=*pData.Int;
+			if (focusScreen>=0 && focusScreen<CWsTop::NumberOfScreens())
+				SetReply(CWsTop::SetCurrentFocusScreen(focusScreen));
+			else
+				SessionPanic(EWservPanicScreenNumber);
+			break;
+			}
+		case EWsClOpGetFocusScreen:
+			SetReply(CWsTop::CurrentFocusScreen()->ScreenNumber());
+			break;
+		case EWsClOpGetNumberOfScreens:
+			SetReply(CWsTop::NumberOfScreens());
+			break;
+		case EWsClOpClearAllRedrawStores:
+			CWsTop::ClearAllRedrawStores();
+			break;
+		case EWsClOpGetGraphicMessage:
+			iGraphicMessageQueue.GetGraphicMessage();
+			break;
+		case EWsClOpGraphicMessageCancel:
+			iGraphicMessageQueue.CancelRead();
+			break;
+		case EWsClOpGraphicAbortMessage:
+			iGraphicMessageQueue.AbortMessage(*pData.Int);
+			break;
+		case EWsClOpGraphicFetchHeaderMessage:
+			SetReply(iGraphicMessageQueue.TopClientHandle());
+			break;
+		case EWsClOpRegisterSurface:
+			SetReply(RegisterSurface(pData));
+			break;
+		case EWsClOpUnregisterSurface:
+			UnregisterSurface(pData);
+			break;
+		case EWsClOpSetCloseProximityThresholds:
+			if(!KSecurityPolicy_WriteDeviceData().CheckPolicy(ClientMessage(),
+					__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWsSession::SetCloseProximityThresholds")))
+				{
+				User::Leave(KErrPermissionDenied);
+				}
+			SetReply(TWsPointer::SetCloseProximityThresholds(pData.ZThresholdPair->enterThreshold,
+															 pData.ZThresholdPair->exitThreshold));
+			break;
+		case EWsClOpSetHighPressureThresholds:
+			if(!KSecurityPolicy_WriteDeviceData().CheckPolicy(ClientMessage(),
+					__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWsSession::SetHighPressureThresholds")))
+				{
+				User::Leave(KErrPermissionDenied);
+				}
+			SetReply(TWsPointer::SetHighPressureThresholds(pData.ZThresholdPair->enterThreshold,
+					 									   pData.ZThresholdPair->exitThreshold));
+			break;
+		case EWsClOpGetEnterCloseProximityThreshold:
+			SetReply(TWsPointer::GetEnterCloseProximityThreshold());
+			break;
+		case EWsClOpGetExitCloseProximityThreshold:
+			SetReply(TWsPointer::GetExitCloseProximityThreshold());
+			break;
+		case EWsClOpGetEnterHighPressureThreshold:
+			SetReply(TWsPointer::GetEnterHighPressureThreshold());
+			break;
+		case EWsClOpGetExitHighPressureThreshold:
+			SetReply(TWsPointer::GetExitHighPressureThreshold());
+			break;
+		case EWsClOpCreateDrawableSource:
+			CreateDrawableSourceL(*pData.CreateDrawableSource);
+			break;
+		default:
+			PPanic(EWservPanicOpcode);
+			break;
+		}
+	}
+/**	Debug information accessor.
+ * 	
+ * 
+ **/
+void CWsClient::DebugInfoL(TInt aFunction, TInt aParam, TBool aHasReplyBuf) const
+	{
+	if (aFunction & EWsDebugClassMask)
+		SetReply(DebugInfoClassifiedL(aFunction,aParam,aHasReplyBuf));
+	else
+		DebugInfoUnclassifiedL(aFunction,aParam,aHasReplyBuf);
+	}
+
+/**	A wide variety of generally unconnected debug enquiries.
+ * 
+ * 
+ **/
+void CWsClient::DebugInfoUnclassifiedL(TInt aFunction, TInt aParam, TBool aHasReplyBuf) const
+	{
+	switch(aFunction)
+		{
+		case EWsDebugInfoHeap:
+			if (aHasReplyBuf)
+				{
+				TWsDebugHeapInfo heapInfo;
+				RHeap& heap=User::Heap();
+				heapInfo.iCount=heap.AllocSize(heapInfo.iTotal);
+				heapInfo.iAvailable=heap.Available(heapInfo.iLargestAvailable);
+				ReplyBuf(&heapInfo,sizeof(heapInfo));
+				}
+			SetReply(KErrArgument);
+			break;
+		case EWsDebugSetCheckHeapOnDisconnectClient:
+			if (!KSecurityPolicy_PowerMgmt().CheckPolicy(ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWsSession::DebugInfo API")))
+				{
+				User::Leave(KErrPermissionDenied);
+				}
+			CWsTop::SetCheckHeapOnDisconnectClient(this);
+			break;
+		case EWsDebugSetCheckHeapOnDisconnectMode:
+			if (!KSecurityPolicy_PowerMgmt().CheckPolicy(ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for RWsSession::DebugInfo API")))
+				{
+				User::Leave(KErrPermissionDenied);
+				}
+			CWsTop::SetCheckHeapOnDisconnectMode(STATIC_CAST(TWsCheckHeapOnDisconnectMode,aParam));
+			break;
+		case EWsDebugFetchCheckHeapResult:
+			SetReply(CWsTop::FetchCheckHeapResult());
+			break;
+		case EWsDebugSetEventQueueTest:
+			CWsWindowGroup::SetEventQueueTestState(aParam);
+			break;
+		default:
+			SetReply(KErrNotSupported);
+			break;
+		}
+	}
+	
+/**	Selects a debug function based on the class of debug query.
+ * 
+ * 
+ **/
+TInt CWsClient::DebugInfoClassifiedL(TInt aFunction, TInt aParam, TBool aHasReplyBuf) const
+	{//Duplicating the meanings of Classified... this would be a good place for a security check
+	//first part of param is always screen number
+	TInt buffSpace=aHasReplyBuf?ReplyBufSpace():0;
+	if (buffSpace<0)
+		return (buffSpace);
+		
+	const TInt screenNumber = (aParam&EWsDebugArgScreenMask)>>EWsDebugArgScreenShift;
+	const TInt functionClass = (aFunction&EWsDebugClassMask);
+	CScreen* screen = NULL;
+	if (functionClass<EWsDebugClassNonScreen)
+		{
+		if (screenNumber<0 || screenNumber>=CWsTop::NumberOfScreens())
+			return (KErrArgument);
+
+		screen = CWsTop::Screen(screenNumber);
+		}
+	WS_ASSERT_DEBUG(screen, EWsPanicNoScreen);
+	switch (aFunction&EWsDebugClassMask)
+		{
+		case EWsDebugClassScreenUiElement:
+			return DebugInfoScreenUiL(aFunction,aParam,buffSpace,*screen);
+		case EWsDebugClassScreenElementSet:
+			return DebugInfoScreenElementSetL(aFunction, aParam, buffSpace, *screen);
+		case EWsDebugClassElementSetWindow:
+			return DebugInfoElementSetWindowL(aFunction, aParam, buffSpace, *screen);
+		case EWsDebugClassElementSetElement:
+			return DebugInfoElementSetElementL(aFunction, aParam, buffSpace, *screen);
+
+		case EWsDebugClassClientWindow:
+		default:
+			return (KErrNotSupported);
+		}
+	}
+
+/**	Returns debug info about the UIElement entries for a screen.
+ * 	This describes the general state or size of the element set.
+ * 	It is indexed via screen num, and optionally element index.
+ * 	Element index MUST BE 0 when not required.
+ * 	@return size of buffer required or error code.
+ **/
+TInt CWsClient::DebugInfoScreenUiL(TInt aFunction, TInt /* aParam */, TInt aReplyBufSize, CScreen& aScreen) const
+	{
+	switch(aFunction)
+		{
+		case EWsDebugGetFastpathMode:
+			{
+			// obsolete through preq2669
+            WS_ASSERT_DEBUG(EFalse, EWsPanicDrawCommandsInvalidState);
+			return KErrNotSupported;
+			}
+			
+		case EWsDebugSetFastpathMode:
+			{
+            // obsolete through preq2669
+            WS_ASSERT_DEBUG(EFalse, EWsPanicDrawCommandsInvalidState);
+            return KErrNotSupported;
+			}
+			
+		case EWsDebugGetUIElementInfoList:
+			{
+            // obsolete through preq2669
+            WS_ASSERT_DEBUG(EFalse, EWsPanicDrawCommandsInvalidState);
+            return KErrNotSupported;
+			}
+			
+		case EWsDebugGetUIElementBase:
+			{
+            // obsolete through preq2669
+            WS_ASSERT_DEBUG(EFalse, EWsPanicDrawCommandsInvalidState);
+            return KErrNotSupported;
+			}
+
+		case EWsDebugGetUIElementIds:
+			{
+            // obsolete through preq2669
+            WS_ASSERT_DEBUG(EFalse, EWsPanicDrawCommandsInvalidState);
+            return KErrNotSupported;
+			}
+
+		case EWsDebugGetSceneElementIdOrder:
+			{
+            // obsolete through preq2669
+            WS_ASSERT_DEBUG(EFalse, EWsPanicDrawCommandsInvalidState);
+            return KErrNotSupported;
+			}
+		case EWsDebugSetFastpathTestMode:
+			{
+            // obsolete through preq2669
+            WS_ASSERT_DEBUG(EFalse, EWsPanicDrawCommandsInvalidState);
+            return KErrNotSupported;
+			}
+			
+		case EWsDebugSetFastpathOomMode:
+			{
+            // obsolete through preq2669
+            WS_ASSERT_DEBUG(EFalse, EWsPanicDrawCommandsInvalidState);
+            return KErrNotSupported;
+			}
+		case EWsDebugGetUIElementConfig:
+			{
+			return DebugReturnConfig(aReplyBufSize,&aScreen.UiElement(),0);
+
+			}
+		default:
+			return (KErrNotSupported);
+		}
+	}
+
+/**	Returns debug info about the CWindowElementSet entry for a screen.
+ * 	This describes the general state or size of the element set
+ * 	It is indexed via screen num.
+ * 	@return size of buffer required or error code.
+ **/
+TInt CWsClient::DebugInfoScreenElementSetL(TInt aFunction, TInt /*aParam*/, TInt aReplyBufSize, const CScreen& aScreen) const
+	{
+	const CWindowElementSet& elementSet = aScreen.WindowElements();
+	switch (aFunction)
+		{
+		case EWsDebugSerialSurfacesUpdated:
+			return 0;
+
+		case EWsDebugSurfaceWindowList:
+			{
+			TInt outSize = elementSet.Count() * sizeof(TWsDebugWindowId);
+			if (outSize<=aReplyBufSize)
+				{//can stream, so I shall!
+				for (TInt index = 0; index < elementSet.Count(); index++)
+					{
+					const CWsClientWindow& win = *elementSet.DebugWindowAt(index);
+					TWsDebugWindowId id=
+						{
+						win.ClientHandle(), 0
+						};
+					if (win.WsOwner()!=this)
+						id.iOtherGroupId=win.WinGroup()->Identifier();
+					ReplyBuf(&id, sizeof(id));
+					}
+				}
+			return outSize;
+			}
+		default:
+			return (KErrNotSupported);
+
+		}
+	}
+
+/**	Returns debug info about a CWindowElement entry.
+ * 	This describes the window or the background element(s)
+ * 	It is indexed via screen num, and index in elementset.
+ * 	@return size of buffer required or error code.
+ **/
+TInt CWsClient::DebugInfoElementSetWindowL(TInt aFunction, TInt aParam,
+		TInt aReplyBufSize, const CScreen& aScreen) const
+	{
+	const CWindowElementSet& elementSet = aScreen.WindowElements();
+	TUint winIndex = (aParam & EWsDebugArgWindowMask) >> EWsDebugArgWindowShift;
+	const TAttributes* winElement = elementSet.DebugBackgroundAt(winIndex);
+	if (winElement == NULL)
+		{
+		return KErrArgument;
+		}
+
+	MWsElement* backElement = winElement->iElement;
+	TInt placedCount = elementSet.DebugPlacedCountAt(winIndex);
+	switch (aFunction)
+		{
+		case EWsDebugElementIdList:
+			{
+			TInt retVal = (placedCount + 1) * sizeof(MWsElement*);
+			if (retVal<aReplyBufSize)
+				{
+				ReplyBuf(&backElement, sizeof(MWsElement*));
+				for (TInt index=0; index<placedCount; index++)
+					ReplyBuf(&elementSet.DebugPlacedAt(winIndex, index)->iElement, sizeof(MWsElement*));
+				}
+			return retVal;
+			}
+		case EWsDebugBackgroundConfig:
+			if (backElement == NULL)
+				return KErrNotFound;
+			else
+				return DebugReturnConfig(aReplyBufSize, backElement,
+						winElement->DebugFlags());
+		case EWsDebugBackgroundBase:
+			if (backElement == NULL)
+				return KErrNotFound;
+			else
+				return DebugReturnBase(aReplyBufSize, backElement);
+		case EWsDebugBackgroundFlags:
+			return DebugReturnFlags(aReplyBufSize, backElement,
+					winElement->DebugFlags());
+		default:
+			return KErrNotSupported;
+		//This method can also be extended to return region and state information from the associated window
+		}
+	}
+
+/**	Returns debug info about a placed element.
+ * 	It is indexed via screen num, index in elementset, and index in placed element array.
+ * 	@return size of buffer required or error code.
+ **/
+TInt CWsClient::DebugInfoElementSetElementL(TInt aFunction, TInt aParam,
+		TInt aReplyBufSize, const CScreen& aScreen) const
+	{
+	const CWindowElementSet& elementSet = aScreen.WindowElements();
+	TUint winIndex = (aParam & EWsDebugArgWindowMask) >> EWsDebugArgWindowShift;
+	TUint placeIndex = (aParam & EWsDebugArgElementMask) >> EWsDebugArgElementShift;
+	const TAttributes* placedElement = elementSet.DebugPlacedAt(winIndex, placeIndex);
+	if (placedElement == NULL)
+		{
+		return KErrArgument;
+		}
+
+	MWsElement* element = placedElement->iElement;
+	if (element == NULL)
+		{
+		return KErrNotFound;
+		}
+
+	switch (aFunction)
+		{
+		case EWsDebugPlacedConfig:
+			return DebugReturnConfig(aReplyBufSize, element,
+					placedElement->DebugFlags());
+		case EWsDebugPlacedBase:
+			return DebugReturnBase(aReplyBufSize, element);
+		case EWsDebugPlacedFlags:
+			return DebugReturnFlags(aReplyBufSize, element,
+					placedElement->DebugFlags());
+		default:
+			return KErrNotSupported;
+		}
+	}
+
+/**	Returns a filled in TSurfaceConfiguration from an MWsElement.
+ * 	Data is usually copied if the buffer is big enough
+ * 	@return the size of buffer required, or zero if the buffer is acceptable
+ **/
+TInt CWsClient::DebugReturnConfig(TInt aReplyBufSize, MWsElement* aElement, TInt /*aFlags*/) const
+	{
+	if (aElement == NULL)
+		{
+		return KErrNotReady;
+		}
+
+	TSurfaceConfiguration config(aReplyBufSize);
+	TInt retVal=config.Size();
+	if (aReplyBufSize)
+		{
+		retVal = CWindowElementSet::GetConfiguration(config, *aElement);
+		if (retVal==KErrNone)
+			{
+			ReplyBuf(&config, config.Size()); //return code is 0 = "just right"
+			}
+		}
+	return retVal;
+	}
+
+/**	Returns the base region of the element.
+ * 	This region is element relative. There are a number of ways that this does not match the input region:
+ * 	First, if no region is specified then the extent rectangle is returned
+ * 	Any region returned has all negative ordinate values clipped. 
+ * 	Positive values may exceed the extent, but negative values are never returned. 
+ *  Internally, a region which is only negative is "remembered illegally", but an empty region is returned.
+ **/
+TInt CWsClient::DebugReturnBase(TInt /*aReplyBufSize*/, const MWsElement* /*aElement*/)const
+	{
+	return KErrNotSupported;
+	}
+
+/**	Returns the flags associated with the given element.
+ * 	2 words are inserted.
+ * 	One represents the MWsElement flags, the other represents CWindowElement or UIElement flags
+ * 	@return length of two words
+ **/
+TInt CWsClient::DebugReturnFlags(TInt aReplyBufSize, const MWsElement* /*aElement*/, TInt aFlags)const
+	{
+	const TInt KArraySize=2;
+	if (aReplyBufSize>KArraySize*sizeof(TInt))
+		{
+		// First field is for flags from scene element if any
+		TInt returns[KArraySize]=
+			{
+			0, aFlags
+			};
+		ReplyBuf(returns,KArraySize*sizeof(TInt));
+		}
+	return KArraySize*sizeof(TInt);
+	}
+
+/**	Packages a region for return ans an array of rectangles.
+ * 	If the buffer is big enough the data is transferred
+ * 	@return the buffer size required, or an error code if an empty or null pointer is passed in
+ **/
+TInt CWsClient::DebugReturnRegion(TInt aReplyBufSize, const TRegion* aRegion, TInt aErrCodeIfEmpty)const
+	{
+	if (aRegion==NULL)
+		return KErrNotReady;
+	
+	const TInt returnSize=aRegion->Count()*sizeof(TRect);
+	if (returnSize==0)
+		return aErrCodeIfEmpty;
+	
+	if (returnSize<=aReplyBufSize)
+		ReplyBuf(aRegion->RectangleList(),returnSize);
+	
+	return returnSize;
+	}
+
+void CWsClient::ReplyGroupName(HBufC* aName, TInt aMaxLength)	// static
+	{
+	if (aName)
+		{
+		if (aName->Length()>aMaxLength)
+			{
+			ReplyBuf(aName->Left(aMaxLength));
+			SetReply(KErrOverflow);
+			}
+		else
+			ReplyBuf(*aName);
+		}
+	else
+		ReplyBuf(KNullDesC);
+	}
+
+void CWsClient::TriggerRedraw()
+	{
+	RedrawQueue()->TriggerRedraw();
+	}
+
+void CWsClient::UpdateWindowOrdinalPrioritys()
+	{
+	for(CWsWindowGroup* win=iScreen->RootWindow()->Child();win;win=win->NextSibling())
+		{
+		if (win->WsOwner()==this)
+			win->UpdateOrdinalPriority(ETrue);
+		}
+	}
+
+void CWsClient::DeleteSystemPointerListEntry(TInt aIndex)
+	{
+	PointerCursor (aIndex)->Close();
+	iSystemPointerCursors->Delete(aIndex);
+	}
+
+CWsPointerCursor* CWsClient::SystemPointerCursor(TInt aIndex)
+	{
+	TInt arrayIndex;
+	if (iSystemPointerCursors)
+		{
+		if (FindCursorArrayItem(iSystemPointerCursors, aIndex, arrayIndex))
+			return PointerCursor(arrayIndex);
+
+		// Cursor not defined so try for default cursor
+		if (FindCursorArrayItem(iSystemPointerCursors, 0, arrayIndex))
+			return PointerCursor(arrayIndex);
+		}
+
+	// If that fails simply return NULL for no cursor
+	return NULL;
+	}
+
+void CWsClient::SetSystemPointerCursorL(TInt aIndex, CWsPointerCursor* aCursor)
+	{
+	if (iSystemPointerCursorListOwner!=this)
+		PPanic(EWservPanicNotSystemPointerCursorListOwner);
+	
+	TInt arrayIndex = KErrNotFound;
+	if (FindCursorArrayItem(iSystemPointerCursors, aIndex, arrayIndex))
+		{
+		PointerCursor(arrayIndex)->Close();
+		PointerCursor(arrayIndex) = aCursor;
+		}
+	else
+		{
+		TWsCursorArrayItem entry;
+		entry.iIndex=aIndex;
+		entry.iCursor=aCursor;
+		iSystemPointerCursors->InsertIsqL(entry, iCursorKey);
+		}
+	
+	aCursor->Open();
+	if (aIndex==iDefaultSystemPointerCursorIndex)
+		iDefaultSystemPointerCursor=aCursor;
+	TWsPointer::UpdatePointerCursor();
+	}
+
+void CWsClient::ClearSystemPointerCursor(TInt aIndex)
+	{
+	if (iSystemPointerCursorListOwner!=this)
+		PPanic(EWservPanicNotSystemPointerCursorListOwner);
+	
+	TInt arrayIndex;
+	if (FindCursorArrayItem(iSystemPointerCursors, aIndex, arrayIndex))
+		{
+		DeleteSystemPointerListEntry(arrayIndex);
+		if (aIndex==iDefaultSystemPointerCursorIndex)
+			iDefaultSystemPointerCursor=NULL;
+		}
+	}
+
+void CWsClient::ClaimSystemPointerCursorListL()
+	{
+	if (iSystemPointerCursorListOwner)
+		User::Leave(KErrInUse);
+	
+	const TInt systemPointerCursorGranularity = 4;
+	iSystemPointerCursors = new(ELeave) CArrayFixFlat<TWsCursorArrayItem> (systemPointerCursorGranularity);
+	iSystemPointerCursorListOwner=this;
+	}
+
+void CWsClient::FreeSystemPointerCursorList()
+	{
+	if(iSystemPointerCursorListOwner == this)
+		{
+		iSystemPointerCursorListOwner = NULL;
+		
+		while(iSystemPointerCursors->Count()>0)
+			DeleteSystemPointerListEntry(0);
+		
+		iDefaultSystemPointerCursor = NULL;
+		iDefaultSystemPointerCursorIndex = 0;
+		
+		delete iSystemPointerCursors;
+		iSystemPointerCursors = NULL;
+		}
+	}
+
+void CWsClient::SetDefaultSystemPointerCursor(TInt aIndex)
+	{
+	TInt arrayIndex;
+	if (iSystemPointerCursorListOwner != this)
+		PPanic(EWservPanicNotSystemPointerCursorListOwner);
+	
+	iDefaultSystemPointerCursorIndex = aIndex;
+	iDefaultSystemPointerCursor = NULL;
+	
+	if (aIndex != ENoDefaultSystemPointerCursor &&
+		FindCursorArrayItem(iSystemPointerCursors, aIndex, arrayIndex))
+		iDefaultSystemPointerCursor = PointerCursor (arrayIndex);
+	else
+		iDefaultSystemPointerCursor = NULL;
+	
+	TWsPointer::UpdatePointerCursor();
+	}
+
+TBool CWsClient::FindCursorArrayItem(CArrayFixFlat<TWsCursorArrayItem>* aCursorArray,
+									 TInt aIndex,TInt& aPosition)
+	{
+	if (!aCursorArray)
+		return EFalse; // No hit if the array isn't even allocated
+
+	TWsCursorArrayItem entry;
+	entry.iIndex = aIndex;
+	return aCursorArray->FindIsq(entry, iCursorKey, aPosition)==KErrNone;
+	}
+
+void CWsClient::SetClientPriority()
+	{
+	if (iComputeMode!=RWsSession::EPriorityControlDisabled)
+		{
+		Client().SetProcessPriority(
+				iComputeMode==RWsSession::EPriorityControlComputeOn 
+			||	CWsTop::FocusWindowGroupOwner()!=this
+				?	EPriorityBackground
+			  	:	EPriorityForeground);
+		}
+	}
+
+void CWsClient::SetComputeMode(RWsSession::TComputeMode aComputeMode)
+	{
+	if (aComputeMode!=RWsSession::EPriorityControlDisabled 
+		&& aComputeMode	!=RWsSession::EPriorityControlComputeOn 
+		&& aComputeMode	!=RWsSession::EPriorityControlComputeOff)
+		PPanic(EWservPanicSetComputeMode);
+	iComputeMode=aComputeMode;
+	SetClientPriority();
+	}
+
+void CWsClient::CompleteMessage(const RMessage2& aMessage,TInt aReason)
+	{
+	WS_ASSERT_DEBUG(!aMessage.IsNull(),EWsPanicPanicFlagError);
+	if (iInternalFlags&EPanicClientAsSoonAsPossible)
+		{
+		aMessage.Panic(KWSERVSessionPanicCategory,iPanicReason);
+		iInternalFlags&=~EPanicClientAsSoonAsPossible;
+		}
+	else
+		{
+		if(!iResponseHandle)
+			aMessage.Complete(aReason);
+		else
+			{
+			aMessage.Complete(*iResponseHandle);
+			iResponseHandle=NULL;
+			}
+		}
+	}
+
+void CWsClient::ServiceError(const RMessage2& /*aMessage*/,TInt aError)
+	{
+	CompleteMessage(iClientMessage,aError);	// (finish)
+	}
+
+void CWsClient::ServiceL(const RMessage2 &aMessage)	// (step ##1)
+//
+// Handle messages for the window server server.
+//
+	{
+	iClientMessage=aMessage; // from now on use always the message stored in the session
+	if (iInternalFlags&EPanicClientAsSoonAsPossible)
+		{
+		iClientMessage.Panic(KWSERVSessionPanicCategory,iPanicReason);
+		}
+	else
+		{
+		iPanicReason=KErrNone;
+		iReply=KErrNone;
+		TBool completeRequest=ETrue;
+		DoServiceL(iClientMessage, completeRequest);	// (call #2)
+		if (completeRequest)
+			CompleteMessage(iClientMessage,iReply);	// (finish)
+		}
+	}
+
+void CWsClient::SetResponseHandle(RHandleBase* aHandle)
+	{
+	iResponseHandle = aHandle;
+	}
+
+void CWsClient::DoServiceL(const RMessage2& aMessage, TBool& aCompleteRequest)	// (step #2)
+	{
+	if (aMessage.IsNull())
+		PPanic(EWservPanicNullMessageFromClient);
+	
+	WS_ASSERT_DEBUG(iInternalFlags&EFinishedProcessingCommands,EWsPanicCommandBufferStillBeingProcessed);
+
+	const TInt function = aMessage.Function();
+	switch (function)
+		{
+	case EWservMessInit:
+		StartInitializationL(iConnectionId++);
+		break;
+	case EWservMessSyncMsgBuf:
+	case EWservMessCommandBuffer:	// Process command buffer containing draw ops
+		{
+		if (!IsInitialised())			
+			PPanic(EWservPanicUninitialisedClient);
+			
+		const TInt err = aMessage.Read(KBufferMessageSlot, iCmdBuf);
+		if (!err)
+			{
+			iReplyOffset=0;
+			iDestObj=NULL;
+			iNextCmd=iCmdBuf.Ptr();
+			DoServiceCommandBuf();	// (call #3.1)
+			}
+		else if (err!=KErrDied)
+			PPanic(EWservPanicDescriptor);
+		
+		if(function == EWservMessCommandBuffer && CWsTop::FinishEveryFlush())
+			Screen()->DoRedrawNow();
+		else
+			aCompleteRequest=EFalse;
+		}
+		break;
+	case EWservMessShutdown:
+		{
+		if(!KSecurityPolicy_PowerMgmt().CheckPolicy(ClientMessage(),__PLATSEC_DIAGNOSTIC_STRING("Capability check failed for EWservMessShutdown message ")))
+			PPanic(EWservPanicPermissionDenied);
+
+		if (aMessage.Int0() == EWservShutdownCheck)
+			CWsTop::Exit();
+		else
+			PPanic(EWservPanicHandle);
+		}
+		break;
+	case EWservMessFinish:
+		Screen()->DoRedrawNow();
+		break;
+	default:
+		if (function&EWservMessAsynchronousService)
+			{
+			TRAPD(err, ExecuteAsyncClientCommandL((function&~EWservMessAsynchronousService), aMessage));	// (call #3.2)
+			aCompleteRequest = (err!=KErrNone);
+			WS_ASSERT_DEBUG((!(iInternalFlags&EPanicClientAsSoonAsPossible))==(!aCompleteRequest), EWsPanicPanicFlagError);
+			}
+		else if (function&EWservMessAnimDllAsyncCommand)
+			{
+			CWsAnimDll* const animDll = static_cast<CWsAnimDll*>(HandleToObj(aMessage.Int0(), WS_HANDLE_ANIM_DLL));
+			if (!animDll)
+				{
+				SessionPanic(EWservPanicHandle);
+				break;
+				}
+				
+			// it looks wrong to call CommandReply here (not AsyncCommandReply, or something, which doesn't exist), but basically, we can't add a virtual AsyncCommandReplyL to CAnim to correspond to RAnim::AsyncCommandReply as that would break binary and source compatibility for Anim plug-ins; instead asynchronous commands are done by the plug-in having to complete the RMessagePtr2 returned by iFunctions->Message() (or a copy of of that object) for asynchronous commands only
+			TRAPD(err, animDll->AnimObjectL(aMessage.Int1())->CommandReply(function&~EWservMessAnimDllAsyncCommand,NULL));
+			aCompleteRequest=(err!=KErrNone);
+			WS_ASSERT_DEBUG((!(iInternalFlags&EPanicClientAsSoonAsPossible))==(!aCompleteRequest), EWsPanicPanicFlagError);
+			}
+		else
+			SetReply(KErrNotSupported);
+		}
+	}
+void CWsClient::RemoteRead(TDes16& aDes, TInt aOffset)
+	{
+	if (iClientMessage.Read(KRemoteBufferMessageSlot,aDes,aOffset)!=KErrNone)
+		SessionPanic(EWservPanicDescriptor);
+	}
+
+void CWsClient::RemoteRead(TDes8& aDes, TInt aOffset)
+	{
+	if (iClientMessage.Read(KRemoteBufferMessageSlot,aDes,aOffset)!=KErrNone)
+		SessionPanic(EWservPanicDescriptor);
+	}
+
+void CWsClient::RemoteReadL(TDes16& aDes, TInt aOffset)
+	{
+	iClientMessage.ReadL(KRemoteBufferMessageSlot,aDes,aOffset);
+	}
+
+void CWsClient::RemoteReadL(TDes8& aDes, TInt aOffset)
+	{
+	iClientMessage.ReadL(KRemoteBufferMessageSlot,aDes,aOffset);
+	}
+
+void CWsClient::InitStaticsL()
+	{
+	iMoreCommands=CIdle::NewL(EClientBufferPriority);
+	}
+
+void CWsClient::DeleteStatics()
+	{
+	if (iTextCursorArray)
+		{
+		const TInt count = iTextCursorArray->Count();
+		for (TInt index=0;index<count;index++)
+			delete iTextCursorArray->At(index).iCursor;
+
+		delete iTextCursorArray;
+		iTextCursorArray = NULL;
+		}
+
+	delete iMoreCommands;
+	iMoreCommands=NULL;
+	// coverity[extend_simple_error] 
+	}
+		
+/* CWsClient implementing MWsClient */
+
+TBool CWsClient::HasCapability(TCapability aCapability) const
+	{
+	return iClient.HasCapability(aCapability);
+	}
+
+TSecureId CWsClient::SecureId() const
+	{
+	return iClient.SecureId();
+	}
+
+TVendorId CWsClient::VendorId() const
+	{
+	return iClient.VendorId();
+	}
+
+/**
+Makes a new copy of the aData. so it could be deleted after this call.
+*/
+TInt CWsClient::SendMessage(const CWsGraphicDrawer* aOnBehalfOf,const TDesC8& aData)
+	{
+	CWsGraphicMessageQueue::CMessage* msg = CWsGraphicMessageQueue::CMessage::New(aData);
+	if(msg)
+		return SendMessage(aOnBehalfOf, *msg);
+	
+	return KErrGeneral;
+	}
+
+/** adds a message to the message queue
+@return a postive number to uniquely identify the message
+*/
+TInt CWsClient::SendMessage(const CWsGraphicDrawer* aOnBehalfOf,CWsMessageData& aData)
+	{
+	WS_ASSERT_DEBUG(aData.Data().Size(), EWsPanicWsGraphic);
+	const CWsGraphicDrawerObject* obj = DrawerObject(aOnBehalfOf);
+	WS_ASSERT_DEBUG(obj, EWsPanicWsGraphic);
+	if(obj)
+		{
+		// assign message id
+		if(iMessageIdSeq == KMaxTInt) // Wrap if iMessageIdSeq has reached KMaxTInt
+			iMessageIdSeq = 0;
+		
+		iMessageIdSeq++;
+		// correct other handles
+		aData.iClientHandle = (obj->ClientHandle() | (EWsGraphMessageTypeUser & 0x03));
+		aData.iDrawer = obj->Drawer();
+		aData.iId = iMessageIdSeq;
+		iGraphicMessageQueue.Queue(&aData);
+		return iMessageIdSeq;
+		}
+
+	return KErrGeneral;
+	}
+
+
+CWsGraphicDrawerObject* CWsClient::DrawerObject(const CWsGraphicDrawer* aDrawer)
+	{
+	const TInt count = ObjectIndex()->Length();
+	for(TInt i=0; i<count; i++)
+		{
+		CWsObject* obj = const_cast<CWsObject*>(ObjectIndex()->At(i));
+		if(obj && (WS_HANDLE_GRAPHIC_DRAWER == obj->Type()))
+			{
+			CWsGraphicDrawerObject* candidate = static_cast<CWsGraphicDrawerObject*>(obj);
+			if(candidate->Drawer() == aDrawer)
+				return candidate;
+			}
+		}
+
+	return NULL;
+	}
+
+const CWsGraphicDrawerObject* CWsClient::DrawerObject(const CWsGraphicDrawer* aDrawer) const
+	{
+	CWsObjectIx* objectIndex = const_cast<CWsClient*>(this)->ObjectIndex();
+	const TInt count = objectIndex->Length();
+	for(TInt i=0; i<count; i++)
+		{
+		CWsObject* obj = const_cast<CWsObject*>(objectIndex->At(i));
+		if(obj && (WS_HANDLE_GRAPHIC_DRAWER == obj->Type()))
+			{
+			const CWsGraphicDrawerObject* candidate = static_cast<CWsGraphicDrawerObject*>(obj);
+			if(candidate->Drawer() == aDrawer)
+				return candidate;
+			}
+		}
+
+	return NULL;
+	}
+
+TInt CWsClient::RegisterSurface(const TWsClCmdUnion& pData)
+	{
+	TInt screenNumber = pData.SurfaceRegister->screenNumber;
+	if (screenNumber<0 || screenNumber>=CWsTop::NumberOfScreens())
+		{
+		PPanic(EWservPanicScreenNumber);
+		}
+	if (pData.SurfaceRegister->surfaceId.Type() == TSurfaceId::EScreenSurface
+			|| pData.SurfaceRegister->surfaceId.IsNull())
+		{
+		PPanic(EWservPanicInvalidSurface);
+		}
+
+	CRegisteredSurfaceMap* surfaceMap = CWsTop::Screen(screenNumber)->SurfaceMap();
+	const TSurfaceId& surfaceId = pData.SurfaceRegister->surfaceId;
+	TInt err = surfaceMap->Add(*this,surfaceId);
+
+	switch(err)
+		{
+	case KErrNone:
+	case KErrNoMemory:
+	case KErrInUse:
+	case KErrArgument:
+		break;
+	default:
+		PPanic(EWservPanicInvalidSurface);
+		}
+	return err;
+	}
+
+void CWsClient::UnregisterSurface(const TWsClCmdUnion& pData)
+	{
+	TInt screenNumber = pData.SurfaceRegister->screenNumber;
+	if (screenNumber<0 || screenNumber>=CWsTop::NumberOfScreens())
+		{
+		PPanic(EWservPanicScreenNumber);
+		}
+	TInt err = CWsTop::Screen(screenNumber)->SurfaceMap()->Remove(*this,pData.SurfaceRegister->surfaceId);
+	WS_ASSERT_DEBUG((err==KErrNone||err==KErrNotFound), EWsPanicSurfaceMapError);
+	}
+
+void CWsClient::CreateDrawableSourceL(const TWsClCmdCreateDrawableSource& aDrawableSourceData)
+	{
+	CWsDrawableSource* drawableSource = new(ELeave) CWsDrawableSource(this);
+	CleanupStack::PushL(drawableSource);
+	drawableSource->ConstructL(aDrawableSourceData);
+	CleanupStack::Pop();
+	}
+
+//
+// class CWsCliObj
+//
+
+CWsCliObj* CWsCliObj::NewL(CWsClient* aOwner)
+	{
+	CWsCliObj* self = new(ELeave) CWsCliObj(aOwner);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+CWsCliObj::CWsCliObj(CWsClient *aOwner) :
+	CWsObject(aOwner, WS_HANDLE_CLIENT)
+	{
+	}
+	
+void CWsCliObj::ConstructL()
+	{
+	NewObjL();	
+	}
+
+void CWsCliObj::CommandL(TInt aOpcode, const TAny* aCmdData)	// (step #5)
+	{
+	iWsOwner->ExecuteCommandL(aOpcode,aCmdData);	// (call #6)
+	}
+
+CWsObject* CWsClient::HandleToObjUntyped(TInt aHandle)
+	{
+	return iObjectIndex->HandleToObject(aHandle);
+	}
+
+const CWsObject* CWsClient::HandleToObjUntyped(TInt aHandle) const
+	{
+	return const_cast<CWsClient*>(this)->HandleToObjUntyped(aHandle);
+	}
+
+CWsObject* CWsClient::HandleToObj(TInt aHandle, WH_HANDLES aType)
+	{
+	CWsObject* object = HandleToObjUntyped(aHandle);
+	return (object && object->Type() == aType) ? object : NULL;
+	}
+
+
+const CWsObject* CWsClient::HandleToObj(TInt aHandle, WH_HANDLES aType) const
+	{
+	return const_cast<CWsClient*>(this)->HandleToObj(aHandle, aType);
+	}
+
+void CWsClient::SetRetryFlag(TEventCode aEventCode)
+	{
+	switch(aEventCode)
+		{
+		//To be expanded
+		case EEventDisplayChanged:
+			{
+			iInternalFlags |= ERetryDisplayEvent;
+			}
+		break;
+		
+		}
+	}
+TBool CWsClient::RetryEvent(TEventCode aEventCode)
+	{
+	switch(aEventCode)
+		{//To be expanded
+		case EEventDisplayChanged:
+			{
+			return (iInternalFlags & ERetryDisplayEvent);
+			}
+		}
+	return EFalse;
+	}
+
+void CWsClient::RemoveRetryFlag(TEventCode aEventCode)
+	{
+	switch(aEventCode)
+		{//To be expanded
+		case EEventDisplayChanged:
+			{
+			iInternalFlags &= ~ERetryDisplayEvent;
+			}
+		break;
+		}
+	}
+