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