author | Gareth Stockwell <gareth.stockwell@accenture.com> |
Fri, 22 Oct 2010 11:38:29 +0100 | |
branch | bug235_bringup_0 |
changeset 206 | c170e304623f |
parent 0 | 5d03bc08d59c |
permissions | -rw-r--r-- |
// Copyright (c) 1995-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: // #include "server.h" #include "WSGRAPHICDRAWERFACTORY.H" #include "panics.h" #include <s32mem.h> #include "wstop.h" TInt CWsGraphicDrawerObject::TransientSequence=1; TBool CWsGraphicDrawerObject::RollOver=EFalse; CWsGraphicDrawerObject* CWsGraphicDrawerObject::NewL(CWsClient* aClient,const TWsClCmdUnion &aParams) { if(!aClient) { WS_PANIC_DEBUG(EWsPanicWsGraphic); User::Leave(KErrGeneral); } TGraphicDrawerId id; id.iId = aParams.CreateGraphic->iId; id.iIsUid = !(EWsGraphicIdTransient & aParams.CreateGraphic->iFlags); // check for collision const CWsGraphicDrawer* dup = CWsTop::WindowServer()->ResolveGraphic(id); // request-specific checks if(dup) { // must be exact same session if(&(dup->Owner()) != aClient) { /* Someone is squatting on someone else's uid, or trying to, but there is no good way to know which. */ __DEBUG_ONLY(aClient->PPanic(EWservPanicPermissionDenied);) User::Leave(KErrAlreadyExists); } // dupping or otherwise must be explicitly intended by the client if(!(EWsGraphicReplace & aParams.CreateGraphic->iFlags)) { aClient->PPanic(EWservPanicPermissionDenied); } } else { // dupping or otherwise must be explicitly intended by the client if(EWsGraphicReplace & aParams.CreateGraphic->iFlags) { aClient->PPanic(EWservPanicPermissionDenied); } if(id.iIsUid) { // police creation of artwork with UIDs _LIT_SECURITY_POLICY_C1(KSecurityPolicyCreateWithUid,ECapabilityProtServ); if(!KSecurityPolicyCreateWithUid.CheckPolicy(aClient->Client())) { __DEBUG_ONLY(aClient->PPanic(EWservPanicPermissionDenied);) User::Leave(KErrPermissionDenied); } } else { // allocate a new transient id // assumption: that there are more values of a TInt than there are possibly Transient objects do { id.iId = TransientSequence++; RollOver |= !TransientSequence; } while(RollOver && CWsTop::WindowServer()->ResolveGraphic(id)); // until no collision } } // create the drawer object TPtrC8 data; HBufC8* dataBuf = NULL; if(aParams.CreateGraphic->iRemoteReadData) { const TInt len = aParams.CreateGraphic->iDataLen; if ((len >= KMaxTInt/4) || (len < 0)) aClient->PPanic(EWservPanicBuffer); dataBuf = HBufC8::NewLC(len); TPtr8 des = dataBuf->Des(); aClient->RemoteRead(des,0); if(des.Size() != len) { aClient->PPanic(EWservPanicBuffer); } data.Set(des); } else { data.Set(CWsClient::BufferTPtr8((TText8*)(aParams.CreateGraphic+1),aParams.CreateGraphic->iDataLen)); } CWsGraphicDrawerObject* drawer = new(ELeave) CWsGraphicDrawerObject(aClient); CleanupStack::PushL(drawer); drawer->ConstructL(aParams.CreateGraphic->iType,*CWsTop::WindowServer(),id,data,aParams.CreateGraphic->iClientHandle); if(!dup) { User::LeaveIfError(CWsTop::WindowServer()->AddGraphicDrawer(drawer->Drawer())); } else { User::LeaveIfError(CWsTop::WindowServer()->SwapGraphicDrawer(drawer->Drawer())); } // take off cleanup stack CleanupStack::Pop(drawer); if(dataBuf) { CleanupStack::PopAndDestroy(dataBuf); } // delete dup, which means resolving the object that encapsulates it if(dup) { CWsGraphicDrawerObject* obj = aClient->DrawerObject(dup); WS_ASSERT_DEBUG(obj, EWsPanicWsGraphic); if(obj) { obj->CloseObject(); } } // trigger redraws if anyone is drawing this graphic before it exists if(id.iIsUid) { CWsTop::WindowServer()->Invalidate(id); } // done return drawer; } CWsGraphicDrawerObject::CWsGraphicDrawerObject(CWsClient* aOwner): CWsObject(aOwner,WS_HANDLE_GRAPHIC_DRAWER) { } CWsGraphicDrawerObject::~CWsGraphicDrawerObject() { delete iDrawer; } void CWsGraphicDrawerObject::ConstructL(TUid aType,MWsGraphicDrawerEnvironment& aEnv,const TGraphicDrawerId& aId,const TDesC8& aData,TInt aClientHandle) { CWsGraphicDrawer* drawer = WsGraphicDrawer::CreateLC(aType,aEnv,aId,*WsOwner(),aData); NewObjL(); iClientHandle = aClientHandle; iDrawer=drawer; CleanupStack::Pop(iDrawer); } void CWsGraphicDrawerObject::CommandL(TInt aOpcode, const TAny *aCmdData) { WS_ASSERT_DEBUG(iDrawer, EWsPanicWsGraphic); if(iDrawer) { TWsClCmdUnion pData; pData.any = aCmdData; switch(aOpcode) { case EWsGdOpFree: // trigger redraws if anyone is drawing this graphic before it exists CWsTop::WindowServer()->RemoveGraphicDrawer(iDrawer->Id()); CloseObject(); return; case EWsGdOpSendMsg: case EWsGdOpSendSynchronMsg: { const TWsClCmdGdSendMessage& cmd = *pData.GraphicSendMessage; __ASSERT_DEBUG(cmd.iDataLen,WsOwner()->PPanic(EWservPanicPermissionDenied)); if(cmd.iDataLen) { if(cmd.iRemoteReadData) { HBufC8* wsAlloc = NULL; TUint8* drawerAlloc = NULL; TPtr8 des(NULL,0); // try to get the drawer to allocate for us MWsGraphicDrawerMessageAlloc* drawerAllocator = iDrawer->ObjectInterface<MWsGraphicDrawerMessageAlloc>(); if(drawerAllocator) { drawerAlloc = reinterpret_cast<TUint8*>(drawerAllocator->Alloc(cmd.iDataLen)); if(drawerAlloc) des.Set(drawerAlloc,0,cmd.iDataLen); } // else use the normal WSERV default heap if(!drawerAlloc) { wsAlloc = HBufC8::NewLC(cmd.iDataLen); des.Set(wsAlloc->Des()); } // fetch WsOwner()->RemoteRead(des,0); TBool receivedOk = (des.Size() == cmd.iDataLen); // dispatch if(receivedOk) { if(aOpcode == EWsGdOpSendMsg) { iDrawer->HandleMessage(des); } else { MWsGraphicHandleSynchronMessage* obj = iDrawer->ObjectInterface<MWsGraphicHandleSynchronMessage>(); if(obj) SetReply(obj->HandleSynchronMessage(des)); else SetReply(KErrNotSupported); } } // dealloc if(drawerAlloc) { drawerAllocator->Free(drawerAlloc); } else { CleanupStack::PopAndDestroy(wsAlloc); } // defer panic until after dealloc if(!receivedOk) { WsOwner()->PPanic(EWservPanicBuffer); } } else { const TPtrC8 data = CWsClient::BufferTPtr8((TText8*)(pData.GraphicSendMessage+1),cmd.iDataLen); if(aOpcode == EWsGdOpSendMsg) { iDrawer->HandleMessage(data); } else { MWsGraphicHandleSynchronMessage* obj = iDrawer->ObjectInterface<MWsGraphicHandleSynchronMessage>(); if(obj) SetReply(obj->HandleSynchronMessage(data)); else SetReply(KErrNotSupported); } } } } break; case EWsGdOpGetGraphicId: { __ASSERT_COMPILE(sizeof(TWsClCmdGdGetId) == sizeof(TGraphicDrawerId)); const TGraphicDrawerId id = iDrawer->Id(); CWsClient::ReplyBuf(&id,sizeof(id)); } break; case EWsGdOpShareGlobally: SetReply(iDrawer->ShareGlobally()); break; case EWsGdOpUnShareGlobally: SetReply(iDrawer->UnShareGlobally()); break; case EWsGdOpShare: { const TSecureId& secid = *reinterpret_cast<const TSecureId*>(aCmdData); SetReply(iDrawer->Share(secid)); break; } case EWsGdOpUnShare: { const TSecureId& secid = *reinterpret_cast<const TSecureId*>(aCmdData); SetReply(iDrawer->UnShare(secid)); break; } default: WsOwner()->PPanic(EWservPanicOpcode); } } } CWsGraphicDrawer* CWsGraphicDrawerObject::Drawer() { return iDrawer; } const CWsGraphicDrawer* CWsGraphicDrawerObject::Drawer() const { return iDrawer; } // CWsGraphicMessageQueue \\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\\ CWsGraphicMessageQueue::CMessage* CWsGraphicMessageQueue::CMessage::New(const TDesC8& aData) { return new(aData.Size()) CMessage(aData); } CWsGraphicMessageQueue::CMessage::CMessage(const TDesC8& aData): iData((reinterpret_cast<TUint8*>(this)+sizeof(*this)),aData.Size()) { iData = aData; } TPtrC8 CWsGraphicMessageQueue::CMessage::Data() const { return iData; } void CWsGraphicMessageQueue::CMessage::Release() { delete this; } CWsGraphicMessageQueue::CMessage::~CMessage() { } CWsGraphicMessageQueue::CWsGraphicMessageQueue(CWsClient *aOwner): CEventBase(aOwner) { } CWsGraphicMessageQueue::~CWsGraphicMessageQueue() { while(iHead) { CWsMessageData* msg = iHead; iHead = iHead->iNext; msg->Release(); } } TInt CWsGraphicMessageQueue::TopClientHandle() const { if(iHead) return iHead->iClientHandle; else return KErrNotFound; } /** same functionality as CEventBase::GetData, but this one also inserts the integer header in the reply. */ void CWsGraphicMessageQueue::GetDataWithHeader(TUint aHeader, const TDesC8& aData, TInt aDataLen) { TPckgBuf<TUint> hdr = aHeader | (EWsGraphMessageTypeUser & 0x03); CWsClient::ReplyBuf(hdr.Ptr(), sizeof(TUint)); GetData((void*)aData.Ptr(), aDataLen); } void CWsGraphicMessageQueue::GetGraphicMessage() { CWsMessageData* top = Pop(); WS_ASSERT_DEBUG(top && top->Data().Length(), EWsPanicWsGraphic); if(top) { GetDataWithHeader(top->iClientHandle, top->Data(), top->Data().Size()); CWsGraphicDrawerObject* obj = iWsOwner->DrawerObject(top->iDrawer); if(obj) { MWsGraphicMessageCallback* messageCallback = obj->Drawer()->ObjectInterface<MWsGraphicMessageCallback>(); if(messageCallback) { messageCallback->HandleMessageDelivery(top->iId, KErrNone); } } top->Release(); } } void CWsGraphicMessageQueue::AbortMessage(TInt aError) { CWsMessageData* top = Pop(); WS_ASSERT_DEBUG(top, EWsPanicWsGraphic); if(top) { CWsGraphicDrawerObject* obj = iWsOwner->DrawerObject(top->iDrawer); if(obj) { MWsGraphicMessageCallback* messageCallback = obj->Drawer()->ObjectInterface<MWsGraphicMessageCallback>(); if(messageCallback) { messageCallback->HandleMessageDelivery(top->iId, aError); } } top->Release(); } } void CWsGraphicMessageQueue::EventReady(const RMessagePtr2& aEventMsg) { CEventBase::EventReady(aEventMsg); if(iHead) { SignalEvent(sizeof(TInt) + iHead->Data().Size()); } } void CWsGraphicMessageQueue::Queue(CWsMessageData* aMessage) { WS_ASSERT_DEBUG(aMessage && !aMessage->iNext, EWsPanicWsGraphic); if(aMessage) { if(iHead) { iTail->iNext = aMessage; iTail = aMessage; } else { iHead = iTail = aMessage; if(!iEventMsg.IsNull()) SignalEvent(sizeof(TInt) + iHead->Data().Size()); } } } CWsMessageData* CWsGraphicMessageQueue::Pop() { CWsMessageData* ret = NULL; if(iHead) { ret = iHead; iHead = iHead->iNext; } return ret; }