--- a/telephonyserver/etelserverandcore/SETEL/ET_PHONE.CPP Mon May 03 13:37:20 2010 +0300
+++ b/telephonyserver/etelserverandcore/SETEL/ET_PHONE.CPP Thu May 06 15:10:38 2010 +0100
@@ -1,2282 +1,2564 @@
-// Copyright (c) 1997-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:
-//
-
-/**
- @file
-*/
-
-#include "ET_SSTD.H"
-#include "et_record.h"
-#include "et_phone_util.h"
-
-//
-// CReqEntry class definitions
-//
-
-CReqEntry* CReqEntry::NewL(TTsyReqHandle aTsyReqHandle, const RMessage2& aMessage, CTelSession* aSession, CBuffer* aBuffer, const CTelObject* aTelObject, TInt aFunction, RHeap* aHeap)
-//
-// Create new request entry. aHeap should be NULL unless this is to be allocated on the
-// priority client heap.
-//
- {
- if (aHeap != NULL)
- {
- return new(aHeap) CReqEntry(aTsyReqHandle,aMessage,aSession,aBuffer,aTelObject,aFunction,aHeap);
- }
-
- return new(ELeave) CReqEntry(aTsyReqHandle,aMessage,aSession,aBuffer,aTelObject,aFunction,NULL);
- }
-
-
-CReqEntry::CReqEntry(TTsyReqHandle aTsyReqHandle,const RMessage2& aMessage,CTelSession* aSession,CBuffer* aBuffer,const CTelObject* aTelObject,TInt aFunction,RHeap* aHeap)
-//
-// CReqEntry constructor
-//
- : iTsyReqHandle(aTsyReqHandle), iMessage(aMessage), iSession(aSession), iTelObject(aTelObject),
- iClientInterested(ETrue), iCancelFnCalled(EFalse), iFunction(aFunction), iBuffer(aBuffer),
- iReadByClient(ETrue), iMessageNulled(EFalse), iHeap(aHeap)
- {}
-
-CReqEntry::~CReqEntry()
-//
-// CReqEntry destructor
-//
- {
- delete iBuffer;
- }
-
-void CReqEntry::Deque()
-//
-// Deque CReqEntry list
-//
- {
- iLink.Deque();
- iLink.iPrev=iLink.iNext=NULL;
- }
-
-void CReqEntry::CompleteAndDeque(TInt aError)
- {
- LOGTEXT("CReqEntry::CompleteAndDeque");
- // if client does not interested in this request do not completed
- if (iClientInterested)
- {
- RECORD_COMPLETE_SUB(iMessage.Session(), iTelObject, iMessage.Int3(), iMessage.Function(), aError);
- iMessage.Complete(aError);
- }
-
- iLink.Deque();
- }
-
-TAny* CReqEntry::operator new(TUint aSize,RHeap* aHeap) __NO_THROW
-//
-// overloaded new using the priority client heap - can leave
-//
- {
- TAny *pM=NULL;
- TRAPD(err, pM=aHeap->AllocL(aSize) );
-
- if(err!=KErrNone)
- pM = NULL;
- else
- Mem::FillZ(pM,aSize);
- return(pM);
- }
-
-TAny* CReqEntry::operator new(TUint aSize) __NO_THROW
- {
- return CBase::operator new(aSize);
- }
-
-TAny* CReqEntry::operator new(TUint aSize,TLeave aLeave)
- {
- return CBase::operator new(aSize,aLeave);
- }
-
-TAny* CReqEntry::operator new(TUint aSize,TUint aExtraSize) __NO_THROW
- {
- return CBase::operator new(aSize,aExtraSize);
- }
-
-void CReqEntry::operator delete(TAny* aPtr)
-//
-// overloaded delete - deletes from priority client heap if iHeap is not NULL
-//
- {
- if (((CReqEntry*)aPtr)->iHeap!=NULL)
- ((CReqEntry*)aPtr)->iHeap->Free(aPtr);
- else
- User::Free(aPtr);
- }
-
-//
-// CBuffer class definitions
-//
-CBuffer* CBuffer::NewL(HEtelBufC8* aBuf8,HEtelBufC16* aBuf16,RHeap* aHeap,TInt aSizeOfData1,TInt aSizeOfData2,TInt aNoOfSlots)
- {
- if (aHeap!=NULL)
- return new(aHeap) CBuffer(aBuf8,aBuf16,aHeap,aSizeOfData1,aSizeOfData2,aNoOfSlots);
-
- return new(ELeave) CBuffer(aBuf8,aBuf16,NULL,aSizeOfData1,aSizeOfData2,aNoOfSlots);
- }
-
-CBuffer::CBuffer(HEtelBufC8* aBuf8,HEtelBufC16* aBuf16,RHeap* aHeap,TInt aSizeOfData1,TInt aSizeOfData2,TInt aNoOfSlots)
- : iBuf8(aBuf8),iBuf16(aBuf16),iHeap(aHeap),iRead(0),iWrite(0),iNoOfSlots(aNoOfSlots),
- iSizeOfData1(aSizeOfData1),iSizeOfData2(aSizeOfData2),
- iOverFlow(EFalse),iBufferFull(EFalse)
- {}
-
-CBuffer::~CBuffer()
- {
- delete iBuf8;
- delete iBuf16;
- }
-
-TAny* CBuffer::operator new(TUint aSize,RHeap* aHeap) __NO_THROW
-//
-// overloaded new using the priority client heap - can leave
-//
- {
- TAny *pM=NULL;
- TRAPD(err, pM=aHeap->AllocL(aSize) );
-
- if(err!=KErrNone)
- pM = NULL;
- else
- Mem::FillZ(pM,aSize);
- return(pM);
- }
-
-TAny* CBuffer::operator new(TUint aSize) __NO_THROW
- {
- return CBase::operator new(aSize);
- }
-
-TAny* CBuffer::operator new(TUint aSize,TLeave aLeave)
- {
- return CBase::operator new(aSize,aLeave);
- }
-
-TAny* CBuffer::operator new(TUint aSize,TUint aExtraSize) __NO_THROW
- {
- return CBase::operator new(aSize,aExtraSize);
- }
-
-void CBuffer::operator delete(TAny* aPtr)
-//
-// overloaded delete - deletes from priority client heap if iHeap not NULL
-//
- {
- if (((CBuffer*)aPtr)->iHeap!=NULL)
- ((CBuffer*)aPtr)->iHeap->Free(aPtr);
- else
- User::Free(aPtr);
- }
-
-TUint CBuffer::Size() const
- {
- return iSizeOfData1 + iSizeOfData2;
- }
-
-void CBuffer::IncRead()
- {
- if(++iRead==iNoOfSlots)
- iRead=0;
- iOverFlow=EFalse;
- iBufferFull=EFalse;
- LOGTEXT2("ETel:\tiRead incremented to %d", iRead);
- }
-
-void CBuffer::IncWrite()
- {
- if(++iWrite==iNoOfSlots)
- iWrite=0;
- if (iOverFlow)
- iRead=iWrite;
- else
- {
- if (!iBufferFull)
- {
- if (iWrite==iRead)
- iBufferFull=ETrue;
- }
- else
- {
- iRead=iWrite;
- iOverFlow=ETrue;
- }
- }
- LOGTEXT2("ETel:\tiWrite incremented to %d", iWrite);
- }
-
-TUint8* CBuffer::CurrentSlotData1(TWhichSlot aWhichSlot) const
-//
-// iSizeOfData1 and iSizeOfData2 include the sizes of the TPtr's
-//
- {
- TInt pos=((aWhichSlot==ESlotRead) ? iRead : iWrite);
-
- if (iBuf8==NULL)
- {
- return NULL;
- }
- else if (iBuf16==NULL)
- {
- TInt slotSize = iSizeOfData1 + iSizeOfData2;
- return (const_cast<TUint8*> (iBuf8->Des().Mid(pos*(slotSize),iSizeOfData1-sizeof(TPtr8)).Ptr()));
- }
- else
- {
- // we have a narrow and a unicode parameter. Data1 is always narrow
- return (const_cast<TUint8*> (iBuf8->Des().Mid(pos*iSizeOfData1,iSizeOfData1-sizeof(TPtr8)).Ptr()));
- }
- }
-
-TUint8* CBuffer::CurrentSlotData2(TWhichSlot aWhichSlot) const
- {
- if (iSizeOfData2==0)
- return NULL;
- TInt pos=((aWhichSlot==ESlotRead) ? iRead : iWrite);
-
- if (iBuf8!=NULL && iBuf16==NULL)
- {
- TInt slotSize = iSizeOfData1 + iSizeOfData2;
- return (const_cast<TUint8*> (iBuf8->Des().Mid(pos*(slotSize)+iSizeOfData1,iSizeOfData2-sizeof(TPtr8)).Ptr()));
- }
-
- return NULL;
- }
-
-TUint16* CBuffer::CurrentSlotData1u(TWhichSlot aWhichSlot) const
-//
-// Unicode version
-//
- {
- TInt pos=((aWhichSlot==ESlotRead) ? iRead : iWrite);
-
- if (iBuf8==NULL && iBuf16!=NULL)
- {
- TInt slotSize = iSizeOfData1 + iSizeOfData2;
- return (const_cast<TUint16*> (iBuf16->Des().Mid(pos*(slotSize),iSizeOfData1-sizeof(TPtr16)).Ptr()));
- }
-
- return NULL; // Data1 will be narrow if we have a mixture of both 8 and 16 bit
- }
-
-TUint16* CBuffer::CurrentSlotData2u(TWhichSlot aWhichSlot) const
-//
-// Unicode version
-//
- {
- if (iSizeOfData2==0)
- return NULL;
- TInt pos=((aWhichSlot==ESlotRead) ? iRead : iWrite);
-
- if (iBuf16==NULL)
- {
- return NULL;
- }
- else if (iBuf8==NULL)
- {
- TInt slotSize = iSizeOfData1 + iSizeOfData2;
- return (const_cast<TUint16*> (iBuf16->Des().Mid(pos*(slotSize)+iSizeOfData1,iSizeOfData2-sizeof(TPtr16)).Ptr()));
- }
- else
- {
- // we have a narrow and a unicode parameter. Data2 is always unicode
- return (const_cast<TUint16*> (iBuf16->Des().Mid(pos*iSizeOfData2,iSizeOfData2-sizeof(TPtr16)).Ptr()));
- }
- }
-
-TBool CBuffer::EqualSizes(TInt aSize1, TInt aSize2) const
- {
- if(iSizeOfData1 != aSize1)
- {
- return EFalse;
- }
- if(iSizeOfData2 != aSize2)
- {
- return EFalse;
- }
- return ETrue;
- }
-
-TInt CBuffer::CompareRWPtrs() const
- {
- return (iRead-iWrite);
- }
-
-//
-//
-// CTelObject class definitions
-//
-
-EXPORT_C CTelObject::CTelObject()
-//
-// CTelObject constructor
-//
- :iActiveReqCount(0), iTelServer(NULL), iDestroyDummySubSession(NULL), iCreateDummy(EFalse)
- {
- __DECLARE_NAME(_S("CTelObject"));
- }
-
-EXPORT_C CTelObject::~CTelObject()
-//
-// Destructor
-//
- {
- delete iDestroyDummySubSession;
- }
-
-EXPORT_C void CTelObject::CTelObject_Reserved1()
-//
-// Reserved virtual function
-//
- {}
-
-void CTelObject::CreateDummySessionObjectL(CTelSession* aTelSession)
- {
- if (iDestroyDummySubSession==NULL)
- {
- LOGTEXT("CDestroyDummySubSession object does not already exist and will be created.");
- iDestroyDummySubSession = CDestroyDummySubSession::NewL(aTelSession->TelServer(),this);
- }
- else
- {
- LOGTEXT("CDestroyDummySubSession object already exists and will not be created");
- }
-
- }
-
-void CTelObject::CreateDummySession(CTelSession* aSession, const TInt aSubSessionHandle, TBool aCreateDummy)
-//
-// So the server has to create a dummy session just to keep session alive until completed
-// function is called.
-//
- {
- LOGTEXT2("CreateDummySession() with iDestroyDummySubSession = %x", iDestroyDummySubSession);
- iCreateDummy=aCreateDummy;
-
- if (iDestroyDummySubSession->iOpen == EFalse)
- {
- if ( IsActiveReq(aSession,aSubSessionHandle) || aCreateDummy)
- {
- LOGTEXT("About to create dummy session");
- __ASSERT_ALWAYS(aSession!=NULL,Fault(EEtelFaultBadTelSessionPointer));
- CObject* theObj=this;
- while(theObj->Owner())
- {
- theObj->Open();
- theObj=theObj->Owner();
- }
- theObj->Open();
- iTelServer=aSession->TelServer();
-
- // incrementing the server's session count to include the dummy session, which
- // has been previously allocated upon the CTelObject creation (by calling
- // CreateDummySessionObjectL() )
- iTelServer->Inc();
- LOGTEXT2("Added a Dummy Session, producing server's session count of %d", iTelServer->Count());
-
- iDestroyDummySubSession->iTelServer = iTelServer;
- iDestroyDummySubSession->iTelObject = this;
- iDestroyDummySubSession->iOpen = ETrue;
- }
- }
- }
-
-void CTelObject::TelObjectClose()
-//
-// Perform an iterative close of Tel Objects
-//
- {
- CTelObject* owner = reinterpret_cast<CTelObject*> (Owner());
- Close();
- if(owner)
- owner->TelObjectClose();
- }
-
-void CTelObject::CompleteAndDestroyReq(CReqEntry* aReqEntry,const TInt aStatus) const
-//
-// complete the entry and remove from entry list and associate heap
-//
- {
- if (!aReqEntry->iMessageNulled)
- {
- RECORD_COMPLETE_SUB(aReqEntry->iMessage.Session(), this, aReqEntry->iMessage.Int3(), aReqEntry->iMessage.Function(), aStatus);
- aReqEntry->iMessage.Complete(aStatus);
- }
- DestroyReq(aReqEntry);
- }
-
-void CTelObject::DestroyReq(CReqEntry* aReqEntry) const
-//
-// remove from entry list and associate heap
-//
- {
- aReqEntry->Deque();
- delete aReqEntry;
- }
-
-TBool CTelObject::IsActiveReq(CTelSession* aSession,const TInt aSubSessionHandle)
-//
-// Return True if found the active req still out standing
-// going through and counting the total of active req
-//
- {
- TBool ret=EFalse;
- CReqEntry* reqEntry=NULL;
- TDblQueIter<CReqEntry> iter(PhoneOwner()->ReqActiveList());
- while(reqEntry=iter++,reqEntry!=NULL) // go through the list from begin to end
- {
- if (aSession==reqEntry->iSession && aSubSessionHandle==reqEntry->iMessage.Int3() && reqEntry->iClientInterested )
- {
- iActiveReqCount++;
- ret=ETrue;
- }
- }
- LOGTEXT2("IsActiveReq found %d active reqs", iActiveReqCount);
- return ret;
- }
-
-void CTelObject::CancelActiveReq(CTelSession* aSession,const TInt aSubSessionHandle)
-//
-// active list - must inform tsy by calling CancelService
-// this request will be destroyed when Tsy do an up call ReqCompleted with KErrCancel
-// Only go through the list once set the count to zero at start to count number of requests
-//
- {
- LOGTEXT("Entered CancelActiveReq");
- CReqEntry* reqEntry=NULL;
- TDblQueIter<CReqEntry> iter(PhoneOwner()->ReqActiveList());
- while(reqEntry=iter++,reqEntry!=NULL) // go through the list from begin to end
- {
- if (aSession==reqEntry->iSession && aSubSessionHandle==reqEntry->iMessage.Int3() && reqEntry->iClientInterested )
- {
- reqEntry->iClientInterested=EFalse;
- __ASSERT_ALWAYS(iActiveReqCount>=0,Fault(EEtelFaultNegativeActiveReqCount));
- if (reqEntry->iCancelFnCalled==FALSE)
- {
- if (reqEntry->iPlacedRequest)
- {
- LOGTEXT2("Calling Cancel Service ActiveReq TsyReq=%d", reqEntry->iTsyReqHandle);
- reqEntry->iCancelFnCalled=ETrue;
- CancelService(reqEntry->iFunction,reqEntry->iTsyReqHandle);
-
- //
- // In calling CancelService() it is possible that a second
- // handle has performed the same request (e.g. a notify) and
- // that ETel will re-post the notify using that handle. In
- // some cases it could happen that the re-posted notify is
- // invalid and fails, thereby completing that next request.
- // Finally, if that request is the next one after this one,
- // then the iterator is going to be invalid. So reset it now
- // and start at the beginning of the list!
- //
- if (PhoneOwner()->ReqActiveList().IsEmpty() == EFalse)
- {
- iter.Set(*PhoneOwner()->ReqActiveList().First());
- }
- else
-
- {
- break;
- }
- }
- else
- {
- LOGTEXT("Destroying request");
- DestroyReq(reqEntry);
- CheckAndDestroyDummySubSession();
- }
- }
- }
- }
- }
-
-void CTelObject::CancelSubSession(CTelSession* aSession,const TInt aSubSessionHandle)
-//
-// Flush outstanding requests from the queue for this client only
-// Cancel the service if request already passed to Tsy
-//
- {
- CReqEntry* reqEntry=NULL;
- while (reqEntry=PhoneOwner()->FindClientReqInWaitList(aSession,aSubSessionHandle),reqEntry)
- CompleteAndDestroyReq(reqEntry,KErrCancel);
-
- CancelActiveReq(aSession,aSubSessionHandle);
- }
-
-void CTelObject::FlushReqs(CTelSession* aSession,const TInt aSubSessionHandle)
-//
-// Flush outstanding requests from the queue for this client only
-// Cancel the service if request already passed to Tsy
-// Return ETrue if it have to create a dummy session
-//
- {
- CReqEntry* reqEntry=NULL;
- // wait list
- while (reqEntry=PhoneOwner()->FindClientReqInWaitList(aSession,aSubSessionHandle),reqEntry)
- DestroyReq(reqEntry);
-
- CancelActiveReq(aSession,aSubSessionHandle);
-
- }
-
-CPhoneBase* CTelObject::PhoneOwner() const
-//
-// Get the owner handle
-//
- {
- return iPhoneOwner;
- }
-
-void CTelObject::SetPhoneOwner(CPhoneBase* aPhoneOwner)
-//
-// Set the owner of phone
-//
- {
- iPhoneOwner=aPhoneOwner;
- }
-
-void CTelObject::GetMessageDescriptorSizes(const RMessage2& aMessage,TInt &aSize1, TInt &aSize2) const
- {
- TInt messageType=aMessage.Int1();
- aSize1=0;
- aSize2=0;
-
- if (messageType!=EIsaNull &&
- messageType!=EIsaCancelMessage &&
- messageType!=EIsPriorityClientReqWithNull)
- { // we're going to create server-side buffer
- TInt basicMsgType = messageType&(~(KUnicodeReq|KPriorityClientReq));
-
- if (messageType==EIsaNarrowAndUnicodeDoubleDesTobeSet)
- basicMsgType=EIsaDoubleDesTobeSet;
- if (messageType==EIsaNarrowAndUnicodeDoubleDesTobeRead)
- basicMsgType=EIsaDoubleDesTobeRead;
-
- switch (basicMsgType)
- {
- case EIsaDoubleDesTobeSet:// if we're setting data, get length
- aSize2=aMessage.GetDesLength(2); // no break
- case EIsaDesTobeSet:
- aSize1=aMessage.GetDesLength(0);
- break;
- case EIsaDoubleDesTobeRead:// if we're reading data, get max length
- aSize2=aMessage.GetDesMaxLength(2); // no break
- case EIsaDesTobeRead:
- aSize1=aMessage.GetDesMaxLength(0);
- break;
- case EIsaNarrowDesToSetAndGet:
- aSize1=aMessage.GetDesLength(0); // set data
- aSize2=aMessage.GetDesMaxLength(2); // get data
- break;
- case EIsaNarrowDesToGetUnicodeDesToSet:
- aSize1=aMessage.GetDesMaxLength(0); // get data
- aSize2=aMessage.GetDesLength(2); // set data
- break;
- case EIsaUnicodeDesToSetAndGet:
- aSize1=aMessage.GetDesLength(0); // set data
- aSize2=aMessage.GetDesMaxLength(2); // get data
- break;
- case EIsaUnicodeDesToGetNarrowDesToSet:
- aSize1=aMessage.GetDesLength(0); // set data
- aSize2=aMessage.GetDesMaxLength(2); // get data
- break;
- default:
- PanicClient(EEtelPanicInvalidRequestType,aMessage);
- break;
- }
- }
- }
-
-TBool CTelObject::IsSameMessageType(const RMessage2& aMessage,CReqEntry* aReqEntry) const
- {
- TInt size1;
- TInt size2;
- TInt ptrSize=sizeof(TPtr8);
- GetMessageDescriptorSizes(aMessage, size1, size2);
-
- if(size1)
- {
- CheckAndResize(size1,aMessage);
- size1+=ptrSize;
- }
- if (size2)
- {
- CheckAndResize(size2,aMessage);
- size2+=ptrSize;
- }
- if(aReqEntry->iBuffer->EqualSizes(size1,size2))
- {
- return ETrue;
- }
- return EFalse;
- }
-
-void CTelObject::CompleteOrBufferRead(const RMessage2& aMessage, CReqEntry* aReqEntry)
-//
-// Check and complete if possible this notification/multislot command from
-// this subsession in the ReqActive list
-// aMessage is the message just received from the client
-// aReqEntry is the Entry previously created when the same client called the same function
-//
- {
- if(aReqEntry->iMessageNulled==FALSE) // same client already posted this notification
- {
- PanicClient(EEtelPanicRequestAsyncTwice,aMessage);
- return;
- }
- TInt slots=0;
- TRAP_IGNORE(slots = NumberOfSlotsL(aReqEntry->iFunction));
- TBool sameMessageType = IsSameMessageType(aMessage, aReqEntry);
-
- if (slots>1)
- {
- TInt comparison = aReqEntry->iBuffer->CompareRWPtrs();
- if (comparison==0 && aReqEntry->iBuffer->BufferFull()==FALSE)
- { // if the client has already read value,the automatic server-TSY
- // notify request becomes the "true" request
- if(sameMessageType)
- {
- aReqEntry->iMessage=aMessage;
- aReqEntry->iMessageNulled=EFalse;
- }
- else
- {
- // cancel in ctsy
- aReqEntry->iCancelFnCalled = ETrue;
- CancelService(aReqEntry->iFunction, aReqEntry->iTsyReqHandle);
- aReqEntry->iCancelFnCalled = EFalse;
- GeneralReq(aMessage,aReqEntry->iSession,NULL);
- }
- }
- else
- {
- if (aReqEntry->iBuffer->OverFlow())
- WriteBackAndCompleteBufferedReq(aMessage,aReqEntry,KErrOverflow);
- else
- {
- if(sameMessageType)
- {
- WriteBackAndCompleteBufferedReq(aMessage,aReqEntry,KErrNone);
- }
- else
- {
- WriteBackAndCompleteBufferedReq(aMessage,aReqEntry,KErrOverflow);
- }
- }
- }
- }
- else // this is a non-registered notification (ie single-slot)
- {
- if(aReqEntry->iReadByClient)
- {
- if(sameMessageType)
- {
- aReqEntry->iMessage=aMessage;
- aReqEntry->iMessageNulled=EFalse;
- }
- else
- {
- CancelService(aReqEntry->iFunction, aReqEntry->iTsyReqHandle);
- GeneralReq(aMessage,aReqEntry->iSession,NULL);
- }
- }
- else // Client has not read this new value yet
- {
- if(sameMessageType)
- {
- WriteBackAndCompleteBufferedReq(aMessage,aReqEntry,KErrNone);
- }
- else
- {
- WriteBackAndCompleteBufferedReq(aMessage,aReqEntry,KErrOverflow);
- }
- }
- }
- }
-
-void CTelObject::CheckAndResize(TInt& aSizeOfData,const RMessage2& aMessage) const
-//
-// Checks that size of data is non-zero - if not, panic client.
-// Also checks that size of data is word-aligned, ie a multiple of 4 bytes.
-// If not, ensure that in the space in buffer for data is word-aligned.
-//
- {
- if(aSizeOfData<0)
- PanicClient(EEtelPanicDesLengthNegative,aMessage);
- aSizeOfData=(aSizeOfData+3)&~3;
- }
-
-HEtelBufC8* CTelObject::CreateNarrowBufferLC(RHeap* aHeap,const RMessage2& aMessage,TUint aIndexOfClientPtr1,TUint aIndexOfClientPtr2,TInt& aSize1,TInt& aSize2,TInt aNoOfSlots) const
-//
-// aSize1 = size of 1st descriptor buffer
-// aSize2 = size of 2nd descriptor buffer (default=0)
-// aHeap may be NULL if the priority heap is not to be used
-// aNoOfSlots will usually be 1. Only if this request is a notification that requires
-// registering, ie increasing the number of events the server will buffer, will it be greater than 1
-//
- {
- TInt desSize1=aSize1;
- TInt desSize2=aSize2;
- CheckAndResize(aSize1,aMessage);
-
- TInt ptrSize=sizeof(TPtr8);
- TInt allocSize=aSize1+ptrSize;
- if (aSize2)
- {
- CheckAndResize(aSize2,aMessage);
- allocSize += aSize2+ptrSize;
- }
- HEtelBufC8* buf = HEtelBufC8::NewMaxLC(allocSize*aNoOfSlots,aHeap); // allocate a buffer for the Des and Data
-
- TPtr8 firstptrDes1(const_cast<TUint8*> (buf->Des().Left(ptrSize).Ptr()),ptrSize,ptrSize); // carve the thing up
- TPtr8 firstdataDes1(const_cast<TUint8*> (buf->Des().Mid(ptrSize,aSize1).Ptr()),desSize1,desSize1);
- TPtr8 firstdataDes2(NULL,0,0);
- aMessage.ReadL(aIndexOfClientPtr1,firstdataDes1);// Read the Data. If it leaves, buf will be cleaned up
- firstptrDes1.Copy(reinterpret_cast<TUint8*> (&firstdataDes1),ptrSize); // Copy the new Des
- if (aSize2)
- // Construct Second descriptor
- {
- TPtr8 firstptrDes2(const_cast<TUint8*> (buf->Des().Mid(ptrSize+aSize1,ptrSize).Ptr()),ptrSize,ptrSize);
- firstdataDes2.Set(const_cast<TUint8*> (buf->Des().Mid((ptrSize*2)+aSize1,aSize2).Ptr()),desSize2,desSize2);
- aMessage.ReadL(aIndexOfClientPtr2,firstdataDes2);
- firstptrDes2.Copy(reinterpret_cast<TUint8*> (&firstdataDes2),ptrSize);
- }
- for (TInt i=1; i<aNoOfSlots;i++)
- {// Copy descriptors into each slot
- TPtr8 ptrDes1(const_cast<TUint8*> (buf->Des().Mid(i*allocSize,ptrSize).Ptr()),ptrSize,ptrSize);
- TPtr8 dataDes1(const_cast<TUint8*> (buf->Des().Mid(i*allocSize+ptrSize,aSize1).Ptr()),desSize1,desSize1);
- dataDes1.Copy(firstdataDes1);
- ptrDes1.Copy(reinterpret_cast<TUint8*> (&dataDes1),ptrSize);
- if (aSize2)
- {
- TPtr8 ptrDes2(const_cast<TUint8*> (buf->Des().Mid(i*allocSize+ptrSize+aSize1,ptrSize).Ptr()),ptrSize,ptrSize);
- TPtr8 dataDes2(const_cast<TUint8*> (buf->Des().Mid(i*allocSize+(ptrSize*2)+aSize1).Ptr()),desSize2,desSize2);
- dataDes2.Copy(firstdataDes2);
- ptrDes2.Copy(reinterpret_cast<TUint8*> (&dataDes2),ptrSize);
- }
- }
- return buf;
- }
-
-HEtelBufC16* CTelObject::CreateUnicodeBufferLC(RHeap* aHeap,const RMessage2& aMessage,TUint aIndexOfClientPtr1,TUint aIndexOfClientPtr2,TInt& aSize1,TInt& aSize2,TInt aNoOfSlots) const
-//
-// We place both parameters in the same buffer which is either narrow or unicode (unicode in this case)
-// Should a function ever require one parameter to be narrow and the other unicode,
-// will need to review.
-//
- {
- TInt desSize1=aSize1;
- TInt desSize2=aSize2;
- CheckAndResize(aSize1,aMessage);
- TInt ptrSize=sizeof(TPtr16);
- TInt allocSize=aSize1+ptrSize;
- if (aSize2)
- {
- CheckAndResize(aSize2,aMessage);
- allocSize += aSize2+ptrSize;
- }
- HEtelBufC16* buf = HEtelBufC16::NewMaxLC(allocSize*aNoOfSlots,aHeap); // allocate a buffer for the Des and Data
-
- TPtr16 firstptrDes1(const_cast<TUint16*> (buf->Des().Left(ptrSize).Ptr()),ptrSize,ptrSize); // carve the thing up
- TPtr16 firstdataDes1(const_cast<TUint16*> (buf->Des().Mid(ptrSize,aSize1).Ptr()),desSize1,desSize1);
- TPtr16 firstdataDes2(NULL,0,0);
- aMessage.ReadL(aIndexOfClientPtr1,firstdataDes1);// Read the Data. If it leaves, buf will be cleaned up
- firstptrDes1.Copy(reinterpret_cast<TUint16*> (&firstdataDes1),ptrSize); // Copy the new Des
- if (aSize2)
- // Construct Second descriptor
- {
- TPtr16 firstptrDes2(const_cast<TUint16*> (buf->Des().Mid(ptrSize+aSize1,ptrSize).Ptr()),ptrSize,ptrSize);
- firstdataDes2.Set(const_cast<TUint16*> (buf->Des().Mid((ptrSize*2)+aSize1,aSize2).Ptr()),desSize2,desSize2);
- aMessage.ReadL(aIndexOfClientPtr2,firstdataDes2);
- firstptrDes2.Copy(reinterpret_cast<TUint16*> (&firstdataDes2),ptrSize);
- }
- for (TInt i=1; i<aNoOfSlots;i++)
- {// Copy descriptors into each slot
- TPtr16 ptrDes1(const_cast<TUint16*> (buf->Des().Mid(i*allocSize,ptrSize).Ptr()),ptrSize,ptrSize);
- TPtr16 dataDes1(const_cast<TUint16*> (buf->Des().Mid(i*allocSize+ptrSize,aSize1).Ptr()),desSize1,desSize1);
- dataDes1.Copy(firstdataDes1);
- ptrDes1.Copy(reinterpret_cast<TUint16*> (&dataDes1),ptrSize);
- if (aSize2)
- {
- TPtr16 ptrDes2(const_cast<TUint16*> (buf->Des().Mid(i*allocSize+ptrSize+aSize1,ptrSize).Ptr()),ptrSize,ptrSize);
- TPtr16 dataDes2(const_cast<TUint16*> (buf->Des().Mid(i*allocSize+(ptrSize*2)+aSize1).Ptr()),desSize2,desSize2);
- dataDes2.Copy(firstdataDes2);
- ptrDes2.Copy(reinterpret_cast<TUint16*> (&dataDes2),ptrSize);
- }
- }
- return buf;
- }
-
-CReqEntry* CTelObject::ReqAnalyserL(const RMessage2& aMessage,CTelSession* aSession,TReqMode& aReqMode)
-//
-// Analyse the request. First search for an entry from the same client for the same request,
-// and if found either panic if this is a non-buffered request(ie the request is already
-// pending) or look at the buffer to see if there is any unread data to complete with.
-// If the identical entry was not found and this is a request of type multiple completion, search
-// for a similar one by a different client (on this TelObject) and if found simply create a new
-// entry with the same request handle that will be completed at the same time as the current
-// posted notification.
-// If this request has not been found in the active or wait lists, create the necessary
-// address space on server side
-//
- {
- HEtelBufC8* buf8=NULL;
- HEtelBufC16* buf16=NULL;
- CReqEntry* reqEntry=NULL;
-
- reqEntry = PhoneOwner()->FindSameClientEntry(aSession,aMessage.Int3(),aMessage.Function());
- if (reqEntry)
- {
- if (aReqMode&KReqModeRePostImmediately)
- {
- // same notification/buffered command has been found
- // and either the read has completed or it has been stored in
- // the request entry waiting for the completion from the TSY.
- CompleteOrBufferRead(aMessage,reqEntry);
- }
- else // found an outstanding async req - panic
- {
- PanicClient(EEtelPanicRequestAsyncTwice,aMessage);
- }
- return NULL;
- }
- TInt messageType=aMessage.Int1();
- TInt noOfSlots = 1;
- if (aReqMode&KReqModeRePostImmediately)
- noOfSlots = NumberOfSlotsL(aMessage.Function());
- TInt size1;
- TInt size2;
- if (messageType!=EIsaNull &&
- messageType!=EIsaCancelMessage &&
- messageType!=EIsPriorityClientReqWithNull)
- { // we're going to create server-side buffer
- GetMessageDescriptorSizes(aMessage, size1, size2);
- if (size1<0 || size2<0)
- {
- PanicClient(EEtelPanicBadDescriptor,aMessage);
- return NULL;
- }
- if (messageType==EIsaNarrowAndUnicodeDoubleDesTobeSet ||
- messageType==EIsaNarrowAndUnicodeDoubleDesTobeRead ||
- messageType==EIsaNarrowDesToGetUnicodeDesToSet ||
- messageType==EIsaUnicodeDesToGetNarrowDesToSet)
- {
- TInt zeroSize=0;
-
- buf8 = CreateNarrowBufferLC(aSession->EmergencyClientHeap(messageType),aMessage,0,2,size1,zeroSize,noOfSlots);
- buf16 = CreateUnicodeBufferLC(aSession->EmergencyClientHeap(messageType),aMessage,2,NULL,size2,zeroSize,noOfSlots); // the second client parameter pointer is passed as the first, so that the second parameter will be copied as the first
- }
- else
- if (messageType==EIsaUnicodeDesToSetAndGet)
- buf16 = CreateUnicodeBufferLC(aSession->EmergencyClientHeap(messageType),aMessage,0,2,size1,size2,noOfSlots);
-
- else
- if (!(aSession->IsUnicodeReq(messageType)))
- buf8 = CreateNarrowBufferLC(aSession->EmergencyClientHeap(messageType),aMessage,0,2,size1,size2,noOfSlots);
-
- else
- buf16 = CreateUnicodeBufferLC(aSession->EmergencyClientHeap(messageType),aMessage,0,2,size1,size2,noOfSlots);
- size1+=sizeof(TPtr); // passed into CBuffer::NewL() later as these sizes
- if (size2!=0) // remain zero otherwise
- size2+=sizeof(TPtr); //sizeof(TPtr)==sizeof(TPtr8)==sizeof(TPtr16)
- }
- else
- {
- size1 = 0;
- size2 = 0;
- }
- //
- // Now create the wrapper class, which manages the circular buffer.
- //
- CBuffer* buffer = CBuffer::NewL(buf8,buf16,aSession->EmergencyClientHeap(messageType),size1,size2,noOfSlots);
- if (buf8)
- CleanupStack::Pop(); // pops HEtelBufC8 off cleanup stack
- if (buf16)
- CleanupStack::Pop(); // pops HEtelBufC16 off cleanup stack
- CleanupStack::PushL(buffer); // since buffer is still not owned by anything
- //
- // Now create the request entry for this client request - even if it's not to be passed
- // down to the TSY in the case of MultipleCompletion.
- //
- reqEntry=PhoneOwner()->NewReqL(aMessage,aSession,buffer,this,aMessage.Function());
- CleanupStack::Pop();
- if (aReqMode&KReqModeMultipleCompletionEnabled)
- // this client has not currently got this request outstanding
- // but another client may have
- {
- CReqEntry* previousReq=NULL;
- previousReq=PhoneOwner()->FindByIpcAndTelObject(aMessage.Function(),this, buffer->Size()); // search in active list
- if (previousReq)
- {
- reqEntry->iTsyReqHandle=previousReq->iTsyReqHandle;
- reqEntry->iReqMode=aReqMode;
- PhoneOwner()->AddReqToActive(reqEntry);
- reqEntry=NULL;
- }
- else if (aReqMode&KReqModeFlowControlObeyed)
- {
- previousReq=PhoneOwner()->FindByIpcAndTelObjectInWaiting(aMessage.Function(),this, buffer->Size());
- if (previousReq)
- {
- reqEntry->iTsyReqHandle=previousReq->iTsyReqHandle;
- reqEntry->iReqMode=aReqMode;
- PhoneOwner()->AddReqToWaiting(reqEntry);
- reqEntry=NULL;
- }
- }
- }
- return reqEntry;
- }
-
-void CTelObject::GeneralReq(const RMessage2& aMessage,CTelSession* aSession,CReqEntry* aNewReqEntry, TBool aFromFlowControlResume)
-//
-// On any CTelObject based class, do the general processing around sequential and parallel
-// request modes for the server, before calling the pure virtual Service in the class to do
-// the actual command.
-//
- {
-
- LOGTEXT2("CTelObject::GeneralReq - IPC=%d", aMessage.Function());
- RECORD_IPC(aMessage,aSession,this,aFromFlowControlResume);
- if (aFromFlowControlResume && !aFromFlowControlResume){ ; } // avoid compiler warning when ETEL_RECORDER is not defined
-
- TInt type=aMessage.Int1();
- CReqEntry* reqEntry=NULL;
- TInt basicMsgType = type&(~(KUnicodeReq|KPriorityClientReq));
- switch(basicMsgType)
- {
- case EIsaNull:
- case EIsaDesTobeSet:
- case EIsaDesTobeRead:
- case EIsaDoubleDesTobeSet:
- case EIsaDoubleDesTobeRead:
- case EIsaNarrowAndUnicodeDoubleDesTobeSet:
- case EIsaNarrowAndUnicodeDoubleDesTobeRead:
- case EIsaNarrowDesToSetAndGet:
- case EIsaNarrowDesToGetUnicodeDesToSet:
- case EIsaUnicodeDesToSetAndGet:
- case EIsaUnicodeDesToGetNarrowDesToSet:
- {
- TInt ipc=aMessage.Function();
-
- TReqMode reqMode=0;
- TRAPD(res,(reqMode=ReqModeL(ipc)));
- if (res)
- {
- RECORD_COMPLETE_SUB(aMessage.Session(), this, aMessage.Int3(), aMessage.Function(), res);
- aMessage.Complete(res);
- return;
- }
- if (aNewReqEntry==NULL)
- {
- TRAP(res,reqEntry=ReqAnalyserL(aMessage,aSession,reqMode));
- if (res)
- {
- RECORD_COMPLETE_SUB(aMessage.Session(), this, aMessage.Int3(), aMessage.Function(), res);
- aMessage.Complete(res);
- return;
- }
- else
- if (reqEntry==NULL) // there was no need to construct another reqEntry,
- // or another reqEntry with identical IPC for a different client
- // has been added inside ReqAnalyserL()
-
- return;
- reqEntry->iReqMode = reqMode; // so ReqCompleted() needn't ask for it again
- }
- else
- reqEntry=aNewReqEntry; // aNewReqEntry has just come from the waiting list
-
- if (reqMode&KReqModeFlowControlObeyed) // flow control obeyed
- {
- if (PhoneOwner()->FlowControl())
- PhoneOwner()->AddReqToWaiting(reqEntry);
- else
- {
- PhoneOwner()->FlowControlInc();
- if (aNewReqEntry==NULL)
- PhoneOwner()->AddReqToActive(reqEntry);
- res=Service(aMessage,reqEntry);
- if (res!=KErrNone) // can not do the service to tsy properly
- {
- CompleteAndDestroyReq(reqEntry,res);
- PhoneOwner()->FlowControlDec(); // Dec() as service is being abandoned
- }
- }
- }
- else // Ignored
- {
- PhoneOwner()->AddReqToActive(reqEntry);
- if (reqMode&KReqModeRePostImmediately)
- res=RegisterNotification(ipc); // this tells the TSY the first time any client
- // calls a particular notification.
- if (res!=KErrNone)
- CompleteAndDestroyReq(reqEntry,res);
- else
- {
- res=Service(aMessage,reqEntry); // down to the TSY
- if (res!=KErrNone)
- CompleteAndDestroyReq(reqEntry,res);
- }
- }
- break;
- }
- case EIsaCancelMessage:
- // This is for Cancel Req - Int0 contains the original IPC
- {
- TInt cancelIpc=aMessage.Int0();
- reqEntry=PhoneOwner()->FindClientInWaiting(aSession,aMessage.Int3(),cancelIpc);
- if(reqEntry!=NULL) // Is it Waiting to be passed to the TSY?
- {
- CompleteAndDestroyReq(reqEntry,KErrCancel); // If yes then complete it.
- RECORD_COMPLETE_SUB(aMessage.Session(), this, aMessage.Int3(), aMessage.Function(), KErrNone);
- aMessage.Complete(KErrNone);
- return;
- }
- reqEntry=PhoneOwner()->FindClientInActive(aSession,aMessage.Int3(),cancelIpc);
- if(reqEntry) // found in active list
- {
- TReqMode reqMode=0;
- TRAPD(res,(reqMode=ReqModeL(reqEntry->iFunction)));
- if (res)
- {
- // client cannot check return value of Cancel()
- // so use return value of original function call
- RECORD_COMPLETE_SUB(reqEntry->iMessage.Session(), this, reqEntry->iMessage.Int3(), reqEntry->iMessage.Function(), res);
- reqEntry->iMessage.Complete(res);
- return;
- }
- if (reqMode&KReqModeRePostImmediately && reqEntry->iMessageNulled)
- {
- // client has called Cancel on a notification
- // after it had completed to the client
- RECORD_COMPLETE_SUB(aMessage.Session(), this, aMessage.Int3(), aMessage.Function(), KErrNone);
- aMessage.Complete(KErrNone);
- return;
- }
- // so now we know the client must have the request outstanding
- if (reqMode&KReqModeMultipleCompletionEnabled && !(reqEntry->iPlacedRequest))
- {
- CompleteAndDestroyReq(reqEntry,KErrCancel); // the request hadn't been passed to the TSY
- RECORD_COMPLETE_SUB(aMessage.Session(), this, aMessage.Int3(), aMessage.Function(), KErrNone);
- aMessage.Complete(KErrNone);
- return;
- }
- // so the request is outstanding on the TSY
- if (reqEntry->iCancelFnCalled==FALSE)
- {
- reqEntry->iCancelFnCalled=ETrue;
- TInt status=CancelService(aMessage.Int0(),reqEntry->iTsyReqHandle);
- if(status!=KErrNone)
- CompleteAndDestroyReq(reqEntry,status);
- }
- }
- RECORD_COMPLETE_SUB(aMessage.Session(), this, aMessage.Int3(), aMessage.Function(), KErrNone);
- aMessage.Complete(KErrNone);
- }
- break;
-
- case EIsaCancelSubSession:
- // This is a special case for cancelling all asynchronous requests for this subsession
- {
- CancelSubSession(aSession,aMessage.Int3());
- RECORD_COMPLETE_SUB(aMessage.Session(), this, aMessage.Int3(), aMessage.Function(), KErrNone);
- aMessage.Complete(KErrNone);
- }
- break;
-
- default:
- PanicClient(EEtelPanicInvalidRequestType,aMessage);
- break;
- }
- }
-
-EXPORT_C void CTelObject::ReqCompleted(const TTsyReqHandle aTsyReqHandle,const TInt aError)
-//
-// General complete function for all CTelObject derived classes
-//
- {
- __ASSERT_ALWAYS(aTsyReqHandle!=TSY_HANDLE_INIT_VALUE,Fault(EEtelFaultNotRecognisedTsyHandle));
- TInt ipc=0;
- CReqEntry* updatedReqEntry = NULL;
- CReqEntry* nextPostedReqEntry = NULL;
- updatedReqEntry=PhoneOwner()->FindByTsyHandleAndPlacedRequest(aTsyReqHandle);
- __ASSERT_ALWAYS(updatedReqEntry!=NULL, Fault(EEtelFaultCompletionReceivedWithNoReqPackage));
-
- TInt error = ResolveError(updatedReqEntry->iSession,aError); // set error as either low or high byte
-
- ipc=updatedReqEntry->iFunction;
- LOGTEXT4("CTelObject::ReqCompleted, IPC=%d, TsyHandle=%d, Error=%d", ipc, aTsyReqHandle, aError);
-
- TReqMode reqMode = updatedReqEntry->iReqMode;
- TBool ret=EFalse;
- if (error!=KErrCancel)
- {
- // Multiple-completion malarky.
- // Don't copy data across to other buffers and complete their reqs if TSY knows about
- // each client that has called it. In that case,
- // TSY will fill in the appropriate client's buffer and complete each separately.
- if (reqMode&KReqModeMultipleCompletionEnabled)
- PhoneOwner()->CheckAndCompleteAllActive(updatedReqEntry,reqMode,ipc,aError);
-
- if (reqMode&KReqModeRePostImmediately && error==KErrNone)
- nextPostedReqEntry = updatedReqEntry;
- updatedReqEntry->iBuffer->IncWrite();
- }
- else // if a cancel comes from the TSY, then if it is a notification
- // there may be other clients who have also called the notification and who
- // have entries in active list, so one of these must be re-posted.
- {
- if (reqMode&KReqModeMultipleCompletionEnabled)
- nextPostedReqEntry = PhoneOwner()->FindThisReqByAnotherClient(updatedReqEntry->iSession,updatedReqEntry->iMessage.Int3(),ipc,updatedReqEntry->iBuffer->Size(),this);
- if (!nextPostedReqEntry)
- // then we don't want to post any other client's requests in place of this one
- {
- nextPostedReqEntry = PhoneOwner()->FindNonCancelledClientReq(updatedReqEntry->iSession,updatedReqEntry->iMessage.Int3(),ipc);
- __ASSERT_DEBUG(updatedReqEntry!=nextPostedReqEntry, Fault(EEtelFaultCancelErrorWithoutCancelled));
- if (nextPostedReqEntry==NULL && reqMode&KReqModeRePostImmediately)
- {
- TInt ret = DeregisterNotification(ipc); // no more clients are interested so
- // tell TSY to stop looking at notifies
- if (ret!=KErrNone)
- error=ret; // so the KErrCancel wouldn't reach the client
- }
- }
- }
- if (reqMode & KReqModeRePostImmediately)
- UpdateAndCompleteIfNecessary(updatedReqEntry,error); // this will destroy the reqEntry
- // if an error occurred.
- else
- WriteBackAndCompleteReq(updatedReqEntry,error);
- if (nextPostedReqEntry) // will be NULL if no following request for TSY
- {
- if(nextPostedReqEntry->iReqMode&KReqModeFlowControlObeyed)
- { // since the request mode is flow control obeyed, increment the flow control counter
- FlowControlSuspend();
- }
- Service(nextPostedReqEntry->iMessage,nextPostedReqEntry);
- }
-
-
- if (!(reqMode&KReqModeFlowControlObeyed)) // If flow control not enabled, go home
- ret=ETrue;
-
-// So everything below assumes it obeyed flow control
-// Resume Flow control ...
- if (!ret)
- FlowControlResume();
-//
-// Check and destroying the dummy session
-//
- CheckAndDestroyDummySubSession();
- }
-
-TInt CTelObject::ResolveError(CTelSession* aSession, const TInt aError) const
-/**
- * Converts a coded error into the correct error to return. The coded error value
- * allows an extended error code to be present allong with a basic error code. If
- * the client has specified awareness of the extended codes, then they are returned.
- * Otherwise the basic error code will be returned. The advanced error codes do not
- * overlap the basic ones.
- *
- * In the case of no extended error code available, then the core error code will
- * be returned regardless of the client's extended error granularity.
- *
- * @return Either the basic error code or the advanced error coded if available and
- * requested.
- * @param aSession The CTelSession of the client.
- * @param aError The coded error.
- */
- {
- //
- // Handle the common cases to make the code more efficent....
- //
- if ((aError==KErrNone) || (aError==KErrCancel))
- {
- return aError;
- }
-
- //
- // 'aError' is coded into two halves (eXtended and baSic): 0xXXXXSSSS. Take the
- // top 16 bits for the eXtended code, and the bottom 16 bit for the baSic code.
- //
- // So, basicError becomes 0xffffSSSS and extendedError becomes 0xffffXXXX.
- //
- // A special case exists if the 16 bits were 0x0000 as this is KErrNone, and we must
- // treat this as a positive int and not a negative one (e.g. clear the top 16 bits).
- //
- TInt basicError = (aError | 0xFFFF0000);
- TInt extendedError = ((aError >> 16) | 0xFFFF0000);
-
- if (basicError == (TInt)(0xffff0000))
- {
- basicError = KErrNone;
- }
-
- if (extendedError == (TInt)(0xffff0000))
- {
- extendedError = KErrNone;
- }
-
- //
- // If the an extended error code is available and if client wants extended errors
- // then return the extended error. Otherwise return the basic error code.
- //
- // The extended error is not available if 'extendedError' is KErrNotFound (e.g.
- // the top 16 bits were 0xffff.
- //
- if (extendedError != KErrNotFound && aSession->IsExpectingExtendedError())
- {
- return extendedError;
- }
- else
- {
- return basicError;
- }
- }
-
-void CTelObject::UpdateAndCompleteIfNecessary(CReqEntry* aReqEntry,TInt aError) const
-//
-// If client has this request outstanding on the server, complete it, otherwise set Read
-// flag to false. Destroy the request if an error has occurred.
-//
- {
- if (aReqEntry->iMessageNulled)
- aReqEntry->iReadByClient=EFalse;
- else
- WriteBackAndCompleteBufferedReq(aReqEntry->iMessage,aReqEntry,aError);
- if (aError)
- DestroyReq(aReqEntry);
- }
-
-void CTelObject::CheckAndDestroyDummySubSession()
- {
- if (iActiveReqCount)
- {
- iActiveReqCount--;
- LOGTEXT2("In CheckAndDestroyDummySubSession(), iActiveReqCount down to %d", iActiveReqCount);
- if ((iActiveReqCount==0) && (iCreateDummy==FALSE))
- {
- __ASSERT_ALWAYS(iDestroyDummySubSession!=NULL,Fault(EEtelFaultBadTelSessionPointer));
- if (!(iDestroyDummySubSession->IsActive())) // only set going if not already active!
- {
- iDestroyDummySubSession->Call();
- iTelServer->Dec();
- }
- }
- }
- else if (iCreateDummy)
- {
- __ASSERT_ALWAYS(iDestroyDummySubSession!=NULL,Fault(EEtelFaultBadTelSessionPointer));
- if (!(iDestroyDummySubSession->IsActive())) // only set going if not already active!
- {
- iDestroyDummySubSession->Call();
- iTelServer->Dec();
- }
- iCreateDummy=EFalse;
- }
- }
-
-void CTelObject::WriteBackAndCompleteBufferedReq(const RMessage2& aNewMessage,CReqEntry* aReqEntry,TInt aError) const
- {
- TInt basicMessageType =0;
- basicMessageType = (aNewMessage.Int1() & ~(KPriorityClientReq));
- switch (basicMessageType)
- {
- case EIsaNull:
- if (aReqEntry->iClientInterested)
- {
- RECORD_COMPLETE_SUB(aNewMessage.Session(), this, aNewMessage.Int3(), aNewMessage.Function(), aError);
- aNewMessage.Complete(aError);
- }
- break;
- case EIsaDesTobeRead:
- case EIsaDoubleDesTobeRead:
- if (aReqEntry->iClientInterested)
- {
- __ASSERT_ALWAYS(aReqEntry->iBuffer->iBuf8!=NULL,Fault(EETelFaultRequestWithoutBuffer));
- TDes8* dataDes1=BufferDes1(aReqEntry->iBuffer,CBuffer::ESlotRead);
- __ASSERT_ALWAYS(dataDes1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
-
- TRAPD(ret,aNewMessage.WriteL(0,*dataDes1)); // if this fails, panic the client
- if(ret!=KErrNone)
- {
- PanicClient(EEtelPanicBadDescriptor,aNewMessage);
- break;
- }
-
- if (basicMessageType==EIsaDoubleDesTobeRead)
- {
- TDes8* dataDes2=BufferDes2(aReqEntry->iBuffer,CBuffer::ESlotRead);
- __ASSERT_ALWAYS(dataDes2!=NULL,Fault(EEtelFaultDes2DoesNotExist));
-
- TRAP(ret,aNewMessage.WriteL(2,*dataDes2));
- if(ret!=KErrNone)
- {
- PanicClient(EEtelPanicBadDescriptor,aNewMessage);
- break;
- }
- }
- RECORD_COMPLETE_SUB(aNewMessage.Session(), this, aNewMessage.Int3(), aNewMessage.Function(), aError);
- aNewMessage.Complete(aError);
- }
- break;
- case EIsaUnicodeDesTobeRead:
- case EIsaUnicodeDoubleDesTobeRead:
- {
- if (aReqEntry->iClientInterested)
- {
- __ASSERT_ALWAYS(aReqEntry->iBuffer->iBuf16!=NULL,Fault(EETelFaultRequestWithoutBuffer));
- // The TDes16 will be at the start of the HBufC buffer
- TDes16* unicodeDataDes1=BufferDes1u(aReqEntry->iBuffer,CBuffer::ESlotRead);
- __ASSERT_ALWAYS(unicodeDataDes1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
-
- TRAPD(ret,aNewMessage.WriteL(0,*unicodeDataDes1));
- if(ret!=KErrNone)
- {
- PanicClient(EEtelPanicBadDescriptor,aNewMessage);
- break;
- }
-
- if (basicMessageType==EIsaUnicodeDoubleDesTobeRead)
- {
- TDes16* unicodeDataDes2=BufferDes2u(aReqEntry->iBuffer,CBuffer::ESlotRead);
- __ASSERT_ALWAYS(unicodeDataDes2!=NULL,Fault(EEtelFaultDes2DoesNotExist));
-
- TRAP(ret,aNewMessage.WriteL(2,*unicodeDataDes2));
- if(ret!=KErrNone)
- {
- PanicClient(EEtelPanicBadDescriptor,aNewMessage);
- break;
- }
- }
- RECORD_COMPLETE_SUB(aNewMessage.Session(), this, aNewMessage.Int3(), aNewMessage.Function(), aError);
- aNewMessage.Complete(aError);
- }
- }
- break;
-
- case EIsaNarrowAndUnicodeDoubleDesTobeRead:
- {
- if (aReqEntry->iClientInterested)
- {
- __ASSERT_ALWAYS(aReqEntry->iBuffer->iBuf16!=NULL,Fault(EETelFaultRequestWithoutBuffer));
- TDes8* dataDes1=BufferDes1(aReqEntry->iBuffer,CBuffer::ESlotRead);
- __ASSERT_ALWAYS(dataDes1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
-
- TRAPD(ret,aNewMessage.WriteL(0,*dataDes1));
- if(ret!=KErrNone)
- {
- PanicClient(EEtelPanicBadDescriptor,aNewMessage);
- break;
- }
-
- TDes16* unicodeDataDes2=BufferDes2u(aReqEntry->iBuffer,CBuffer::ESlotRead);
- __ASSERT_ALWAYS(unicodeDataDes2!=NULL,Fault(EEtelFaultDes2DoesNotExist));
-
- TRAP(ret,aNewMessage.WriteL(2,*unicodeDataDes2));
- if(ret!=KErrNone)
- {
- PanicClient(EEtelPanicBadDescriptor,aNewMessage);
- break;
- }
- RECORD_COMPLETE_SUB(aNewMessage.Session(), this, aNewMessage.Int3(), aNewMessage.Function(), aError);
- aNewMessage.Complete(aError);
- }
- }
- break;
-
- case EIsaNarrowDesToSetAndGet:
- {
- if (aReqEntry->iClientInterested)
- {
- __ASSERT_ALWAYS(aReqEntry->iBuffer->iBuf8!=NULL,Fault(EETelFaultRequestWithoutBuffer));
- TDes8* dataDes2=BufferDes2(aReqEntry->iBuffer,CBuffer::ESlotRead);
- __ASSERT_ALWAYS(dataDes2!=NULL,Fault(EEtelFaultDes2DoesNotExist));
-
- TRAPD(ret,aNewMessage.WriteL(2,*dataDes2));
- if(ret!=KErrNone)
- {
- PanicClient(EEtelPanicBadDescriptor,aNewMessage);
- break;
- }
- RECORD_COMPLETE_SUB(aNewMessage.Session(), this, aNewMessage.Int3(), aNewMessage.Function(), aError);
- aNewMessage.Complete(aError);
- }
- }
- break;
-
- case EIsaUnicodeDesToGetNarrowDesToSet:
- case EIsaUnicodeDesToSetAndGet:
- if (aReqEntry->iClientInterested)
- {
- __ASSERT_ALWAYS(aReqEntry->iBuffer->iBuf16!=NULL,Fault(EETelFaultRequestWithoutBuffer));
- TDes16* dataDes2=BufferDes2u(aReqEntry->iBuffer,CBuffer::ESlotRead);
- __ASSERT_ALWAYS(dataDes2!=NULL,Fault(EEtelFaultDes2DoesNotExist));
-
- TRAPD(ret,aNewMessage.WriteL(2,*dataDes2));
- if(ret!=KErrNone)
- {
- PanicClient(EEtelPanicBadDescriptor,aNewMessage);
- break;
- }
- RECORD_COMPLETE_SUB(aNewMessage.Session(), this, aNewMessage.Int3(), aNewMessage.Function(), aError);
- aNewMessage.Complete(aError);
- }
- break;
-
- case EIsaNarrowDesToGetUnicodeDesToSet:
- {
- if (aReqEntry->iClientInterested)
- {
- __ASSERT_ALWAYS(aReqEntry->iBuffer->iBuf8!=NULL,Fault(EETelFaultRequestWithoutBuffer));
- TDes8* dataDes1=BufferDes1(aReqEntry->iBuffer,CBuffer::ESlotRead);
- __ASSERT_ALWAYS(dataDes1!=NULL,Fault(EEtelFaultDes1DoesNotExist));
-
- TRAPD(ret,aNewMessage.WriteL(0,*dataDes1));
- if(ret!=KErrNone)
- {
- PanicClient(EEtelPanicBadDescriptor,aNewMessage);
- break;
- }
- RECORD_COMPLETE_SUB(aNewMessage.Session(), this, aNewMessage.Int3(), aNewMessage.Function(), aError);
- aNewMessage.Complete(aError);
- }
- }
- break;
-
- case EIsaDesTobeSet:
- case EIsaDoubleDesTobeSet:
- case EIsaUnicodeDesTobeSet:
- case EIsaUnicodeDoubleDesTobeSet:
- case EIsaNarrowAndUnicodeDoubleDesTobeSet:
- case EIsaCancelMessage:
- case EIsaCancelSubSession:
-
- default:
- Fault(EEtelFaultBadMessageType);
- break;
- }
- if (aError==KErrNone || aError==KErrOverflow)
- {
- aReqEntry->iReadByClient=ETrue;
- aReqEntry->iMessageNulled=ETrue;
- aReqEntry->iBuffer->IncRead();
- }
- }
-
-void CTelObject::WriteBackAndCompleteReq(CReqEntry* aReqEntry,const TInt aError) const
-//
-// Complete a request entry and write data back to client
-//
- {
- __ASSERT_ALWAYS(aReqEntry!=NULL,Fault(EEtelFaultCompleteReqWithoutReqEntry));
- LOGTEXT("CTelObject::WriteBackAndCompleteReq");
- TInt basicMessageType = (aReqEntry->iMessage.Int1() & ~KPriorityClientReq);
-
- switch (basicMessageType)
- {
- case EIsaNull:
- aReqEntry->CompleteAndDeque(aError);
- break;
- case EIsaDesTobeSet:
- case EIsaDoubleDesTobeSet:
- __ASSERT_ALWAYS(aReqEntry->iBuffer->iBuf8!=NULL,Fault(EETelFaultRequestWithoutBuffer));
- aReqEntry->CompleteAndDeque(aError);
- break;
- case EIsaUnicodeDesTobeSet:
- case EIsaUnicodeDoubleDesTobeSet:
- case EIsaNarrowAndUnicodeDoubleDesTobeSet:
- __ASSERT_ALWAYS(aReqEntry->iBuffer->iBuf16!=NULL,Fault(EETelFaultRequestWithoutBuffer));
- aReqEntry->CompleteAndDeque(aError);
- break;
- case EIsaDesTobeRead:
- case EIsaDoubleDesTobeRead:
- {
- if (aReqEntry->iClientInterested)
- {
- __ASSERT_ALWAYS(aReqEntry->iBuffer->iBuf8!=NULL,Fault(EETelFaultRequestWithoutBuffer));
- // The TPtr8 will be at the start of the HBufC buffer
- TDes8* dataDes1=BufferDes1(aReqEntry->iBuffer,CBuffer::ESlotRead);
- __ASSERT_ALWAYS(dataDes1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
-
- TRAPD(ret,aReqEntry->iMessage.WriteL(0,*dataDes1));
- if(ret!=KErrNone)
- {
- PanicClient(EEtelPanicBadDescriptor,aReqEntry->iMessage);
- break;
- }
-
- if (basicMessageType==EIsaDoubleDesTobeRead)
- {
- TDes8* dataDes2=BufferDes2(aReqEntry->iBuffer,CBuffer::ESlotRead);
-
- TRAP(ret,aReqEntry->iMessage.WriteL(2,*dataDes2));
- if(ret!=KErrNone)
- {
- PanicClient(EEtelPanicBadDescriptor,aReqEntry->iMessage);
- break;
- }
- }
- }
- aReqEntry->CompleteAndDeque(aError);
- }
- break;
- case EIsaUnicodeDesTobeRead:
- case EIsaUnicodeDoubleDesTobeRead:
- {
- if (aReqEntry->iClientInterested)
- {
- __ASSERT_ALWAYS(aReqEntry->iBuffer->iBuf16!=NULL,Fault(EETelFaultRequestWithoutBuffer));
- TDes16* dataDes1=BufferDes1u(aReqEntry->iBuffer,CBuffer::ESlotRead);
-
- TRAPD(ret,aReqEntry->iMessage.WriteL(0,*dataDes1));
- if(ret!=KErrNone)
- {
- PanicClient(EEtelPanicBadDescriptor,aReqEntry->iMessage);
- break;
- }
-
- if (basicMessageType==EIsaUnicodeDoubleDesTobeRead)
- {
- TDes16* dataDes2=BufferDes2u(aReqEntry->iBuffer,CBuffer::ESlotRead);
- __ASSERT_ALWAYS(dataDes2!=NULL,Fault(EEtelFaultDes2DoesNotExist));
-
- TRAP(ret,aReqEntry->iMessage.WriteL(2,*dataDes2));
- if(ret!=KErrNone)
- {
- PanicClient(EEtelPanicBadDescriptor,aReqEntry->iMessage);
- break;
- }
- }
- }
- aReqEntry->CompleteAndDeque(aError);
- }
- break;
- case EIsaNarrowAndUnicodeDoubleDesTobeRead:
- {
- if (aReqEntry->iClientInterested)
- {
- __ASSERT_ALWAYS(aReqEntry->iBuffer->iBuf16!=NULL,Fault(EETelFaultRequestWithoutBuffer));
- TDes8* dataDes1=BufferDes1(aReqEntry->iBuffer,CBuffer::ESlotRead);
- __ASSERT_ALWAYS(dataDes1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
-
- TRAPD(ret,aReqEntry->iMessage.WriteL(0,*dataDes1));
- if(ret!=KErrNone)
- {
- PanicClient(EEtelPanicBadDescriptor,aReqEntry->iMessage);
- break;
- }
-
- TDes16* unicodeDataDes2=BufferDes2u(aReqEntry->iBuffer,CBuffer::ESlotRead);
- __ASSERT_ALWAYS(unicodeDataDes2!=NULL,Fault(EEtelFaultDes2DoesNotExist));
-
- TRAP(ret,aReqEntry->iMessage.WriteL(2,*unicodeDataDes2));
- if(ret!=KErrNone)
- {
- PanicClient(EEtelPanicBadDescriptor,aReqEntry->iMessage);
- break;
- }
- }
- aReqEntry->CompleteAndDeque(aError);
- }
- break;
-
- case EIsaNarrowDesToSetAndGet:
- {
- if (aReqEntry->iClientInterested)
- {
- __ASSERT_ALWAYS(aReqEntry->iBuffer->iBuf8!=NULL,Fault(EETelFaultRequestWithoutBuffer));
- // only write back the second parameter
- TDes8* dataDes2=BufferDes2(aReqEntry->iBuffer,CBuffer::ESlotRead);
- __ASSERT_ALWAYS(dataDes2!=NULL,Fault(EETelFaultRequestWithoutBuffer));
-
- TRAPD(ret,aReqEntry->iMessage.WriteL(2,*dataDes2));
- if(ret!=KErrNone)
- {
- PanicClient(EEtelPanicBadDescriptor,aReqEntry->iMessage);
- break;
- }
- }
- aReqEntry->CompleteAndDeque(aError);
- }
- break;
-
- case EIsaNarrowDesToGetUnicodeDesToSet:
- {
- if (aReqEntry->iClientInterested)
- {
- __ASSERT_ALWAYS(aReqEntry->iBuffer->iBuf8!=NULL,Fault(EETelFaultRequestWithoutBuffer));
- // only write back the first parameter
- TDes8* dataDes1=BufferDes1(aReqEntry->iBuffer,CBuffer::ESlotRead);
- __ASSERT_ALWAYS(dataDes1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
-
- TRAPD(ret,aReqEntry->iMessage.WriteL(0,*dataDes1));
- if(ret!=KErrNone)
- {
- PanicClient(EEtelPanicBadDescriptor,aReqEntry->iMessage);
- break;
- }
- }
- aReqEntry->CompleteAndDeque(aError);
- }
- break;
-
- case EIsaUnicodeDesToSetAndGet:
- case EIsaUnicodeDesToGetNarrowDesToSet:
- {
- if (aReqEntry->iClientInterested)
- {
- __ASSERT_ALWAYS(aReqEntry->iBuffer->iBuf16!=NULL,Fault(EETelFaultRequestWithoutBuffer));
- // only write back the second parameter
- TDes16* dataDes2=BufferDes2u(aReqEntry->iBuffer,CBuffer::ESlotRead);
- __ASSERT_ALWAYS(dataDes2!=NULL,Fault(EETelFaultRequestWithoutBuffer));
-
- TRAPD(ret,aReqEntry->iMessage.WriteL(2,*dataDes2));
- if(ret!=KErrNone)
- {
- PanicClient(EEtelPanicBadDescriptor,aReqEntry->iMessage);
- break;
- }
- }
- aReqEntry->CompleteAndDeque(aError);
- }
- break;
-
- default:
- Fault(EEtelFaultBadMessageType);
- break;
- }
- aReqEntry->Deque();
- delete aReqEntry;
- }
-
-EXPORT_C void CTelObject::FlowControlSuspend()
-//
-// Suspend the Request Flow
-//
- {
- PhoneOwner()->FlowControlInc();
- }
-
-
-EXPORT_C void CTelObject::FlowControlResume()
-
-//
-// Resume the Request Flow
-//
- {
- PhoneOwner()->FlowControlDec();
- if(PhoneOwner()->FlowControl()>0) // check for outstanding request
- return;
-
- CReqEntry* reqEntry=PhoneOwner()->ActivateNextWaitingReq();
- if (reqEntry==NULL)
- return;
-
- RMessage2& message=reqEntry->iMessage;
-
- CTelObject* theObj=reqEntry->iSession->CObjectFromHandle(message.Int3());
- __ASSERT_ALWAYS(theObj!=NULL, Fault(EEtelFaultWaitingReqLostCObject));
- theObj->GeneralReq(message,reqEntry->iSession,reqEntry, ETrue);
- }
-
-//
-// Future proofing in server
-//
-EXPORT_C TInt CTelObject::DownCallOption(TInt /*aOptionNumber*/, TAny* /*aData*/)
- {
- return KErrNotSupported;
- }
-
-EXPORT_C TInt CTelObject::UpCallOption(TInt /*aOptionNumber*/, TAny* /*aData*/)
- {
- return KErrNotSupported;
- }
-
-EXPORT_C TInt CTelObject::ServerVersion() const
-//
-// Lets TSY know which version of server this is, ie which extra options the server will support.
-//
- {
- return KETelServerVersion;
- }
-
-EXPORT_C TSecurityPolicy CTelObject::GetRequiredPlatSecCaps(const TInt /*aIpc*/)
-/**
- * Default implementation of TSY side of the Etel capability policy checking delegation.
- * If the TSY does not support CustomAPIs or the TSY does not implement it's own version
- * of this virtual function, then this default implementation will get used and shall always
- * return a policy that fails the capability check.
- *
- * @return This base implementation always returns a TSecurityPolicy::EAlwaysFail.
- * @param aIpc This parameter is not used in the base implementation of this virtual function.
- */
- {
- return TSecurityPolicy(TSecurityPolicy::EAlwaysFail);
- }
-
-
-TDes8* CTelObject::BufferDes1(const CBuffer* aBuffer,CBuffer::TWhichSlot aWhichSlot) const
-//
-// Returns pointer to first descriptor in current slot. More specifically, a pointer to the
-// TPtr which is stored just before the data that it points to.
-
-// The buffer is circular, and there are
-// two "current" slots - one slot for where the next data should be written to by the TSY,
-// the other from which the client should next read from. aWhichSlot specifies which of these
-// should be returned.
-//
- {
- TDes8* des1=NULL;
- if (aBuffer->iBuf8)
- {
- TUint8* pos = aBuffer->CurrentSlotData1(aWhichSlot);
- if (pos)
- des1=reinterpret_cast<TDes8*> (pos);
- }
- return des1;
- }
-
-TDes8* CTelObject::BufferDes2(const CBuffer* aBuffer,CBuffer::TWhichSlot aWhichSlot) const
- {
- TDes8* des2=NULL;
- if (aBuffer->iBuf8)
- {
- TUint8* pos = aBuffer->CurrentSlotData2(aWhichSlot);
- if (pos)
- des2=reinterpret_cast<TDes8*> (pos);
- }
- return des2;
- }
-
-TDes16* CTelObject::BufferDes1u(const CBuffer* aBuffer,CBuffer::TWhichSlot aWhichSlot) const
- {
- TDes16* des1=NULL;
- if (aBuffer->iBuf16)
- {
- TUint16* pos = aBuffer->CurrentSlotData1u(aWhichSlot);
- if (pos)
- des1=reinterpret_cast<TDes16*> (pos);
- }
- return des1;
- }
-
-TDes16* CTelObject::BufferDes2u(const CBuffer* aBuffer,CBuffer::TWhichSlot aWhichSlot) const
- {
- TDes16* des2=NULL;
- if (aBuffer->iBuf16)
- {
- TUint16* pos = aBuffer->CurrentSlotData2u(aWhichSlot);
- if (pos)
- des2=reinterpret_cast<TDes16*> (pos);
- }
- return des2;
- }
-
-TUint8* CTelObject::Ptr1(const TDes8* aDes1) const
-//
-// return the pointer to the data of the first descriptor
-// return NULL if does not exist
-//
- {
- TUint8* ptr1=NULL;
- if (aDes1)
- ptr1=const_cast<TUint8*> (aDes1->Ptr());
- return ptr1;
- }
-
-void CTelObject::RemoveDummySubSessionDestroyer()
- {
- iDestroyDummySubSession = NULL;
- }
-
-//
-//
-// CSubSessionExtBase
-//
-//
-EXPORT_C CSubSessionExtBase::CSubSessionExtBase()
-//
-// C'Tor
-//
- {
- __DECLARE_NAME(_S("CSubSessionExtBase"));
- }
-
-EXPORT_C CSubSessionExtBase::~CSubSessionExtBase()
-//
-// D'Tor
-//
- {}
-
-TInt CSubSessionExtBase::ServiceExtFunc(const RMessage2& aMessage,CReqEntry* aReqEntry)
-//
-// Sort out Des1 and Des2 before calling ExtFunc()
-//
- {
- __ASSERT_ALWAYS(aReqEntry!=NULL,Fault(EEtelFaultCallTsyServiceWithoutReqPackage));
- TTsyReqHandle tsyReqHandle=aReqEntry->iTsyReqHandle;
-
- LOGTEXT2("Entered ServiceExtFunc with TSY handle %d", tsyReqHandle);
- TInt ret=KErrNone;
-
- TInt basicMessageType = aMessage.Int1() & ~(KPriorityClientReq);
- switch (basicMessageType)
- {
- case EIsaNull:
- case EIsaCancelMessage:
- {
- TDataPackage package; // a package with all data pointers nulled
- ret=ExtFunc(tsyReqHandle,aMessage.Function(),package);
- }
- break;
- case EIsaDesTobeSet:
- case EIsaDesTobeRead:
- case EIsaDoubleDesTobeSet:
- case EIsaDoubleDesTobeRead: // may have been multi-slot registered
- case EIsaNarrowDesToSetAndGet:
- {
- TDes8* des1 = BufferDes1(aReqEntry->iBuffer,CBuffer::ESlotWrite);
- if (!des1)
- {
- return KErrArgument;
- }
- TDes8* des2=NULL;
- if (basicMessageType==EIsaDoubleDesTobeSet ||
- basicMessageType==EIsaDoubleDesTobeRead ||
- basicMessageType==EIsaNarrowDesToSetAndGet)
- {
- des2=BufferDes2(aReqEntry->iBuffer,CBuffer::ESlotWrite);
- if (!des2)
- {
- return KErrArgument;
- }
- }
- TDataPackage package(des1,des2);
- ret=ExtFunc(tsyReqHandle,aReqEntry->iFunction,package);
- }
- break;
- case EIsaUnicodeDesTobeSet:
- case EIsaUnicodeDesTobeRead:
- case EIsaUnicodeDoubleDesTobeSet:
- case EIsaUnicodeDoubleDesTobeRead:
- case EIsaUnicodeDesToSetAndGet:
- {
- TDes16* des1 = BufferDes1u(aReqEntry->iBuffer,CBuffer::ESlotWrite);
- if (!des1)
- {
- return KErrArgument;
- }
- TDes16* des2=NULL;
- if (basicMessageType==EIsaUnicodeDoubleDesTobeSet ||
- basicMessageType==EIsaUnicodeDoubleDesTobeRead ||
- basicMessageType==EIsaUnicodeDesToSetAndGet)
- {
- des2 = BufferDes2u(aReqEntry->iBuffer,CBuffer::ESlotWrite);
- if (!des2)
- {
- return KErrArgument;
- }
- }
- TDataPackage package(des1,des2);
- ret=ExtFunc(tsyReqHandle,aReqEntry->iFunction,package);
- }
- break;
- case EIsaNarrowAndUnicodeDoubleDesTobeSet:
- case EIsaNarrowAndUnicodeDoubleDesTobeRead:
- case EIsaNarrowDesToGetUnicodeDesToSet:
- case EIsaUnicodeDesToGetNarrowDesToSet:
- {
- TDes8* des1 = BufferDes1(aReqEntry->iBuffer,CBuffer::ESlotWrite);
- if (!des1)
- {
- return KErrArgument;
- }
- TDes16* des2=NULL;
- des2=BufferDes2u(aReqEntry->iBuffer,CBuffer::ESlotWrite);
- if (!des2)
- {
- return KErrArgument;
- }
- TDataPackage package(des1,des2);
- ret=ExtFunc(tsyReqHandle,aReqEntry->iFunction,package);
- }
- break;
-
- default:
- Fault(EEtelFaultMessageTypeCorrupted);
- break;
- }
- return ret;
- }
-
-EXPORT_C TInt CSubSessionExtBase::Service(const RMessage2& aMessage, CReqEntry* aReqEntry)
-//
-// The ServiceL functionality for the ext base
-//
- {
- aReqEntry->iPlacedRequest=ETrue;
- return ServiceExtFunc(aMessage,aReqEntry);
- }
-
-EXPORT_C void CSubSessionExtBase::CloseSubSessionPreProcessing(CTelSession* aSession,const TInt aSubSessionHandle)
- {
- CreateDummySession(aSession,aSubSessionHandle);
- FlushReqs(aSession,aSubSessionHandle);
- }
-
-EXPORT_C void CSubSessionExtBase::OpenPostProcessing(CTelSession* /*aSession*/,const TInt)
-//
-// Perform post-processing after object has been added to session's CObjectIx.
-//
- {
- }
-
-EXPORT_C RHandleBase* CSubSessionExtBase::GlobalKernelObjectHandle()
- {
- return NULL;
- }
-
-EXPORT_C void CSubSessionExtBase::NullMethod1()
- {}
-
-EXPORT_C void CFaxBase::NullMethod2()
- {}
-
-//
-//
-// CLibUnloader
-//
-//
-CLibUnloader::CLibUnloader()
-//
-// C'tor
-//
- :CAsyncOneShot(CActive::EPriorityHigh)
- {
- __DECLARE_NAME(_S("CLibUnloader"));
- }
-
-CLibUnloader* CLibUnloader::NewL(RLibrary &aLib)
-//
-// New Library Unloader
-//
- {
- CLibUnloader *s=new(ELeave)CLibUnloader;
- s->iLib=aLib;
- return s;
- }
-
-CLibUnloader::~CLibUnloader()
- {
- Cancel();
- iLib.Close();
- }
-
-void CLibUnloader::RunL()
-//
-// Unload TSY module
-//
- {
- delete this;
- }
-
-//
-//
-// CPhoneFactoryBase definition
-//
-//
-EXPORT_C TBool CPhoneFactoryBase::QueryVersionSupported( TVersion const & aVersion )const
-//
-// Pass through to default QVS
-//
- {
- return(User::QueryVersionSupported(iVersion,aVersion));
- }
-
-EXPORT_C CPhoneFactoryBase::CPhoneFactoryBase()
-//
-// C'Tor
-//
- {
- __DECLARE_NAME(_S("CPhoneFactoryBase"));
- }
-
-void CPhoneFactoryBase::ConstructL(RLibrary& aLib)
-//
-// Allocate a CLibrary Unloader
-//
- {
- iLibUnloader=CLibUnloader::NewL(aLib);
- }
-
-EXPORT_C CPhoneFactoryBase::~CPhoneFactoryBase()
-//
-// D'Tor
-//
- {
- if (iLibUnloader)
- {
- LOGTEXT("About to call iLibUnloader");
- iLibUnloader->Call();
- }
- }
-
-EXPORT_C void CPhoneFactoryBase::CPhoneFactoryBase_Reserved1()
-//
-// Reserved virtual function
-//
- {}
-
-//
-// HEtelBufC definitions
-//
-
-
-//
-// HEtelBufC8
-//
-HEtelBufC8* HEtelBufC8::NewMaxLC(TInt aMaxLength,RHeap* aHeap)
- {
- __ASSERT_ALWAYS(aMaxLength>=0,Fault(EEtelFaultMaxDesLengthNegative));
-
- HEtelBufC8* pH=NULL;
- TInt size=sizeof(HEtelBufC8)+(aMaxLength*sizeof(TUint8));
- if (aHeap!=NULL)
- pH=(HEtelBufC8*)aHeap->AllocLC(size);
- else
- pH=(HEtelBufC8*)User::AllocLC(size);
- pH->iLength=aMaxLength;
- pH->iHeap=aHeap;
- pH->Des().SetLength(aMaxLength);
- return(pH);
- }
-
-TPtr8 HEtelBufC8::Des()
- {
- TUint8* ptr = reinterpret_cast<TUint8*> (((reinterpret_cast<TInt> (this)) +
- sizeof(HEtelBufC8))
- );
- return TPtr8(ptr,iLength,iLength);
- }
-
-const TUint8* HEtelBufC8::Ptr() const
- {
- return reinterpret_cast<const TUint8*> (((reinterpret_cast<TInt> (this)) +
- sizeof(HEtelBufC8))
- );
- }
-
-void HEtelBufC8::operator delete(TAny* aPtr)
-//
-// overloaded delete - deletes from priority client heap if iHeap is not NULL
-//
- {
- RHeap* heap=NULL;
- if (aPtr!=NULL)
- {
- heap = (reinterpret_cast<HEtelBufC8*> (aPtr))->iHeap;
- }
-
- if (heap!=NULL)
- {
- reinterpret_cast<HEtelBufC8*> (aPtr)->iHeap->Free(aPtr);
- }
- else
- {
- User::Free(aPtr);
- }
- }
-
-//
-// HEtelBufC16
-//
-HEtelBufC16* HEtelBufC16::NewMaxLC(TInt aMaxLength,RHeap* aHeap)
- {
- __ASSERT_ALWAYS(aMaxLength>=0,Fault(EEtelFaultMaxDesLengthNegative));
-
- HEtelBufC16* pH=NULL;
- TInt size=sizeof(HEtelBufC16)+(aMaxLength*sizeof(TUint16));
- if (aHeap!=NULL)
- pH=(HEtelBufC16*)aHeap->AllocLC(size);
- else
- pH=(HEtelBufC16*)User::AllocLC(size);
- pH->iLength=aMaxLength;
- pH->iHeap=aHeap;
- pH->Des().SetLength(aMaxLength);
- return(pH);
- }
-
-TPtr16 HEtelBufC16::Des()
- {
- TUint16* ptr=reinterpret_cast<TUint16*> ((reinterpret_cast<TInt> (this)+sizeof(HEtelBufC16)));
- return TPtr16(ptr,iLength,iLength);
- }
-
-const TUint16* HEtelBufC16::Ptr() const
- {
- return reinterpret_cast<const TUint16*> ((reinterpret_cast<TInt> (this)+sizeof(HEtelBufC16)));
- }
-
-void HEtelBufC16::operator delete(TAny* aPtr)
-//
-// overloaded delete - deletes from priority client heap if iHeap is not NULL
-//
- {
- RHeap* heap=NULL;
- if (aPtr!=NULL)
- heap=reinterpret_cast<HEtelBufC16*> (aPtr)->iHeap;
-
- if (heap!=NULL)
- reinterpret_cast<HEtelBufC16*> (aPtr)->iHeap->Free(aPtr);
- else
- User::Free(aPtr);
- }
-
-//
-// TDataPackage class contains the data pointers to be passed down to the TSY in ExtFunc()
-//
-TDataPackage::TDataPackage()
- : iDes1(NULL),iDes2(NULL),iDes1u(NULL),iDes2u(NULL)
- {}
-TDataPackage::TDataPackage(TDes8* aDes1, TDes8* aDes2)
- : iDes1(aDes1),iDes2(aDes2),iDes1u(NULL),iDes2u(NULL)
- {}
-
-TDataPackage::TDataPackage(TDes16* aDes1, TDes16* aDes2)
- : iDes1(NULL),iDes2(NULL),iDes1u(aDes1),iDes2u(aDes2)
- {}
-TDataPackage::TDataPackage(TDes8* aDes1, TDes16* aDes2)
- : iDes1(aDes1),iDes2(NULL),iDes1u(NULL),iDes2u(aDes2)
- {}
-
-EXPORT_C TDes8* TDataPackage::Des1n() const
- {
- __ASSERT_ALWAYS(iDes1,Fault(EEtelFaultDes1DoesNotExist));
- return iDes1;
- }
-EXPORT_C TDes8* TDataPackage::Des2n() const
- {
- __ASSERT_ALWAYS(iDes2,Fault(EEtelFaultDes2DoesNotExist));
- return iDes2;
- }
-EXPORT_C TDes16* TDataPackage::Des1u() const
- {
- __ASSERT_ALWAYS(iDes1u,Fault(EEtelFaultDes1DoesNotExist));
- return iDes1u;
- }
-EXPORT_C TDes16* TDataPackage::Des2u() const
- {
- __ASSERT_ALWAYS(iDes2u,Fault(EEtelFaultDes2DoesNotExist));
- return iDes2u;
- }
-
-EXPORT_C TAny* TDataPackage::Ptr1() const
- {
- if (iDes1u)
- return reinterpret_cast<TAny*> (const_cast<TUint16*> (iDes1u->Ptr()));
- if (iDes1)
- return reinterpret_cast<TAny*> (const_cast<TUint8*> (iDes1->Ptr()));
- return NULL;
- }
-
-EXPORT_C TAny* TDataPackage::Ptr2() const
- {
- if (iDes2u)
- return reinterpret_cast<TAny*> (const_cast<TUint16*> (iDes2u->Ptr()));
- if (iDes2)
- return reinterpret_cast<TAny*> (const_cast<TUint8*> (iDes2->Ptr()));
- return NULL;
- }
-
-/**
-* This helper utility returns the type of a packaged data structure.
-* It is very useful to know which type of variables (unicode or narrow) a package contains
-* before passing it to any functions. It could also help to provide more generic implementation
-* on the TSY, that currently assumes knowledge of the way the data are packaged.
-*
-*/
-
-EXPORT_C TDataPackage::TDataPackageType TDataPackage::Type() const
- {
- if(iDes1 && iDes2)
- return EPackage1n2n;
- else if (iDes1u && iDes2u)
- return EPackage1u2u;
- else if (iDes1 && iDes2u)
- return EPackage1n2u;
- else if (iDes1 && !iDes2)
- return EPackage1n;
- else if (iDes1u && !iDes2u)
- return EPackage1u;
- else
- return EPackageUnknown;
- }
-
-/**
-Non-exported static factory constructor. This class should only be instantiated by Etel server.
-*/
-CFaxSharedFileHandles* CFaxSharedFileHandles::NewL(const RMessage2& aMsg)
- {
- CFaxSharedFileHandles* obj = new(ELeave) CFaxSharedFileHandles();
- CleanupStack::PushL(obj);
- obj->ConstructL(aMsg);
- CleanupStack::Pop(obj);
- return obj;
- }
-
-/**
-Destructor.
-
-@publishedPartner
-@released
-*/
-EXPORT_C CFaxSharedFileHandles::~CFaxSharedFileHandles()
- {
- iFile.Close();
- }
-
-/**
-Default constructor.
-*/
-CFaxSharedFileHandles::CFaxSharedFileHandles()
- {
- //empty
- }
-
-/**
-Reference to an adopted file.
-
-@return RFile& Reference to an open file handle.
-@publishedPartner
-@released
-*/
-EXPORT_C RFile& CFaxSharedFileHandles::File()
- {
- return iFile;
- };
-
-/**
-Adopt the file during construction.
-*/
-void CFaxSharedFileHandles::ConstructL(const RMessage2& aMsg)
- {
- //Use the RMessage2 and EKA2 adopt functions to adopt the file. Slots 0 & 2 contain relevant session handles.
- User::LeaveIfError(iFile.AdoptFromClient(aMsg, 0, 2));
- }
+// Copyright (c) 1997-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:
+//
+
+/**
+ @file
+*/
+
+#include "ET_SSTD.H"
+#include "et_record.h"
+#include "et_phone_util.h"
+#include "et_patchdata.h"
+//
+// CReqEntry class definitions
+//
+
+CReqEntry* CReqEntry::NewL(TTsyReqHandle aTsyReqHandle, const RMessage2& aMessage, CTelSession* aSession, CBuffer* aBuffer, const CTelObject* aTelObject, TInt aFunction, RHeap* aHeap)
+//
+// Create new request entry. aHeap should be NULL unless this is to be allocated on the
+// priority client heap.
+//
+ {
+ if (aHeap != NULL)
+ {
+ return new(aHeap) CReqEntry(aTsyReqHandle,aMessage,aSession,aBuffer,aTelObject,aFunction,aHeap);
+ }
+
+ return new(ELeave) CReqEntry(aTsyReqHandle,aMessage,aSession,aBuffer,aTelObject,aFunction,NULL);
+ }
+
+
+CReqEntry::CReqEntry(TTsyReqHandle aTsyReqHandle,const RMessage2& aMessage,CTelSession* aSession,CBuffer* aBuffer,const CTelObject* aTelObject,TInt aFunction,RHeap* aHeap)
+//
+// CReqEntry constructor
+//
+ : iTsyReqHandle(aTsyReqHandle), iMessage(aMessage), iSession(aSession), iTelObject(aTelObject),
+ iClientInterested(ETrue), iCancelFnCalled(EFalse), iFunction(aFunction), iBuffer(aBuffer),
+ iReadByClient(ETrue), iMessageNulled(EFalse), iHeap(aHeap)
+ {}
+
+CReqEntry::~CReqEntry()
+//
+// CReqEntry destructor
+//
+ {
+ delete iBuffer;
+ }
+
+void CReqEntry::Deque()
+//
+// Deque CReqEntry list
+//
+ {
+ iLink.Deque();
+ iLink.iPrev=iLink.iNext=NULL;
+ }
+
+void CReqEntry::CompleteAndDeque(TInt aError)
+ {
+ LOGTEXT("CReqEntry::CompleteAndDeque");
+ // if client does not interested in this request do not completed
+ if (iClientInterested)
+ {
+ RECORD_COMPLETE_SUB(iMessage.Session(), iTelObject, iMessage.Int3(), iMessage.Function(), aError);
+ iMessage.Complete(aError);
+ }
+
+ iLink.Deque();
+ }
+
+TAny* CReqEntry::operator new(TUint aSize,RHeap* aHeap) __NO_THROW
+//
+// overloaded new using the priority client heap - can leave
+//
+ {
+ TAny *pM=NULL;
+ TRAPD(err, pM=aHeap->AllocL(aSize) );
+
+ if(err!=KErrNone)
+ pM = NULL;
+ else
+ Mem::FillZ(pM,aSize);
+ return(pM);
+ }
+
+TAny* CReqEntry::operator new(TUint aSize) __NO_THROW
+ {
+ return CBase::operator new(aSize);
+ }
+
+TAny* CReqEntry::operator new(TUint aSize,TLeave aLeave)
+ {
+ return CBase::operator new(aSize,aLeave);
+ }
+
+TAny* CReqEntry::operator new(TUint aSize,TUint aExtraSize) __NO_THROW
+ {
+ return CBase::operator new(aSize,aExtraSize);
+ }
+
+void CReqEntry::operator delete(TAny* aPtr)
+//
+// overloaded delete - deletes from priority client heap if iHeap is not NULL
+//
+ {
+ if (((CReqEntry*)aPtr)->iHeap!=NULL)
+ ((CReqEntry*)aPtr)->iHeap->Free(aPtr);
+ else
+ User::Free(aPtr);
+ }
+
+//
+// CBuffer class definitions
+//
+CBuffer* CBuffer::NewL(HEtelBufC8* aBuf8,HEtelBufC16* aBuf16,RHeap* aHeap,TInt aSizeOfData1,TInt aSizeOfData2,TInt aNoOfSlots)
+ {
+ if (aHeap!=NULL)
+ return new(aHeap) CBuffer(aBuf8,aBuf16,aHeap,aSizeOfData1,aSizeOfData2,aNoOfSlots);
+
+ return new(ELeave) CBuffer(aBuf8,aBuf16,NULL,aSizeOfData1,aSizeOfData2,aNoOfSlots);
+ }
+
+CBuffer::CBuffer(HEtelBufC8* aBuf8,HEtelBufC16* aBuf16,RHeap* aHeap,TInt aSizeOfData1,TInt aSizeOfData2,TInt aNoOfSlots)
+ : iBuf8(aBuf8),iBuf16(aBuf16),iHeap(aHeap),iRead(0),iWrite(0),iNoOfSlots(aNoOfSlots),
+ iSizeOfData1(aSizeOfData1),iSizeOfData2(aSizeOfData2),
+ iOverFlow(EFalse),iBufferFull(EFalse)
+ {}
+
+CBuffer::~CBuffer()
+ {
+ delete iBuf8;
+ delete iBuf16;
+ }
+
+TAny* CBuffer::operator new(TUint aSize,RHeap* aHeap) __NO_THROW
+//
+// overloaded new using the priority client heap - can leave
+//
+ {
+ TAny *pM=NULL;
+ TRAPD(err, pM=aHeap->AllocL(aSize) );
+
+ if(err!=KErrNone)
+ pM = NULL;
+ else
+ Mem::FillZ(pM,aSize);
+ return(pM);
+ }
+
+TAny* CBuffer::operator new(TUint aSize) __NO_THROW
+ {
+ return CBase::operator new(aSize);
+ }
+
+TAny* CBuffer::operator new(TUint aSize,TLeave aLeave)
+ {
+ return CBase::operator new(aSize,aLeave);
+ }
+
+TAny* CBuffer::operator new(TUint aSize,TUint aExtraSize) __NO_THROW
+ {
+ return CBase::operator new(aSize,aExtraSize);
+ }
+
+void CBuffer::operator delete(TAny* aPtr)
+//
+// overloaded delete - deletes from priority client heap if iHeap not NULL
+//
+ {
+ if (((CBuffer*)aPtr)->iHeap!=NULL)
+ ((CBuffer*)aPtr)->iHeap->Free(aPtr);
+ else
+ User::Free(aPtr);
+ }
+
+TUint CBuffer::Size() const
+ {
+ return iSizeOfData1 + iSizeOfData2;
+ }
+
+void CBuffer::IncRead()
+ {
+ if(++iRead==iNoOfSlots)
+ iRead=0;
+ iOverFlow=EFalse;
+ iBufferFull=EFalse;
+ LOGTEXT2("ETel:\tiRead incremented to %d", iRead);
+ }
+
+void CBuffer::IncWrite()
+ {
+ if(++iWrite==iNoOfSlots)
+ iWrite=0;
+ if (iOverFlow)
+ iRead=iWrite;
+ else
+ {
+ if (!iBufferFull)
+ {
+ if (iWrite==iRead)
+ iBufferFull=ETrue;
+ }
+ else
+ {
+ iRead=iWrite;
+ iOverFlow=ETrue;
+ }
+ }
+ LOGTEXT2("ETel:\tiWrite incremented to %d", iWrite);
+ }
+
+TUint8* CBuffer::CurrentSlotData1(TWhichSlot aWhichSlot) const
+//
+// iSizeOfData1 and iSizeOfData2 include the sizes of the TPtr's
+//
+ {
+ TInt pos=((aWhichSlot==ESlotRead) ? iRead : iWrite);
+
+ if (iBuf8==NULL)
+ {
+ return NULL;
+ }
+ else if (iBuf16==NULL)
+ {
+ TInt slotSize = iSizeOfData1 + iSizeOfData2;
+ return (const_cast<TUint8*> (iBuf8->Des().Mid(pos*(slotSize),iSizeOfData1-sizeof(TPtr8)).Ptr()));
+ }
+ else
+ {
+ // we have a narrow and a unicode parameter. Data1 is always narrow
+ return (const_cast<TUint8*> (iBuf8->Des().Mid(pos*iSizeOfData1,iSizeOfData1-sizeof(TPtr8)).Ptr()));
+ }
+ }
+
+TUint8* CBuffer::CurrentSlotData2(TWhichSlot aWhichSlot) const
+ {
+ if (iSizeOfData2==0)
+ return NULL;
+ TInt pos=((aWhichSlot==ESlotRead) ? iRead : iWrite);
+
+ if (iBuf8!=NULL && iBuf16==NULL)
+ {
+ TInt slotSize = iSizeOfData1 + iSizeOfData2;
+ return (const_cast<TUint8*> (iBuf8->Des().Mid(pos*(slotSize)+iSizeOfData1,iSizeOfData2-sizeof(TPtr8)).Ptr()));
+ }
+
+ return NULL;
+ }
+
+TUint16* CBuffer::CurrentSlotData1u(TWhichSlot aWhichSlot) const
+//
+// Unicode version
+//
+ {
+ TInt pos=((aWhichSlot==ESlotRead) ? iRead : iWrite);
+
+ if (iBuf8==NULL && iBuf16!=NULL)
+ {
+ TInt slotSize = iSizeOfData1 + iSizeOfData2;
+ return (const_cast<TUint16*> (iBuf16->Des().Mid(pos*(slotSize),iSizeOfData1-sizeof(TPtr16)).Ptr()));
+ }
+
+ return NULL; // Data1 will be narrow if we have a mixture of both 8 and 16 bit
+ }
+
+TUint16* CBuffer::CurrentSlotData2u(TWhichSlot aWhichSlot) const
+//
+// Unicode version
+//
+ {
+ if (iSizeOfData2==0)
+ return NULL;
+ TInt pos=((aWhichSlot==ESlotRead) ? iRead : iWrite);
+
+ if (iBuf16==NULL)
+ {
+ return NULL;
+ }
+ else if (iBuf8==NULL)
+ {
+ TInt slotSize = iSizeOfData1 + iSizeOfData2;
+ return (const_cast<TUint16*> (iBuf16->Des().Mid(pos*(slotSize)+iSizeOfData1,iSizeOfData2-sizeof(TPtr16)).Ptr()));
+ }
+ else
+ {
+ // we have a narrow and a unicode parameter. Data2 is always unicode
+ return (const_cast<TUint16*> (iBuf16->Des().Mid(pos*iSizeOfData2,iSizeOfData2-sizeof(TPtr16)).Ptr()));
+ }
+ }
+
+TBool CBuffer::EqualSizes(TInt aSize1, TInt aSize2) const
+ {
+ if(iSizeOfData1 != aSize1)
+ {
+ return EFalse;
+ }
+ if(iSizeOfData2 != aSize2)
+ {
+ return EFalse;
+ }
+ return ETrue;
+ }
+
+TInt CBuffer::CompareRWPtrs() const
+ {
+ return (iRead-iWrite);
+ }
+
+//
+//
+// CTelObject class definitions
+//
+
+EXPORT_C CTelObject::CTelObject()
+//
+// CTelObject constructor
+//
+ :iActiveReqCount(0), iTelServer(NULL), iDestroyDummySubSession(NULL), iCreateDummy(EFalse)
+ {
+ __DECLARE_NAME(_S("CTelObject"));
+ }
+
+EXPORT_C CTelObject::~CTelObject()
+//
+// Destructor
+//
+ {
+ delete iDeliveryObject;
+ delete iDestroyDummySubSession;
+ }
+
+EXPORT_C void CTelObject::CTelObject_Reserved1()
+//
+// Reserved virtual function
+//
+ {}
+
+void CTelObject::CreateDummySessionObjectL(CTelSession* aTelSession)
+ {
+ if (iDestroyDummySubSession==NULL)
+ {
+ LOGTEXT("CDestroyDummySubSession object does not already exist and will be created.");
+ iDestroyDummySubSession = CDestroyDummySubSession::NewL(aTelSession->TelServer(),this);
+ }
+ else
+ {
+ LOGTEXT("CDestroyDummySubSession object already exists and will not be created");
+ }
+
+ }
+
+void CTelObject::CreateDummySession(CTelSession* aSession, const TInt aSubSessionHandle, TBool aCreateDummy)
+//
+// So the server has to create a dummy session just to keep session alive until completed
+// function is called.
+//
+ {
+ LOGTEXT2("CreateDummySession() with iDestroyDummySubSession = %x", iDestroyDummySubSession);
+ iCreateDummy=aCreateDummy;
+
+ if (iDestroyDummySubSession->iOpen == EFalse)
+ {
+ if ( IsActiveReq(aSession,aSubSessionHandle) || aCreateDummy)
+ {
+ LOGTEXT("About to create dummy session");
+ __ASSERT_ALWAYS(aSession!=NULL,Fault(EEtelFaultBadTelSessionPointer));
+ CObject* theObj=this;
+ while(theObj->Owner())
+ {
+ theObj->Open();
+ theObj=theObj->Owner();
+ }
+ theObj->Open();
+ iTelServer=aSession->TelServer();
+
+ // incrementing the server's session count to include the dummy session, which
+ // has been previously allocated upon the CTelObject creation (by calling
+ // CreateDummySessionObjectL() )
+ iTelServer->Inc();
+ LOGTEXT2("Added a Dummy Session, producing server's session count of %d", iTelServer->Count());
+
+ iDestroyDummySubSession->iTelServer = iTelServer;
+ iDestroyDummySubSession->iTelObject = this;
+ iDestroyDummySubSession->iOpen = ETrue;
+ }
+ }
+ }
+
+void CTelObject::TelObjectClose()
+//
+// Perform an iterative close of Tel Objects
+//
+ {
+ CTelObject* owner = reinterpret_cast<CTelObject*> (Owner());
+ Close();
+ if(owner)
+ owner->TelObjectClose();
+ }
+
+void CTelObject::CompleteAndDestroyReq(CReqEntry* aReqEntry,const TInt aStatus) const
+//
+// complete the entry and remove from entry list and associate heap
+//
+ {
+ if (!aReqEntry->iMessageNulled)
+ {
+ RECORD_COMPLETE_SUB(aReqEntry->iMessage.Session(), this, aReqEntry->iMessage.Int3(), aReqEntry->iMessage.Function(), aStatus);
+ aReqEntry->iMessage.Complete(aStatus);
+ }
+ DestroyReq(aReqEntry);
+ }
+
+void CTelObject::DestroyReq(CReqEntry* aReqEntry) const
+//
+// remove from entry list and associate heap
+//
+ {
+ aReqEntry->Deque();
+ delete aReqEntry;
+ }
+
+TBool CTelObject::IsActiveReq(CTelSession* aSession,const TInt aSubSessionHandle)
+//
+// Return True if found the active req still out standing
+// going through and counting the total of active req
+//
+ {
+ TBool ret=EFalse;
+ CReqEntry* reqEntry=NULL;
+ TDblQueIter<CReqEntry> iter(PhoneOwner()->ReqActiveList());
+ while(reqEntry=iter++,reqEntry!=NULL) // go through the list from begin to end
+ {
+ if (aSession==reqEntry->iSession && aSubSessionHandle==reqEntry->iMessage.Int3() && reqEntry->iClientInterested )
+ {
+ iActiveReqCount++;
+ ret=ETrue;
+ }
+ }
+ LOGTEXT2("IsActiveReq found %d active reqs", iActiveReqCount);
+ return ret;
+ }
+
+void CTelObject::CancelActiveReq(CTelSession* aSession,const TInt aSubSessionHandle)
+//
+// active list - must inform tsy by calling CancelService
+// this request will be destroyed when Tsy do an up call ReqCompleted with KErrCancel
+// Only go through the list once set the count to zero at start to count number of requests
+//
+ {
+ LOGTEXT("Entered CancelActiveReq");
+ CReqEntry* reqEntry=NULL;
+ TDblQueIter<CReqEntry> iter(PhoneOwner()->ReqActiveList());
+ while(reqEntry=iter++,reqEntry!=NULL) // go through the list from begin to end
+ {
+ if (aSession==reqEntry->iSession && aSubSessionHandle==reqEntry->iMessage.Int3() && reqEntry->iClientInterested )
+ {
+ reqEntry->iClientInterested=EFalse;
+ __ASSERT_ALWAYS(iActiveReqCount>=0,Fault(EEtelFaultNegativeActiveReqCount));
+ if (reqEntry->iCancelFnCalled==FALSE)
+ {
+ TReqMode reqMode = reqEntry->iReqMode;
+
+ if (reqEntry->iPlacedRequest)
+ {
+ LOGTEXT2("Calling Cancel Service ActiveReq TsyReq=%d", reqEntry->iTsyReqHandle);
+ reqEntry->iCancelFnCalled=ETrue;
+ CancelService(reqEntry->iFunction,reqEntry->iTsyReqHandle);
+
+ //
+ // In calling CancelService() it is possible that a second
+ // handle has performed the same request (e.g. a notify) and
+ // that ETel will re-post the notify using that handle. In
+ // some cases it could happen that the re-posted notify is
+ // invalid and fails, thereby completing that next request.
+ // Finally, if that request is the next one after this one,
+ // then the iterator is going to be invalid. So reset it now
+ // and start at the beginning of the list!
+ //
+ if (PhoneOwner()->ReqActiveList().IsEmpty() == EFalse)
+ {
+ iter.Set(*PhoneOwner()->ReqActiveList().First());
+ }
+ else
+ {
+ break;
+ }
+ }
+ else
+ {
+ if (reqMode&KReqModeMultipleCompletionWithInterestLevel && iDeliveryObject)
+ {
+ iDeliveryObject->DeletedReqEntry(reqEntry);
+ }
+
+ LOGTEXT("Destroying request");
+ DestroyReq(reqEntry);
+ CheckAndDestroyDummySubSession();
+ }
+ }
+ }
+ }
+ }
+
+void CTelObject::CancelSubSession(CTelSession* aSession,const TInt aSubSessionHandle)
+//
+// Flush outstanding requests from the queue for this client only
+// Cancel the service if request already passed to Tsy
+//
+ {
+ CReqEntry* reqEntry=NULL;
+ while (reqEntry=PhoneOwner()->FindClientReqInWaitList(aSession,aSubSessionHandle),reqEntry)
+ CompleteAndDestroyReq(reqEntry,KErrCancel);
+
+ CancelActiveReq(aSession,aSubSessionHandle);
+ }
+
+void CTelObject::FlushReqs(CTelSession* aSession,const TInt aSubSessionHandle)
+//
+// Flush outstanding requests from the queue for this client only
+// Cancel the service if request already passed to Tsy
+// Return ETrue if it have to create a dummy session
+//
+ {
+ CReqEntry* reqEntry=NULL;
+ // wait list
+ while (reqEntry=PhoneOwner()->FindClientReqInWaitList(aSession,aSubSessionHandle),reqEntry)
+ DestroyReq(reqEntry);
+
+ CancelActiveReq(aSession,aSubSessionHandle);
+
+ }
+
+CPhoneBase* CTelObject::PhoneOwner() const
+//
+// Get the owner handle
+//
+ {
+ return iPhoneOwner;
+ }
+
+void CTelObject::SetPhoneOwner(CPhoneBase* aPhoneOwner)
+//
+// Set the owner of phone
+//
+ {
+ iPhoneOwner=aPhoneOwner;
+ }
+
+void CTelObject::GetMessageDescriptorSizes(const RMessage2& aMessage,TInt &aSize1, TInt &aSize2) const
+ {
+ TInt messageType=aMessage.Int1();
+ aSize1=0;
+ aSize2=0;
+
+ if (messageType!=EIsaNull &&
+ messageType!=EIsaCancelMessage &&
+ messageType!=EIsPriorityClientReqWithNull)
+ { // we're going to create server-side buffer
+ TInt basicMsgType = messageType&(~(KUnicodeReq|KPriorityClientReq));
+
+ if (messageType==EIsaNarrowAndUnicodeDoubleDesTobeSet)
+ basicMsgType=EIsaDoubleDesTobeSet;
+ if (messageType==EIsaNarrowAndUnicodeDoubleDesTobeRead)
+ basicMsgType=EIsaDoubleDesTobeRead;
+
+ switch (basicMsgType)
+ {
+ case EIsaDoubleDesTobeSet:// if we're setting data, get length
+ aSize2=aMessage.GetDesLength(2); // no break
+ case EIsaDesTobeSet:
+ aSize1=aMessage.GetDesLength(0);
+ break;
+ case EIsaDoubleDesTobeRead:// if we're reading data, get max length
+ aSize2=aMessage.GetDesMaxLength(2); // no break
+ case EIsaDesTobeRead:
+ aSize1=aMessage.GetDesMaxLength(0);
+ break;
+ case EIsaNarrowDesToSetAndGet:
+ aSize1=aMessage.GetDesLength(0); // set data
+ aSize2=aMessage.GetDesMaxLength(2); // get data
+ break;
+ case EIsaNarrowDesToGetUnicodeDesToSet:
+ aSize1=aMessage.GetDesMaxLength(0); // get data
+ aSize2=aMessage.GetDesLength(2); // set data
+ break;
+ case EIsaUnicodeDesToSetAndGet:
+ aSize1=aMessage.GetDesLength(0); // set data
+ aSize2=aMessage.GetDesMaxLength(2); // get data
+ break;
+ case EIsaUnicodeDesToGetNarrowDesToSet:
+ aSize1=aMessage.GetDesLength(0); // set data
+ aSize2=aMessage.GetDesMaxLength(2); // get data
+ break;
+ default:
+ PanicClient(EEtelPanicInvalidRequestType,aMessage);
+ break;
+ }
+ }
+ }
+
+TBool CTelObject::IsSameMessageType(const RMessage2& aMessage,CReqEntry* aReqEntry) const
+ {
+ TInt size1;
+ TInt size2;
+ TInt ptrSize=sizeof(TPtr8);
+ GetMessageDescriptorSizes(aMessage, size1, size2);
+
+ if(size1)
+ {
+ CheckAndResize(size1,aMessage);
+ size1+=ptrSize;
+ }
+ if (size2)
+ {
+ CheckAndResize(size2,aMessage);
+ size2+=ptrSize;
+ }
+ if(aReqEntry->iBuffer->EqualSizes(size1,size2))
+ {
+ return ETrue;
+ }
+ return EFalse;
+ }
+
+void CTelObject::CompleteOrBufferRead(const RMessage2& aMessage, CReqEntry* aReqEntry)
+//
+// Check and complete if possible this notification/multislot command from
+// this subsession in the ReqActive list
+// aMessage is the message just received from the client
+// aReqEntry is the Entry previously created when the same client called the same function
+//
+ {
+ if(aReqEntry->iMessageNulled==FALSE) // same client already posted this notification
+ {
+ PanicClient(EEtelPanicRequestAsyncTwice,aMessage);
+ return;
+ }
+ TInt slots=0;
+ TRAP_IGNORE(slots = NumberOfSlotsL(aReqEntry->iFunction));
+ TBool sameMessageType = IsSameMessageType(aMessage, aReqEntry);
+
+ if (slots>1)
+ {
+ TInt comparison = aReqEntry->iBuffer->CompareRWPtrs();
+ if (comparison==0 && aReqEntry->iBuffer->BufferFull()==FALSE)
+ { // if the client has already read value,the automatic server-TSY
+ // notify request becomes the "true" request
+ if(sameMessageType)
+ {
+ aReqEntry->iMessage=aMessage;
+ aReqEntry->iMessageNulled=EFalse;
+ }
+ else
+ {
+ // cancel in ctsy
+ aReqEntry->iCancelFnCalled = ETrue;
+ CancelService(aReqEntry->iFunction, aReqEntry->iTsyReqHandle);
+ aReqEntry->iCancelFnCalled = EFalse;
+ GeneralReq(aMessage,aReqEntry->iSession,NULL);
+ }
+ }
+ else
+ {
+ if (aReqEntry->iBuffer->OverFlow())
+ WriteBackAndCompleteBufferedReq(aMessage,aReqEntry,KErrOverflow);
+ else
+ {
+ if(sameMessageType)
+ {
+ WriteBackAndCompleteBufferedReq(aMessage,aReqEntry,KErrNone);
+ }
+ else
+ {
+ WriteBackAndCompleteBufferedReq(aMessage,aReqEntry,KErrOverflow);
+ }
+ }
+ }
+ }
+ else // this is a non-registered notification (ie single-slot)
+ {
+ if(aReqEntry->iReadByClient)
+ {
+ if(sameMessageType)
+ {
+ aReqEntry->iMessage=aMessage;
+ aReqEntry->iMessageNulled=EFalse;
+ }
+ else
+ {
+ CancelService(aReqEntry->iFunction, aReqEntry->iTsyReqHandle);
+ GeneralReq(aMessage,aReqEntry->iSession,NULL);
+ }
+ }
+ else // Client has not read this new value yet
+ {
+ if(sameMessageType)
+ {
+ WriteBackAndCompleteBufferedReq(aMessage,aReqEntry,KErrNone);
+ }
+ else
+ {
+ WriteBackAndCompleteBufferedReq(aMessage,aReqEntry,KErrOverflow);
+ }
+ }
+ }
+ }
+
+void CTelObject::CheckAndResize(TInt& aSizeOfData,const RMessage2& aMessage) const
+//
+// Checks that size of data is non-zero - if not, panic client.
+// Also checks that size of data is word-aligned, ie a multiple of 4 bytes.
+// If not, ensure that in the space in buffer for data is word-aligned.
+//
+ {
+ if(aSizeOfData<0)
+ PanicClient(EEtelPanicDesLengthNegative,aMessage);
+ aSizeOfData=(aSizeOfData+3)&~3;
+ }
+
+HEtelBufC8* CTelObject::CreateNarrowBufferLC(RHeap* aHeap,const RMessage2& aMessage,TUint aIndexOfClientPtr1,TUint aIndexOfClientPtr2,TInt& aSize1,TInt& aSize2,TInt aNoOfSlots) const
+//
+// aSize1 = size of 1st descriptor buffer
+// aSize2 = size of 2nd descriptor buffer (default=0)
+// aHeap may be NULL if the priority heap is not to be used
+// aNoOfSlots will usually be 1. Only if this request is a notification that requires
+// registering, ie increasing the number of events the server will buffer, will it be greater than 1
+//
+ {
+ TInt desSize1=aSize1;
+ TInt desSize2=aSize2;
+ CheckAndResize(aSize1,aMessage);
+
+ TInt ptrSize=sizeof(TPtr8);
+ TInt allocSize=aSize1+ptrSize;
+ if (aSize2)
+ {
+ CheckAndResize(aSize2,aMessage);
+ allocSize += aSize2+ptrSize;
+ }
+ HEtelBufC8* buf = HEtelBufC8::NewMaxLC(allocSize*aNoOfSlots,aHeap); // allocate a buffer for the Des and Data
+
+ TPtr8 firstptrDes1(const_cast<TUint8*> (buf->Des().Left(ptrSize).Ptr()),ptrSize,ptrSize); // carve the thing up
+ TPtr8 firstdataDes1(const_cast<TUint8*> (buf->Des().Mid(ptrSize,aSize1).Ptr()),desSize1,desSize1);
+ TPtr8 firstdataDes2(NULL,0,0);
+ aMessage.ReadL(aIndexOfClientPtr1,firstdataDes1);// Read the Data. If it leaves, buf will be cleaned up
+ firstptrDes1.Copy(reinterpret_cast<TUint8*> (&firstdataDes1),ptrSize); // Copy the new Des
+ if (aSize2)
+ // Construct Second descriptor
+ {
+ TPtr8 firstptrDes2(const_cast<TUint8*> (buf->Des().Mid(ptrSize+aSize1,ptrSize).Ptr()),ptrSize,ptrSize);
+ firstdataDes2.Set(const_cast<TUint8*> (buf->Des().Mid((ptrSize*2)+aSize1,aSize2).Ptr()),desSize2,desSize2);
+ aMessage.ReadL(aIndexOfClientPtr2,firstdataDes2);
+ firstptrDes2.Copy(reinterpret_cast<TUint8*> (&firstdataDes2),ptrSize);
+ }
+ for (TInt i=1; i<aNoOfSlots;i++)
+ {// Copy descriptors into each slot
+ TPtr8 ptrDes1(const_cast<TUint8*> (buf->Des().Mid(i*allocSize,ptrSize).Ptr()),ptrSize,ptrSize);
+ TPtr8 dataDes1(const_cast<TUint8*> (buf->Des().Mid(i*allocSize+ptrSize,aSize1).Ptr()),desSize1,desSize1);
+ dataDes1.Copy(firstdataDes1);
+ ptrDes1.Copy(reinterpret_cast<TUint8*> (&dataDes1),ptrSize);
+ if (aSize2)
+ {
+ TPtr8 ptrDes2(const_cast<TUint8*> (buf->Des().Mid(i*allocSize+ptrSize+aSize1,ptrSize).Ptr()),ptrSize,ptrSize);
+ TPtr8 dataDes2(const_cast<TUint8*> (buf->Des().Mid(i*allocSize+(ptrSize*2)+aSize1).Ptr()),desSize2,desSize2);
+ dataDes2.Copy(firstdataDes2);
+ ptrDes2.Copy(reinterpret_cast<TUint8*> (&dataDes2),ptrSize);
+ }
+ }
+ return buf;
+ }
+
+HEtelBufC16* CTelObject::CreateUnicodeBufferLC(RHeap* aHeap,const RMessage2& aMessage,TUint aIndexOfClientPtr1,TUint aIndexOfClientPtr2,TInt& aSize1,TInt& aSize2,TInt aNoOfSlots) const
+//
+// We place both parameters in the same buffer which is either narrow or unicode (unicode in this case)
+// Should a function ever require one parameter to be narrow and the other unicode,
+// will need to review.
+//
+ {
+ TInt desSize1=aSize1;
+ TInt desSize2=aSize2;
+ CheckAndResize(aSize1,aMessage);
+ TInt ptrSize=sizeof(TPtr16);
+ TInt allocSize=aSize1+ptrSize;
+ if (aSize2)
+ {
+ CheckAndResize(aSize2,aMessage);
+ allocSize += aSize2+ptrSize;
+ }
+ HEtelBufC16* buf = HEtelBufC16::NewMaxLC(allocSize*aNoOfSlots,aHeap); // allocate a buffer for the Des and Data
+
+ TPtr16 firstptrDes1(const_cast<TUint16*> (buf->Des().Left(ptrSize).Ptr()),ptrSize,ptrSize); // carve the thing up
+ TPtr16 firstdataDes1(const_cast<TUint16*> (buf->Des().Mid(ptrSize,aSize1).Ptr()),desSize1,desSize1);
+ TPtr16 firstdataDes2(NULL,0,0);
+ aMessage.ReadL(aIndexOfClientPtr1,firstdataDes1);// Read the Data. If it leaves, buf will be cleaned up
+ firstptrDes1.Copy(reinterpret_cast<TUint16*> (&firstdataDes1),ptrSize); // Copy the new Des
+ if (aSize2)
+ // Construct Second descriptor
+ {
+ TPtr16 firstptrDes2(const_cast<TUint16*> (buf->Des().Mid(ptrSize+aSize1,ptrSize).Ptr()),ptrSize,ptrSize);
+ firstdataDes2.Set(const_cast<TUint16*> (buf->Des().Mid((ptrSize*2)+aSize1,aSize2).Ptr()),desSize2,desSize2);
+ aMessage.ReadL(aIndexOfClientPtr2,firstdataDes2);
+ firstptrDes2.Copy(reinterpret_cast<TUint16*> (&firstdataDes2),ptrSize);
+ }
+ for (TInt i=1; i<aNoOfSlots;i++)
+ {// Copy descriptors into each slot
+ TPtr16 ptrDes1(const_cast<TUint16*> (buf->Des().Mid(i*allocSize,ptrSize).Ptr()),ptrSize,ptrSize);
+ TPtr16 dataDes1(const_cast<TUint16*> (buf->Des().Mid(i*allocSize+ptrSize,aSize1).Ptr()),desSize1,desSize1);
+ dataDes1.Copy(firstdataDes1);
+ ptrDes1.Copy(reinterpret_cast<TUint16*> (&dataDes1),ptrSize);
+ if (aSize2)
+ {
+ TPtr16 ptrDes2(const_cast<TUint16*> (buf->Des().Mid(i*allocSize+ptrSize+aSize1,ptrSize).Ptr()),ptrSize,ptrSize);
+ TPtr16 dataDes2(const_cast<TUint16*> (buf->Des().Mid(i*allocSize+(ptrSize*2)+aSize1).Ptr()),desSize2,desSize2);
+ dataDes2.Copy(firstdataDes2);
+ ptrDes2.Copy(reinterpret_cast<TUint16*> (&dataDes2),ptrSize);
+ }
+ }
+ return buf;
+ }
+
+CReqEntry* CTelObject::ReqAnalyserL(const RMessage2& aMessage,CTelSession* aSession,TReqMode& aReqMode)
+//
+// Analyse the request. First search for an entry from the same client for the same request,
+// and if found either panic if this is a non-buffered request(ie the request is already
+// pending) or look at the buffer to see if there is any unread data to complete with.
+// If the identical entry was not found and this is a request of type multiple completion, search
+// for a similar one by a different client (on this TelObject) and if found simply create a new
+// entry with the same request handle that will be completed at the same time as the current
+// posted notification.
+// If this request has not been found in the active or wait lists, create the necessary
+// address space on server side
+//
+ {
+ HEtelBufC8* buf8=NULL;
+ HEtelBufC16* buf16=NULL;
+ CReqEntry* reqEntry=NULL;
+
+ reqEntry = PhoneOwner()->FindSameClientEntry(aSession,aMessage.Int3(),aMessage.Function());
+ if (reqEntry)
+ {
+ if (aReqMode&KReqModeRePostImmediately)
+ {
+ // same notification/buffered command has been found
+ // and either the read has completed or it has been stored in
+ // the request entry waiting for the completion from the TSY.
+ CompleteOrBufferRead(aMessage,reqEntry);
+ }
+ else // found an outstanding async req - panic
+ {
+ PanicClient(EEtelPanicRequestAsyncTwice,aMessage);
+ }
+ return NULL;
+ }
+ TInt messageType=aMessage.Int1();
+ TInt noOfSlots = 1;
+ if (aReqMode&KReqModeRePostImmediately)
+ noOfSlots = NumberOfSlotsL(aMessage.Function());
+ TInt size1;
+ TInt size2;
+ if (messageType!=EIsaNull &&
+ messageType!=EIsaCancelMessage &&
+ messageType!=EIsPriorityClientReqWithNull)
+ { // we're going to create server-side buffer
+ GetMessageDescriptorSizes(aMessage, size1, size2);
+ if (size1<0 || size2<0)
+ {
+ PanicClient(EEtelPanicBadDescriptor,aMessage);
+ return NULL;
+ }
+ if (messageType==EIsaNarrowAndUnicodeDoubleDesTobeSet ||
+ messageType==EIsaNarrowAndUnicodeDoubleDesTobeRead ||
+ messageType==EIsaNarrowDesToGetUnicodeDesToSet ||
+ messageType==EIsaUnicodeDesToGetNarrowDesToSet)
+ {
+ TInt zeroSize=0;
+
+ buf8 = CreateNarrowBufferLC(aSession->EmergencyClientHeap(messageType),aMessage,0,2,size1,zeroSize,noOfSlots);
+ buf16 = CreateUnicodeBufferLC(aSession->EmergencyClientHeap(messageType),aMessage,2,NULL,size2,zeroSize,noOfSlots); // the second client parameter pointer is passed as the first, so that the second parameter will be copied as the first
+ }
+ else
+ if (messageType==EIsaUnicodeDesToSetAndGet)
+ buf16 = CreateUnicodeBufferLC(aSession->EmergencyClientHeap(messageType),aMessage,0,2,size1,size2,noOfSlots);
+
+ else
+ if (!(aSession->IsUnicodeReq(messageType)))
+ buf8 = CreateNarrowBufferLC(aSession->EmergencyClientHeap(messageType),aMessage,0,2,size1,size2,noOfSlots);
+
+ else
+ buf16 = CreateUnicodeBufferLC(aSession->EmergencyClientHeap(messageType),aMessage,0,2,size1,size2,noOfSlots);
+ size1+=sizeof(TPtr); // passed into CBuffer::NewL() later as these sizes
+ if (size2!=0) // remain zero otherwise
+ size2+=sizeof(TPtr); //sizeof(TPtr)==sizeof(TPtr8)==sizeof(TPtr16)
+ }
+ else
+ {
+ size1 = 0;
+ size2 = 0;
+ }
+ //
+ // Now create the wrapper class, which manages the circular buffer.
+ //
+ CBuffer* buffer = CBuffer::NewL(buf8,buf16,aSession->EmergencyClientHeap(messageType),size1,size2,noOfSlots);
+ if (buf8)
+ CleanupStack::Pop(); // pops HEtelBufC8 off cleanup stack
+ if (buf16)
+ CleanupStack::Pop(); // pops HEtelBufC16 off cleanup stack
+ CleanupStack::PushL(buffer); // since buffer is still not owned by anything
+ //
+ // Now create the request entry for this client request - even if it's not to be passed
+ // down to the TSY in the case of MultipleCompletion.
+ //
+ reqEntry=PhoneOwner()->NewReqL(aMessage,aSession,buffer,this,aMessage.Function());
+ CleanupStack::Pop();
+
+ reqEntry->iInterestCategory = FindInterestCategory(aMessage.SecureId());
+
+ if ( aReqMode & (KReqModeMultipleCompletionEnabled | KReqModeMultipleCompletionWithInterestLevel) )
+ // this client has not currently got this request outstanding but another client may have
+ {
+ CReqEntry* previousReq=NULL;
+ previousReq=PhoneOwner()->FindByIpcAndTelObject(aMessage.Function(),this, buffer->Size()); // search in active list
+ if (previousReq)
+ {
+ reqEntry->iTsyReqHandle=previousReq->iTsyReqHandle;
+ reqEntry->iReqMode=aReqMode;
+ PhoneOwner()->AddReqToActive(reqEntry);
+ reqEntry=NULL;
+ }
+ else if (aReqMode&KReqModeFlowControlObeyed)
+ {
+ previousReq=PhoneOwner()->FindByIpcAndTelObjectInWaiting(aMessage.Function(),this, buffer->Size());
+ if (previousReq)
+ {
+ reqEntry->iTsyReqHandle=previousReq->iTsyReqHandle;
+ reqEntry->iReqMode=aReqMode;
+ PhoneOwner()->AddReqToWaiting(reqEntry);
+ reqEntry=NULL;
+ }
+ }
+ }
+ return reqEntry;
+ }
+
+void CTelObject::GeneralReq(const RMessage2& aMessage,CTelSession* aSession,CReqEntry* aNewReqEntry, TBool aFromFlowControlResume)
+//
+// On any CTelObject based class, do the general processing around sequential and parallel
+// request modes for the server, before calling the pure virtual Service in the class to do
+// the actual command.
+//
+ {
+
+ LOGTEXT2("CTelObject::GeneralReq - IPC=%d", aMessage.Function());
+ RECORD_IPC(aMessage,aSession,this,aFromFlowControlResume);
+ if (aFromFlowControlResume && !aFromFlowControlResume){ ; } // avoid compiler warning when ETEL_RECORDER is not defined
+
+ TInt type=aMessage.Int1();
+ CReqEntry* reqEntry=NULL;
+ TInt basicMsgType = type&(~(KUnicodeReq|KPriorityClientReq));
+ switch(basicMsgType)
+ {
+ case EIsaNull:
+ case EIsaDesTobeSet:
+ case EIsaDesTobeRead:
+ case EIsaDoubleDesTobeSet:
+ case EIsaDoubleDesTobeRead:
+ case EIsaNarrowAndUnicodeDoubleDesTobeSet:
+ case EIsaNarrowAndUnicodeDoubleDesTobeRead:
+ case EIsaNarrowDesToSetAndGet:
+ case EIsaNarrowDesToGetUnicodeDesToSet:
+ case EIsaUnicodeDesToSetAndGet:
+ case EIsaUnicodeDesToGetNarrowDesToSet:
+ {
+ TInt ipc=aMessage.Function();
+
+ TReqMode reqMode=0;
+ TRAPD(res,(reqMode=ReqModeL(ipc)));
+ if (res)
+ {
+ RECORD_COMPLETE_SUB(aMessage.Session(), this, aMessage.Int3(), aMessage.Function(), res);
+ aMessage.Complete(res);
+ return;
+ }
+
+ // If a call is session based then it can only be used
+ // when the client is the session owner.
+ if (reqMode&KReqModeSessionBased && IsSessionInProgress()
+ /*&& aMessage.Int3() != iSessionOwner.iSubSessionId TODO*/)
+ {
+ // Each type of session only allowed to have one ongoing 'session/dialogue'.
+ RECORD_COMPLETE_SUB(aMessage.Session(), this, aMessage.Int3(), aMessage.Function(), res);
+ aMessage.Complete(KErrServerBusy);
+ return;
+ }
+
+ if (aNewReqEntry==NULL)
+ {
+ TRAP(res,reqEntry=ReqAnalyserL(aMessage,aSession,reqMode));
+ if (res)
+ {
+ RECORD_COMPLETE_SUB(aMessage.Session(), this, aMessage.Int3(), aMessage.Function(), res);
+ aMessage.Complete(res);
+ return;
+ }
+ else
+ if (reqEntry==NULL) // there was no need to construct another reqEntry,
+ // or another reqEntry with identical IPC for a different client
+ // has been added inside ReqAnalyserL()
+
+ return;
+ reqEntry->iReqMode = reqMode; // so ReqCompleted() needn't ask for it again
+ }
+ else
+ reqEntry=aNewReqEntry; // aNewReqEntry has just come from the waiting list
+
+ if (reqMode&KReqModeFlowControlObeyed) // flow control obeyed
+ {
+ if (PhoneOwner()->FlowControl())
+ PhoneOwner()->AddReqToWaiting(reqEntry);
+ else
+ {
+ PhoneOwner()->FlowControlInc();
+ if (aNewReqEntry==NULL)
+ PhoneOwner()->AddReqToActive(reqEntry);
+ res=Service(aMessage,reqEntry);
+ if (res!=KErrNone) // can not do the service to tsy properly
+ {
+ CompleteAndDestroyReq(reqEntry,res);
+ PhoneOwner()->FlowControlDec(); // Dec() as service is being abandoned
+ }
+ }
+ }
+ else // Ignored
+ {
+ PhoneOwner()->AddReqToActive(reqEntry);
+ if (reqMode&KReqModeRePostImmediately)
+ res=RegisterNotification(ipc); // this tells the TSY the first time any client
+ // calls a particular notification.
+ if (res!=KErrNone)
+ CompleteAndDestroyReq(reqEntry,res);
+ else
+ {
+ res=Service(aMessage,reqEntry); // down to the TSY
+ if (res!=KErrNone)
+ CompleteAndDestroyReq(reqEntry,res);
+ }
+ }
+ break;
+ }
+ case EIsaCancelMessage:
+ // This is for Cancel Req - Int0 contains the original IPC
+ {
+ TInt cancelIpc=aMessage.Int0();
+ reqEntry=PhoneOwner()->FindClientInWaiting(aSession,aMessage.Int3(),cancelIpc);
+ if(reqEntry!=NULL) // Is it Waiting to be passed to the TSY?
+ {
+ CompleteAndDestroyReq(reqEntry,KErrCancel); // If yes then complete it.
+ RECORD_COMPLETE_SUB(aMessage.Session(), this, aMessage.Int3(), aMessage.Function(), KErrNone);
+ aMessage.Complete(KErrNone);
+ return;
+ }
+ reqEntry=PhoneOwner()->FindClientInActive(aSession,aMessage.Int3(),cancelIpc);
+ if(reqEntry) // found in active list
+ {
+ TReqMode reqMode=0;
+ TRAPD(res,(reqMode=ReqModeL(reqEntry->iFunction)));
+ if (res)
+ {
+ // client cannot check return value of Cancel()
+ // so use return value of original function call
+ RECORD_COMPLETE_SUB(reqEntry->iMessage.Session(), this, reqEntry->iMessage.Int3(), reqEntry->iMessage.Function(), res);
+ reqEntry->iMessage.Complete(res);
+ return;
+ }
+ if (reqMode&KReqModeRePostImmediately && reqEntry->iMessageNulled)
+ {
+ // client has called Cancel on a notification
+ // after it had completed to the client
+ RECORD_COMPLETE_SUB(aMessage.Session(), this, aMessage.Int3(), aMessage.Function(), KErrNone);
+ aMessage.Complete(KErrNone);
+ return;
+ }
+ // so now we know the client must have the request outstanding
+ if ((reqMode&KReqModeMultipleCompletionEnabled || reqMode&KReqModeMultipleCompletionWithInterestLevel) && !(reqEntry->iPlacedRequest))
+ {
+ if (iDeliveryObject)
+ {
+ iDeliveryObject->DeletedReqEntry(reqEntry);
+ }
+
+ CompleteAndDestroyReq(reqEntry,KErrCancel); // the request hadn't been passed to the TSY
+ RECORD_COMPLETE_SUB(aMessage.Session(), this, aMessage.Int3(), aMessage.Function(), KErrNone);
+ aMessage.Complete(KErrNone);
+ return;
+ }
+ // so the request is outstanding on the TSY
+ if (reqEntry->iCancelFnCalled==FALSE)
+ {
+ reqEntry->iCancelFnCalled=ETrue;
+ TInt status=CancelService(aMessage.Int0(),reqEntry->iTsyReqHandle);
+ if(status!=KErrNone)
+ CompleteAndDestroyReq(reqEntry,status);
+ }
+ }
+ RECORD_COMPLETE_SUB(aMessage.Session(), this, aMessage.Int3(), aMessage.Function(), KErrNone);
+ aMessage.Complete(KErrNone);
+ }
+ break;
+
+ case EIsaCancelSubSession:
+ // This is a special case for cancelling all asynchronous requests for this subsession
+ {
+ CancelSubSession(aSession,aMessage.Int3());
+ RECORD_COMPLETE_SUB(aMessage.Session(), this, aMessage.Int3(), aMessage.Function(), KErrNone);
+ aMessage.Complete(KErrNone);
+ }
+ break;
+
+ default:
+ PanicClient(EEtelPanicInvalidRequestType,aMessage);
+ break;
+ }
+ }
+
+void CTelObject::AcceptIncoming(const RMessage2& aMessage,CTelSession* aSession)
+ {
+ TInt status = KErrNotReady;
+ if (iDeliveryObject)
+ {
+ status = iDeliveryObject->ClientsDecision(aMessage, aSession, ETrue);
+ }
+ aMessage.Complete(status);
+ }
+
+void CTelObject::RejectIncoming(const RMessage2& aMessage,CTelSession* aSession)
+ {
+ TInt status = KErrNotReady;
+ if (iDeliveryObject)
+ {
+ if (iDeliveryObject->DeliveryInProgress())
+ {
+ status = iDeliveryObject->ClientsDecision(aMessage, aSession, EFalse);
+ }
+ else
+ {
+ // Rejecting when the time out has occurred will lead to a KErrNone
+ // error rather than KErrTimedOut.
+ status = KErrNone;
+ }
+ }
+ aMessage.Complete(status);
+ }
+
+EXPORT_C void CTelObject::ReqCompleted(const TTsyReqHandle aTsyReqHandle,const TInt aError)
+//
+// General complete function for all CTelObject derived classes
+//
+ {
+ __ASSERT_ALWAYS(aTsyReqHandle!=TSY_HANDLE_INIT_VALUE,Fault(EEtelFaultNotRecognisedTsyHandle));
+ TInt ipc=0;
+ CReqEntry* updatedReqEntry = NULL;
+ CReqEntry* nextPostedReqEntry = NULL;
+ updatedReqEntry=PhoneOwner()->FindByTsyHandleAndPlacedRequest(aTsyReqHandle);
+ __ASSERT_ALWAYS(updatedReqEntry!=NULL, Fault(EEtelFaultCompletionReceivedWithNoReqPackage));
+
+ TInt error = ResolveError(updatedReqEntry->iSession,aError); // set error as either low or high byte
+
+ ipc=updatedReqEntry->iFunction;
+ LOGTEXT4("CTelObject::ReqCompleted, IPC=%d, TsyHandle=%d, Error=%d", ipc, aTsyReqHandle, aError);
+
+ TReqMode reqMode = updatedReqEntry->iReqMode;
+ TBool ret=EFalse;
+ if (error!=KErrCancel)
+ {
+ // Multiple-completion malarky.
+ // Don't copy data across to other buffers and complete their reqs if TSY knows about
+ // each client that has called it. In that case,
+ // TSY will fill in the appropriate client's buffer and complete each separately.
+ if (reqMode&KReqModeMultipleCompletionEnabled)
+ {
+
+ PhoneOwner()->CheckAndCompleteAllActive(updatedReqEntry,reqMode,ipc,aError);
+ }
+ else if (reqMode&KReqModeMultipleCompletionWithInterestLevel && error ==KErrNone)
+ {
+ // TODO if delivery is active for this req then return
+ // KErrInUse / KErrServerBusy?
+ // TODO what if one CTelObject has multiple requests which are
+ // KReqModeMultipleCompletionWithInterestLevel. Would we need multiple
+ // delivery managers?
+ if (!IsSessionInProgress())
+ {
+ // Find an owner for the new session by offering it to the
+ // interested clients one by one.
+ DeliverReqL(updatedReqEntry,reqMode, ipc, aError);
+ }
+ else
+ {
+ // Route response direct to session owner
+ FindReq(updatedReqEntry, reqMode, ipc, aError);
+ }
+
+ }
+
+ if (reqMode&KReqModeRePostImmediately && error==KErrNone)
+ nextPostedReqEntry = updatedReqEntry;
+ updatedReqEntry->iBuffer->IncWrite();
+ }
+ else // if a cancel comes from the TSY, then if it is a notification
+ // there may be other clients who have also called the notification and who
+ // have entries in active list, so one of these must be re-posted.
+ {
+
+ if ( reqMode&KReqModeMultipleCompletionEnabled || reqMode&KReqModeMultipleCompletionWithInterestLevel)
+ {
+ nextPostedReqEntry = PhoneOwner()->FindThisReqByAnotherClient(updatedReqEntry->iSession,
+ updatedReqEntry->iMessage.Int3(),ipc,updatedReqEntry->iBuffer->Size(),this);
+ }
+
+ if (!nextPostedReqEntry)
+ // then we don't want to post any other client's requests in place of this one
+ {
+ nextPostedReqEntry = PhoneOwner()->FindNonCancelledClientReq(updatedReqEntry->iSession,updatedReqEntry->iMessage.Int3(),ipc);
+ __ASSERT_DEBUG(updatedReqEntry!=nextPostedReqEntry, Fault(EEtelFaultCancelErrorWithoutCancelled));
+ if (nextPostedReqEntry==NULL && reqMode&KReqModeRePostImmediately)
+ {
+ TInt ret = DeregisterNotification(ipc); // no more clients are interested so
+ // tell TSY to stop looking at notifies
+ if (ret!=KErrNone)
+ error=ret; // so the KErrCancel wouldn't reach the client
+ }
+ }
+ }
+
+ if (error && reqMode&KReqModeMultipleCompletionWithInterestLevel && iDeliveryObject)
+ {
+ // We need to do this before the updatedReqEntry is destroyed
+ iDeliveryObject->DeletedReqEntry(updatedReqEntry);
+ }
+
+ if (reqMode & KReqModeRePostImmediately)
+ {
+ // this will destroy the reqEntry if an error occurred.
+ UpdateAndCompleteIfNecessary(updatedReqEntry,error);
+ }
+ else
+ {
+ WriteBackAndCompleteReq(updatedReqEntry,error);
+ }
+
+ if (nextPostedReqEntry) // will be NULL if no following request for TSY
+ {
+ if(nextPostedReqEntry->iReqMode&KReqModeFlowControlObeyed &&
+ !(nextPostedReqEntry->iReqMode&KReqModeMultipleCompletionWithInterestLevel))
+ { // since the request mode is flow control obeyed, increment the flow control counter
+ FlowControlSuspend();
+ }
+ Service(nextPostedReqEntry->iMessage,nextPostedReqEntry);
+ }
+
+
+ if (!(reqMode&KReqModeFlowControlObeyed)) // If flow control not enabled, go home
+ {
+ ret=ETrue;
+ }
+
+// So everything below assumes it obeyed flow control
+// Resume Flow control ...
+ if (!ret)
+ {
+ FlowControlResume();
+ }
+//
+// Check and destroying the dummy session
+//
+ CheckAndDestroyDummySubSession();
+ }
+
+TInt CTelObject::DeliverReqL(CReqEntry* aUpdatedReqEntry,const TReqMode aReqMode,const TInt aIpc, const TInt aError)
+ {
+ // There is no active session therefore we have to work out who to deliver it to.
+ if (!iDeliveryObject)
+ {
+ iDeliveryObject = CMmDeliveryObject::NewL(*this);
+ }
+
+ if (iDeliveryObject->DeliveryInProgress())
+ {
+ // Session in progress.
+ return KErrPermissionDenied;
+ }
+
+ return iDeliveryObject->DeliverReqL(PhoneOwner()->ReqActiveList(), aUpdatedReqEntry, aReqMode, aIpc, aError);
+ }
+
+void CTelObject::FindReq(CReqEntry* aUpdatedReqEntry,const TReqMode aReqMode,const TInt aIpc,const TInt aError)
+ {
+ CReqEntry* reqEntry;
+ TDblQueIter<CReqEntry> iter(PhoneOwner()->ReqActiveList());
+ while(reqEntry = iter++, reqEntry!=NULL)
+ {
+ if(reqEntry->iFunction==aIpc
+ && reqEntry->iTelObject==aUpdatedReqEntry->iTelObject
+ && reqEntry->iBuffer->Size()==aUpdatedReqEntry->iBuffer->Size()
+ /*&& IsSessionOwner(reqEntry)*/)
+ {
+ if (aUpdatedReqEntry != reqEntry)
+ {
+ // Copy data from the 'placed' request to the one
+ // that is owned by the client.
+ PhoneOwner()->UpdateBuffer(aUpdatedReqEntry,reqEntry);
+ }
+ OfferToClient(reqEntry, aUpdatedReqEntry, aReqMode, aError);
+ RepostRequest(aUpdatedReqEntry, aError);
+ }
+ }
+ }
+
+void CTelObject::OfferToClient(CReqEntry* aReqEntry,CReqEntry* aUpdatedReqEntry,const TReqMode aReqMode,const TInt aError)
+ {
+ if (aReqEntry == aUpdatedReqEntry)
+ {
+ aUpdatedReqEntry->iBuffer->IncWrite();
+ if (aReqMode&KReqModeRePostImmediately)
+ {
+ // this will destroy the reqEntry if an error occurred.
+ UpdateAndCompleteIfNecessary(aUpdatedReqEntry,aError);
+ }
+ else
+ {
+ WriteBackAndCompleteReq(aUpdatedReqEntry,aError);
+ }
+ }
+ else
+ {
+ TInt error = ResolveError(aReqEntry->iSession,aError); // set error as either low or high byte
+ if (aReqMode&KReqModeRePostImmediately)
+ {
+ UpdateAndCompleteIfNecessary(aReqEntry,error);
+ }
+ else
+ {
+ WriteBackAndCompleteReq(aReqEntry,error);
+ }
+ }
+
+ CheckAndDestroyDummySubSession(); //TODO
+ }
+
+void CTelObject::RepostRequest(CReqEntry* aUpdatedReqEntry, const TInt aError)
+ {
+ TReqMode reqMode = aUpdatedReqEntry->iReqMode;
+ TBool ret=EFalse;
+
+ CReqEntry* nextPostedReqEntry = NULL;
+ if (reqMode&KReqModeRePostImmediately && aError==KErrNone)
+ {
+ nextPostedReqEntry = aUpdatedReqEntry;
+ }
+
+ if (nextPostedReqEntry) // will be NULL if no following request for TSY
+ {
+ if(nextPostedReqEntry->iReqMode&KReqModeFlowControlObeyed)
+ { // since the request mode is flow control obeyed, increment the flow control counter
+ FlowControlSuspend();
+ }
+ Service(nextPostedReqEntry->iMessage,nextPostedReqEntry);
+ }
+
+ if (!(reqMode&KReqModeFlowControlObeyed && aError == KErrNone)) // If flow control not enabled, go home
+ ret=ETrue;
+
+ // So everything below assumes it obeyed flow control
+ // Resume Flow control ...
+ if (!ret)
+ FlowControlResume();
+ }
+
+void CTelObject::SetSessionOwner(TInt aSessionHandle, TInt aSubSessionHandle)
+ {
+ iDeliveryObject->iSessionOwner = TPhoneClientId(aSessionHandle, aSubSessionHandle);
+ // TODO notify TSY that the session owner has changed
+ }
+
+// TODO can be used by the TSY to set the session owner to the current request.
+// For each request the CTSY is given a TsyReqHandle so this is a sensible thing
+// for it to be dealing with.
+// TODO note that once a session has an owner the reserved state is irrelevant.
+
+EXPORT_C void CTelObject::SetSessionOwnerByTsyHandle(const TTsyReqHandle aTsyReqHandle)
+ {
+// const TInt owningsession = PhoneOwner()->FindSessionByTsyHandle( aTsyReqHandle );
+// const TInt owningsubsession = PhoneOwner()->FindSubSessionByTsyHandle( aTsyReqHandle );
+
+// iSessionOwner = TPhoneClientId(owningsession, owningsubsession);
+ // TODO notify TSY that the session owner has changed
+ }
+
+
+TBool CTelObject::IsSessionOwner(CReqEntry* aReqEntry) const
+ {
+ // TODO Neil's experimental update
+ TPhoneClientId clientId(reinterpret_cast<TInt>(aReqEntry->iSession),aReqEntry->iMessage.Int3());
+ return (clientId == iDeliveryObject->iSessionOwner);
+ }
+
+TInterestCategory CTelObject::FindInterestCategory( const TSecureId aSid)
+ {
+ if (aSid == KUssdPriorityClientSid)
+ {
+ return EInterestCategoryPriority;
+ }
+ else if(aSid == KUssdDefaultClientSid)
+ {
+ return EInterestCategoryDefault;
+ }
+ else
+ return EInterestCategoryStandard;
+ }
+
+EXPORT_C TBool CTelObject::IsSessionInProgress() const
+ {
+ // TODO Neil's experimental update
+ if (iDeliveryObject)
+ {
+ return iDeliveryObject->iSessionOwner != TPhoneClientId();
+ }
+ return EFalse;
+ }
+
+EXPORT_C TInt CTelObject::ReserveSession()
+ {
+ // TODO Neil's experimental update
+ ASSERT(iDeliveryObject);
+ if (iDeliveryObject->iSessionReserved)
+ {
+ return KErrInUse;
+ }
+ iDeliveryObject->iSessionReserved = ETrue;
+ return KErrNone;
+ }
+
+EXPORT_C TBool CTelObject::IsSessionReserved() const
+ {
+ // TODO Neil's experimental update
+ return iDeliveryObject->iSessionReserved;
+ }
+
+EXPORT_C void CTelObject::CancelReserveSession()
+ {
+ // TODO Neil's experimental update
+ iDeliveryObject->iSessionReserved = EFalse;
+ }
+
+EXPORT_C void CTelObject::EndSession()
+ {
+ // TODO Neil's experimental update
+ iDeliveryObject->iSessionOwner = TPhoneClientId();
+ iDeliveryObject->iSessionReserved = EFalse;
+ }
+
+TInt CTelObject::ResolveError(CTelSession* aSession, const TInt aError) const
+/**
+ * Converts a coded error into the correct error to return. The coded error value
+ * allows an extended error code to be present allong with a basic error code. If
+ * the client has specified awareness of the extended codes, then they are returned.
+ * Otherwise the basic error code will be returned. The advanced error codes do not
+ * overlap the basic ones.
+ *
+ * In the case of no extended error code available, then the core error code will
+ * be returned regardless of the client's extended error granularity.
+ *
+ * @return Either the basic error code or the advanced error coded if available and
+ * requested.
+ * @param aSession The CTelSession of the client.
+ * @param aError The coded error.
+ */
+ {
+ //
+ // Handle the common cases to make the code more efficent....
+ //
+ if ((aError==KErrNone) || (aError==KErrCancel))
+ {
+ return aError;
+ }
+
+ //
+ // 'aError' is coded into two halves (eXtended and baSic): 0xXXXXSSSS. Take the
+ // top 16 bits for the eXtended code, and the bottom 16 bit for the baSic code.
+ //
+ // So, basicError becomes 0xffffSSSS and extendedError becomes 0xffffXXXX.
+ //
+ // A special case exists if the 16 bits were 0x0000 as this is KErrNone, and we must
+ // treat this as a positive int and not a negative one (e.g. clear the top 16 bits).
+ //
+ TInt basicError = (aError | 0xFFFF0000);
+ TInt extendedError = ((aError >> 16) | 0xFFFF0000);
+
+ if (basicError == (TInt)(0xffff0000))
+ {
+ basicError = KErrNone;
+ }
+
+ if (extendedError == (TInt)(0xffff0000))
+ {
+ extendedError = KErrNone;
+ }
+
+ //
+ // If the an extended error code is available and if client wants extended errors
+ // then return the extended error. Otherwise return the basic error code.
+ //
+ // The extended error is not available if 'extendedError' is KErrNotFound (e.g.
+ // the top 16 bits were 0xffff.
+ //
+ if (extendedError != KErrNotFound && aSession->IsExpectingExtendedError())
+ {
+ return extendedError;
+ }
+ else
+ {
+ return basicError;
+ }
+ }
+
+void CTelObject::UpdateAndCompleteIfNecessary(CReqEntry* aReqEntry,TInt aError) const
+//
+// If client has this request outstanding on the server, complete it, otherwise set Read
+// flag to false. Destroy the request if an error has occurred.
+//
+ {
+ if (aReqEntry->iMessageNulled)
+ aReqEntry->iReadByClient=EFalse;
+ else
+ WriteBackAndCompleteBufferedReq(aReqEntry->iMessage,aReqEntry,aError);
+ if (aError)
+ DestroyReq(aReqEntry);
+ }
+
+void CTelObject::CheckAndDestroyDummySubSession()
+ {
+ if (iActiveReqCount)
+ {
+ iActiveReqCount--;
+ LOGTEXT2("In CheckAndDestroyDummySubSession(), iActiveReqCount down to %d", iActiveReqCount);
+ if ((iActiveReqCount==0) && (iCreateDummy==FALSE))
+ {
+ __ASSERT_ALWAYS(iDestroyDummySubSession!=NULL,Fault(EEtelFaultBadTelSessionPointer));
+ if (!(iDestroyDummySubSession->IsActive())) // only set going if not already active!
+ {
+ iDestroyDummySubSession->Call();
+ iTelServer->Dec();
+ }
+ }
+ }
+ else if (iCreateDummy)
+ {
+ __ASSERT_ALWAYS(iDestroyDummySubSession!=NULL,Fault(EEtelFaultBadTelSessionPointer));
+ if (!(iDestroyDummySubSession->IsActive())) // only set going if not already active!
+ {
+ iDestroyDummySubSession->Call();
+ iTelServer->Dec();
+ }
+ iCreateDummy=EFalse;
+ }
+ }
+
+void CTelObject::WriteBackAndCompleteBufferedReq(const RMessage2& aNewMessage,CReqEntry* aReqEntry,TInt aError) const
+ {
+ TInt basicMessageType =0;
+ basicMessageType = (aNewMessage.Int1() & ~(KPriorityClientReq));
+ switch (basicMessageType)
+ {
+ case EIsaNull:
+ if (aReqEntry->iClientInterested)
+ {
+ RECORD_COMPLETE_SUB(aNewMessage.Session(), this, aNewMessage.Int3(), aNewMessage.Function(), aError);
+ aNewMessage.Complete(aError);
+ }
+ break;
+ case EIsaDesTobeRead:
+ case EIsaDoubleDesTobeRead:
+ if (aReqEntry->iClientInterested)
+ {
+ __ASSERT_ALWAYS(aReqEntry->iBuffer->iBuf8!=NULL,Fault(EETelFaultRequestWithoutBuffer));
+ TDes8* dataDes1=BufferDes1(aReqEntry->iBuffer,CBuffer::ESlotRead);
+ __ASSERT_ALWAYS(dataDes1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
+
+ TRAPD(ret,aNewMessage.WriteL(0,*dataDes1)); // if this fails, panic the client
+ if(ret!=KErrNone)
+ {
+ PanicClient(EEtelPanicBadDescriptor,aNewMessage);
+ break;
+ }
+
+ if (basicMessageType==EIsaDoubleDesTobeRead)
+ {
+ TDes8* dataDes2=BufferDes2(aReqEntry->iBuffer,CBuffer::ESlotRead);
+ __ASSERT_ALWAYS(dataDes2!=NULL,Fault(EEtelFaultDes2DoesNotExist));
+
+ TRAP(ret,aNewMessage.WriteL(2,*dataDes2));
+ if(ret!=KErrNone)
+ {
+ PanicClient(EEtelPanicBadDescriptor,aNewMessage);
+ break;
+ }
+ }
+ RECORD_COMPLETE_SUB(aNewMessage.Session(), this, aNewMessage.Int3(), aNewMessage.Function(), aError);
+ aNewMessage.Complete(aError);
+ }
+ break;
+ case EIsaUnicodeDesTobeRead:
+ case EIsaUnicodeDoubleDesTobeRead:
+ {
+ if (aReqEntry->iClientInterested)
+ {
+ __ASSERT_ALWAYS(aReqEntry->iBuffer->iBuf16!=NULL,Fault(EETelFaultRequestWithoutBuffer));
+ // The TDes16 will be at the start of the HBufC buffer
+ TDes16* unicodeDataDes1=BufferDes1u(aReqEntry->iBuffer,CBuffer::ESlotRead);
+ __ASSERT_ALWAYS(unicodeDataDes1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
+
+ TRAPD(ret,aNewMessage.WriteL(0,*unicodeDataDes1));
+ if(ret!=KErrNone)
+ {
+ PanicClient(EEtelPanicBadDescriptor,aNewMessage);
+ break;
+ }
+
+ if (basicMessageType==EIsaUnicodeDoubleDesTobeRead)
+ {
+ TDes16* unicodeDataDes2=BufferDes2u(aReqEntry->iBuffer,CBuffer::ESlotRead);
+ __ASSERT_ALWAYS(unicodeDataDes2!=NULL,Fault(EEtelFaultDes2DoesNotExist));
+
+ TRAP(ret,aNewMessage.WriteL(2,*unicodeDataDes2));
+ if(ret!=KErrNone)
+ {
+ PanicClient(EEtelPanicBadDescriptor,aNewMessage);
+ break;
+ }
+ }
+ RECORD_COMPLETE_SUB(aNewMessage.Session(), this, aNewMessage.Int3(), aNewMessage.Function(), aError);
+ aNewMessage.Complete(aError);
+ }
+ }
+ break;
+
+ case EIsaNarrowAndUnicodeDoubleDesTobeRead:
+ {
+ if (aReqEntry->iClientInterested)
+ {
+ __ASSERT_ALWAYS(aReqEntry->iBuffer->iBuf16!=NULL,Fault(EETelFaultRequestWithoutBuffer));
+ TDes8* dataDes1=BufferDes1(aReqEntry->iBuffer,CBuffer::ESlotRead);
+ __ASSERT_ALWAYS(dataDes1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
+
+ TRAPD(ret,aNewMessage.WriteL(0,*dataDes1));
+ if(ret!=KErrNone)
+ {
+ PanicClient(EEtelPanicBadDescriptor,aNewMessage);
+ break;
+ }
+
+ TDes16* unicodeDataDes2=BufferDes2u(aReqEntry->iBuffer,CBuffer::ESlotRead);
+ __ASSERT_ALWAYS(unicodeDataDes2!=NULL,Fault(EEtelFaultDes2DoesNotExist));
+
+ TRAP(ret,aNewMessage.WriteL(2,*unicodeDataDes2));
+ if(ret!=KErrNone)
+ {
+ PanicClient(EEtelPanicBadDescriptor,aNewMessage);
+ break;
+ }
+ RECORD_COMPLETE_SUB(aNewMessage.Session(), this, aNewMessage.Int3(), aNewMessage.Function(), aError);
+ aNewMessage.Complete(aError);
+ }
+ }
+ break;
+
+ case EIsaNarrowDesToSetAndGet:
+ {
+ if (aReqEntry->iClientInterested)
+ {
+ __ASSERT_ALWAYS(aReqEntry->iBuffer->iBuf8!=NULL,Fault(EETelFaultRequestWithoutBuffer));
+ TDes8* dataDes2=BufferDes2(aReqEntry->iBuffer,CBuffer::ESlotRead);
+ __ASSERT_ALWAYS(dataDes2!=NULL,Fault(EEtelFaultDes2DoesNotExist));
+
+ TRAPD(ret,aNewMessage.WriteL(2,*dataDes2));
+ if(ret!=KErrNone)
+ {
+ PanicClient(EEtelPanicBadDescriptor,aNewMessage);
+ break;
+ }
+ RECORD_COMPLETE_SUB(aNewMessage.Session(), this, aNewMessage.Int3(), aNewMessage.Function(), aError);
+ aNewMessage.Complete(aError);
+ }
+ }
+ break;
+
+ case EIsaUnicodeDesToGetNarrowDesToSet:
+ case EIsaUnicodeDesToSetAndGet:
+ if (aReqEntry->iClientInterested)
+ {
+ __ASSERT_ALWAYS(aReqEntry->iBuffer->iBuf16!=NULL,Fault(EETelFaultRequestWithoutBuffer));
+ TDes16* dataDes2=BufferDes2u(aReqEntry->iBuffer,CBuffer::ESlotRead);
+ __ASSERT_ALWAYS(dataDes2!=NULL,Fault(EEtelFaultDes2DoesNotExist));
+
+ TRAPD(ret,aNewMessage.WriteL(2,*dataDes2));
+ if(ret!=KErrNone)
+ {
+ PanicClient(EEtelPanicBadDescriptor,aNewMessage);
+ break;
+ }
+ RECORD_COMPLETE_SUB(aNewMessage.Session(), this, aNewMessage.Int3(), aNewMessage.Function(), aError);
+ aNewMessage.Complete(aError);
+ }
+ break;
+
+ case EIsaNarrowDesToGetUnicodeDesToSet:
+ {
+ if (aReqEntry->iClientInterested)
+ {
+ __ASSERT_ALWAYS(aReqEntry->iBuffer->iBuf8!=NULL,Fault(EETelFaultRequestWithoutBuffer));
+ TDes8* dataDes1=BufferDes1(aReqEntry->iBuffer,CBuffer::ESlotRead);
+ __ASSERT_ALWAYS(dataDes1!=NULL,Fault(EEtelFaultDes1DoesNotExist));
+
+ TRAPD(ret,aNewMessage.WriteL(0,*dataDes1));
+ if(ret!=KErrNone)
+ {
+ PanicClient(EEtelPanicBadDescriptor,aNewMessage);
+ break;
+ }
+ RECORD_COMPLETE_SUB(aNewMessage.Session(), this, aNewMessage.Int3(), aNewMessage.Function(), aError);
+ aNewMessage.Complete(aError);
+ }
+ }
+ break;
+
+ case EIsaDesTobeSet:
+ case EIsaDoubleDesTobeSet:
+ case EIsaUnicodeDesTobeSet:
+ case EIsaUnicodeDoubleDesTobeSet:
+ case EIsaNarrowAndUnicodeDoubleDesTobeSet:
+ case EIsaCancelMessage:
+ case EIsaCancelSubSession:
+
+ default:
+ Fault(EEtelFaultBadMessageType);
+ break;
+ }
+ if (aError==KErrNone || aError==KErrOverflow)
+ {
+ aReqEntry->iReadByClient=ETrue;
+ aReqEntry->iMessageNulled=ETrue;
+ aReqEntry->iBuffer->IncRead();
+ }
+ }
+
+void CTelObject::WriteBackAndCompleteReq(CReqEntry* aReqEntry,const TInt aError) const
+//
+// Complete a request entry and write data back to client
+//
+ {
+ __ASSERT_ALWAYS(aReqEntry!=NULL,Fault(EEtelFaultCompleteReqWithoutReqEntry));
+ LOGTEXT("CTelObject::WriteBackAndCompleteReq");
+ TInt basicMessageType = (aReqEntry->iMessage.Int1() & ~KPriorityClientReq);
+
+ switch (basicMessageType)
+ {
+ case EIsaNull:
+ aReqEntry->CompleteAndDeque(aError);
+ break;
+ case EIsaDesTobeSet:
+ case EIsaDoubleDesTobeSet:
+ __ASSERT_ALWAYS(aReqEntry->iBuffer->iBuf8!=NULL,Fault(EETelFaultRequestWithoutBuffer));
+ aReqEntry->CompleteAndDeque(aError);
+ break;
+ case EIsaUnicodeDesTobeSet:
+ case EIsaUnicodeDoubleDesTobeSet:
+ case EIsaNarrowAndUnicodeDoubleDesTobeSet:
+ __ASSERT_ALWAYS(aReqEntry->iBuffer->iBuf16!=NULL,Fault(EETelFaultRequestWithoutBuffer));
+ aReqEntry->CompleteAndDeque(aError);
+ break;
+ case EIsaDesTobeRead:
+ case EIsaDoubleDesTobeRead:
+ {
+ if (aReqEntry->iClientInterested)
+ {
+ __ASSERT_ALWAYS(aReqEntry->iBuffer->iBuf8!=NULL,Fault(EETelFaultRequestWithoutBuffer));
+ // The TPtr8 will be at the start of the HBufC buffer
+ TDes8* dataDes1=BufferDes1(aReqEntry->iBuffer,CBuffer::ESlotRead);
+ __ASSERT_ALWAYS(dataDes1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
+
+ TRAPD(ret,aReqEntry->iMessage.WriteL(0,*dataDes1));
+ if(ret!=KErrNone)
+ {
+ PanicClient(EEtelPanicBadDescriptor,aReqEntry->iMessage);
+ break;
+ }
+
+ if (basicMessageType==EIsaDoubleDesTobeRead)
+ {
+ TDes8* dataDes2=BufferDes2(aReqEntry->iBuffer,CBuffer::ESlotRead);
+
+ TRAP(ret,aReqEntry->iMessage.WriteL(2,*dataDes2));
+ if(ret!=KErrNone)
+ {
+ PanicClient(EEtelPanicBadDescriptor,aReqEntry->iMessage);
+ break;
+ }
+ }
+ }
+ aReqEntry->CompleteAndDeque(aError);
+ }
+ break;
+ case EIsaUnicodeDesTobeRead:
+ case EIsaUnicodeDoubleDesTobeRead:
+ {
+ if (aReqEntry->iClientInterested)
+ {
+ __ASSERT_ALWAYS(aReqEntry->iBuffer->iBuf16!=NULL,Fault(EETelFaultRequestWithoutBuffer));
+ TDes16* dataDes1=BufferDes1u(aReqEntry->iBuffer,CBuffer::ESlotRead);
+
+ TRAPD(ret,aReqEntry->iMessage.WriteL(0,*dataDes1));
+ if(ret!=KErrNone)
+ {
+ PanicClient(EEtelPanicBadDescriptor,aReqEntry->iMessage);
+ break;
+ }
+
+ if (basicMessageType==EIsaUnicodeDoubleDesTobeRead)
+ {
+ TDes16* dataDes2=BufferDes2u(aReqEntry->iBuffer,CBuffer::ESlotRead);
+
+ TRAP(ret,aReqEntry->iMessage.WriteL(2,*dataDes2));
+ if(ret!=KErrNone)
+ {
+ PanicClient(EEtelPanicBadDescriptor,aReqEntry->iMessage);
+ break;
+ }
+ }
+ }
+ aReqEntry->CompleteAndDeque(aError);
+ }
+ break;
+ case EIsaNarrowAndUnicodeDoubleDesTobeRead:
+ {
+ if (aReqEntry->iClientInterested)
+ {
+ __ASSERT_ALWAYS(aReqEntry->iBuffer->iBuf16!=NULL,Fault(EETelFaultRequestWithoutBuffer));
+ TDes8* dataDes1=BufferDes1(aReqEntry->iBuffer,CBuffer::ESlotRead);
+ __ASSERT_ALWAYS(dataDes1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
+
+ TRAPD(ret,aReqEntry->iMessage.WriteL(0,*dataDes1));
+ if(ret!=KErrNone)
+ {
+ PanicClient(EEtelPanicBadDescriptor,aReqEntry->iMessage);
+ break;
+ }
+
+ TDes16* unicodeDataDes2=BufferDes2u(aReqEntry->iBuffer,CBuffer::ESlotRead);
+ __ASSERT_ALWAYS(unicodeDataDes2!=NULL,Fault(EEtelFaultDes2DoesNotExist));
+
+ TRAP(ret,aReqEntry->iMessage.WriteL(2,*unicodeDataDes2));
+ if(ret!=KErrNone)
+ {
+ PanicClient(EEtelPanicBadDescriptor,aReqEntry->iMessage);
+ break;
+ }
+ }
+ aReqEntry->CompleteAndDeque(aError);
+ }
+ break;
+
+ case EIsaNarrowDesToSetAndGet:
+ {
+ if (aReqEntry->iClientInterested)
+ {
+ __ASSERT_ALWAYS(aReqEntry->iBuffer->iBuf8!=NULL,Fault(EETelFaultRequestWithoutBuffer));
+ // only write back the second parameter
+ TDes8* dataDes2=BufferDes2(aReqEntry->iBuffer,CBuffer::ESlotRead);
+ __ASSERT_ALWAYS(dataDes2!=NULL,Fault(EETelFaultRequestWithoutBuffer));
+
+ TRAPD(ret,aReqEntry->iMessage.WriteL(2,*dataDes2));
+ if(ret!=KErrNone)
+ {
+ PanicClient(EEtelPanicBadDescriptor,aReqEntry->iMessage);
+ break;
+ }
+ }
+ aReqEntry->CompleteAndDeque(aError);
+ }
+ break;
+
+ case EIsaNarrowDesToGetUnicodeDesToSet:
+ {
+ if (aReqEntry->iClientInterested)
+ {
+ __ASSERT_ALWAYS(aReqEntry->iBuffer->iBuf8!=NULL,Fault(EETelFaultRequestWithoutBuffer));
+ // only write back the first parameter
+ TDes8* dataDes1=BufferDes1(aReqEntry->iBuffer,CBuffer::ESlotRead);
+ __ASSERT_ALWAYS(dataDes1!=NULL,Fault(EETelFaultRequestWithoutBuffer));
+
+ TRAPD(ret,aReqEntry->iMessage.WriteL(0,*dataDes1));
+ if(ret!=KErrNone)
+ {
+ PanicClient(EEtelPanicBadDescriptor,aReqEntry->iMessage);
+ break;
+ }
+ }
+ aReqEntry->CompleteAndDeque(aError);
+ }
+ break;
+
+ case EIsaUnicodeDesToSetAndGet:
+ case EIsaUnicodeDesToGetNarrowDesToSet:
+ {
+ if (aReqEntry->iClientInterested)
+ {
+ __ASSERT_ALWAYS(aReqEntry->iBuffer->iBuf16!=NULL,Fault(EETelFaultRequestWithoutBuffer));
+ // only write back the second parameter
+ TDes16* dataDes2=BufferDes2u(aReqEntry->iBuffer,CBuffer::ESlotRead);
+ __ASSERT_ALWAYS(dataDes2!=NULL,Fault(EETelFaultRequestWithoutBuffer));
+
+ TRAPD(ret,aReqEntry->iMessage.WriteL(2,*dataDes2));
+ if(ret!=KErrNone)
+ {
+ PanicClient(EEtelPanicBadDescriptor,aReqEntry->iMessage);
+ break;
+ }
+ }
+ aReqEntry->CompleteAndDeque(aError);
+ }
+ break;
+
+ default:
+ Fault(EEtelFaultBadMessageType);
+ break;
+ }
+ aReqEntry->Deque();
+ delete aReqEntry;
+ }
+
+EXPORT_C void CTelObject::FlowControlSuspend()
+//
+// Suspend the Request Flow
+//
+ {
+ PhoneOwner()->FlowControlInc();
+ }
+
+
+EXPORT_C void CTelObject::FlowControlResume()
+
+//
+// Resume the Request Flow
+//
+ {
+ PhoneOwner()->FlowControlDec();
+ if(PhoneOwner()->FlowControl()>0) // check for outstanding request
+ return;
+
+ CReqEntry* reqEntry=PhoneOwner()->ActivateNextWaitingReq();
+ if (reqEntry==NULL)
+ return;
+
+ RMessage2& message=reqEntry->iMessage;
+
+ CTelObject* theObj=reqEntry->iSession->CObjectFromHandle(message.Int3());
+ __ASSERT_ALWAYS(theObj!=NULL, Fault(EEtelFaultWaitingReqLostCObject));
+ theObj->GeneralReq(message,reqEntry->iSession,reqEntry, ETrue);
+ }
+
+//
+// Future proofing in server
+//
+EXPORT_C TInt CTelObject::DownCallOption(TInt /*aOptionNumber*/, TAny* /*aData*/)
+ {
+ return KErrNotSupported;
+ }
+
+EXPORT_C TInt CTelObject::UpCallOption(TInt /*aOptionNumber*/, TAny* /*aData*/)
+ {
+ return KErrNotSupported;
+ }
+
+EXPORT_C TInt CTelObject::ServerVersion() const
+//
+// Lets TSY know which version of server this is, ie which extra options the server will support.
+//
+ {
+ return KETelServerVersion;
+ }
+
+EXPORT_C TSecurityPolicy CTelObject::GetRequiredPlatSecCaps(const TInt /*aIpc*/)
+/**
+ * Default implementation of TSY side of the Etel capability policy checking delegation.
+ * If the TSY does not support CustomAPIs or the TSY does not implement it's own version
+ * of this virtual function, then this default implementation will get used and shall always
+ * return a policy that fails the capability check.
+ *
+ * @return This base implementation always returns a TSecurityPolicy::EAlwaysFail.
+ * @param aIpc This parameter is not used in the base implementation of this virtual function.
+ */
+ {
+ return TSecurityPolicy(TSecurityPolicy::EAlwaysFail);
+ }
+
+
+TDes8* CTelObject::BufferDes1(const CBuffer* aBuffer,CBuffer::TWhichSlot aWhichSlot) const
+//
+// Returns pointer to first descriptor in current slot. More specifically, a pointer to the
+// TPtr which is stored just before the data that it points to.
+
+// The buffer is circular, and there are
+// two "current" slots - one slot for where the next data should be written to by the TSY,
+// the other from which the client should next read from. aWhichSlot specifies which of these
+// should be returned.
+//
+ {
+ TDes8* des1=NULL;
+ if (aBuffer->iBuf8)
+ {
+ TUint8* pos = aBuffer->CurrentSlotData1(aWhichSlot);
+ if (pos)
+ des1=reinterpret_cast<TDes8*> (pos);
+ }
+ return des1;
+ }
+
+TDes8* CTelObject::BufferDes2(const CBuffer* aBuffer,CBuffer::TWhichSlot aWhichSlot) const
+ {
+ TDes8* des2=NULL;
+ if (aBuffer->iBuf8)
+ {
+ TUint8* pos = aBuffer->CurrentSlotData2(aWhichSlot);
+ if (pos)
+ des2=reinterpret_cast<TDes8*> (pos);
+ }
+ return des2;
+ }
+
+TDes16* CTelObject::BufferDes1u(const CBuffer* aBuffer,CBuffer::TWhichSlot aWhichSlot) const
+ {
+ TDes16* des1=NULL;
+ if (aBuffer->iBuf16)
+ {
+ TUint16* pos = aBuffer->CurrentSlotData1u(aWhichSlot);
+ if (pos)
+ des1=reinterpret_cast<TDes16*> (pos);
+ }
+ return des1;
+ }
+
+TDes16* CTelObject::BufferDes2u(const CBuffer* aBuffer,CBuffer::TWhichSlot aWhichSlot) const
+ {
+ TDes16* des2=NULL;
+ if (aBuffer->iBuf16)
+ {
+ TUint16* pos = aBuffer->CurrentSlotData2u(aWhichSlot);
+ if (pos)
+ des2=reinterpret_cast<TDes16*> (pos);
+ }
+ return des2;
+ }
+
+TUint8* CTelObject::Ptr1(const TDes8* aDes1) const
+//
+// return the pointer to the data of the first descriptor
+// return NULL if does not exist
+//
+ {
+ TUint8* ptr1=NULL;
+ if (aDes1)
+ ptr1=const_cast<TUint8*> (aDes1->Ptr());
+ return ptr1;
+ }
+
+void CTelObject::RemoveDummySubSessionDestroyer()
+ {
+ iDestroyDummySubSession = NULL;
+ }
+
+//
+//
+// CSubSessionExtBase
+//
+//
+EXPORT_C CSubSessionExtBase::CSubSessionExtBase()
+//
+// C'Tor
+//
+ {
+ __DECLARE_NAME(_S("CSubSessionExtBase"));
+ }
+
+EXPORT_C CSubSessionExtBase::~CSubSessionExtBase()
+//
+// D'Tor
+//
+ {}
+
+TInt CSubSessionExtBase::ServiceExtFunc(const RMessage2& aMessage,CReqEntry* aReqEntry)
+//
+// Sort out Des1 and Des2 before calling ExtFunc()
+//
+ {
+ __ASSERT_ALWAYS(aReqEntry!=NULL,Fault(EEtelFaultCallTsyServiceWithoutReqPackage));
+ TTsyReqHandle tsyReqHandle=aReqEntry->iTsyReqHandle;
+
+ LOGTEXT2("Entered ServiceExtFunc with TSY handle %d", tsyReqHandle);
+ TInt ret=KErrNone;
+
+ TInt basicMessageType = aMessage.Int1() & ~(KPriorityClientReq);
+ switch (basicMessageType)
+ {
+ case EIsaNull:
+ case EIsaCancelMessage:
+ {
+ TDataPackage package; // a package with all data pointers nulled
+ ret=ExtFunc(tsyReqHandle,aMessage.Function(),package);
+ }
+ break;
+ case EIsaDesTobeSet:
+ case EIsaDesTobeRead:
+ case EIsaDoubleDesTobeSet:
+ case EIsaDoubleDesTobeRead: // may have been multi-slot registered
+ case EIsaNarrowDesToSetAndGet:
+ {
+ TDes8* des1 = BufferDes1(aReqEntry->iBuffer,CBuffer::ESlotWrite);
+ if (!des1)
+ {
+ return KErrArgument;
+ }
+ TDes8* des2=NULL;
+ if (basicMessageType==EIsaDoubleDesTobeSet ||
+ basicMessageType==EIsaDoubleDesTobeRead ||
+ basicMessageType==EIsaNarrowDesToSetAndGet)
+ {
+ des2=BufferDes2(aReqEntry->iBuffer,CBuffer::ESlotWrite);
+ if (!des2)
+ {
+ return KErrArgument;
+ }
+ }
+ TDataPackage package(des1,des2);
+ ret=ExtFunc(tsyReqHandle,aReqEntry->iFunction,package);
+ }
+ break;
+ case EIsaUnicodeDesTobeSet:
+ case EIsaUnicodeDesTobeRead:
+ case EIsaUnicodeDoubleDesTobeSet:
+ case EIsaUnicodeDoubleDesTobeRead:
+ case EIsaUnicodeDesToSetAndGet:
+ {
+ TDes16* des1 = BufferDes1u(aReqEntry->iBuffer,CBuffer::ESlotWrite);
+ if (!des1)
+ {
+ return KErrArgument;
+ }
+ TDes16* des2=NULL;
+ if (basicMessageType==EIsaUnicodeDoubleDesTobeSet ||
+ basicMessageType==EIsaUnicodeDoubleDesTobeRead ||
+ basicMessageType==EIsaUnicodeDesToSetAndGet)
+ {
+ des2 = BufferDes2u(aReqEntry->iBuffer,CBuffer::ESlotWrite);
+ if (!des2)
+ {
+ return KErrArgument;
+ }
+ }
+ TDataPackage package(des1,des2);
+ ret=ExtFunc(tsyReqHandle,aReqEntry->iFunction,package);
+ }
+ break;
+ case EIsaNarrowAndUnicodeDoubleDesTobeSet:
+ case EIsaNarrowAndUnicodeDoubleDesTobeRead:
+ case EIsaNarrowDesToGetUnicodeDesToSet:
+ case EIsaUnicodeDesToGetNarrowDesToSet:
+ {
+ TDes8* des1 = BufferDes1(aReqEntry->iBuffer,CBuffer::ESlotWrite);
+ if (!des1)
+ {
+ return KErrArgument;
+ }
+ TDes16* des2=NULL;
+ des2=BufferDes2u(aReqEntry->iBuffer,CBuffer::ESlotWrite);
+ if (!des2)
+ {
+ return KErrArgument;
+ }
+ TDataPackage package(des1,des2);
+ ret=ExtFunc(tsyReqHandle,aReqEntry->iFunction,package);
+ }
+ break;
+
+ default:
+ Fault(EEtelFaultMessageTypeCorrupted);
+ break;
+ }
+ return ret;
+ }
+
+EXPORT_C TInt CSubSessionExtBase::Service(const RMessage2& aMessage, CReqEntry* aReqEntry)
+//
+// The ServiceL functionality for the ext base
+//
+ {
+ aReqEntry->iPlacedRequest=ETrue;
+ return ServiceExtFunc(aMessage,aReqEntry);
+ }
+
+EXPORT_C void CSubSessionExtBase::CloseSubSessionPreProcessing(CTelSession* aSession,const TInt aSubSessionHandle)
+ {
+ CreateDummySession(aSession,aSubSessionHandle);
+ FlushReqs(aSession,aSubSessionHandle);
+ }
+
+EXPORT_C void CSubSessionExtBase::OpenPostProcessing(CTelSession* /*aSession*/,const TInt)
+//
+// Perform post-processing after object has been added to session's CObjectIx.
+//
+ {
+ }
+
+EXPORT_C RHandleBase* CSubSessionExtBase::GlobalKernelObjectHandle()
+ {
+ return NULL;
+ }
+
+EXPORT_C void CSubSessionExtBase::NullMethod1()
+ {}
+
+EXPORT_C void CFaxBase::NullMethod2()
+ {}
+
+//
+//
+// CLibUnloader
+//
+//
+CLibUnloader::CLibUnloader()
+//
+// C'tor
+//
+ :CAsyncOneShot(CActive::EPriorityHigh)
+ {
+ __DECLARE_NAME(_S("CLibUnloader"));
+ }
+
+CLibUnloader* CLibUnloader::NewL(RLibrary &aLib)
+//
+// New Library Unloader
+//
+ {
+ CLibUnloader *s=new(ELeave)CLibUnloader;
+ s->iLib=aLib;
+ return s;
+ }
+
+CLibUnloader::~CLibUnloader()
+ {
+ Cancel();
+ iLib.Close();
+ }
+
+void CLibUnloader::RunL()
+//
+// Unload TSY module
+//
+ {
+ delete this;
+ }
+
+//
+//
+// CPhoneFactoryBase definition
+//
+//
+EXPORT_C TBool CPhoneFactoryBase::QueryVersionSupported( TVersion const & aVersion )const
+//
+// Pass through to default QVS
+//
+ {
+ return(User::QueryVersionSupported(iVersion,aVersion));
+ }
+
+EXPORT_C CPhoneFactoryBase::CPhoneFactoryBase()
+//
+// C'Tor
+//
+ {
+ __DECLARE_NAME(_S("CPhoneFactoryBase"));
+ }
+
+void CPhoneFactoryBase::ConstructL(RLibrary& aLib)
+//
+// Allocate a CLibrary Unloader
+//
+ {
+ iLibUnloader=CLibUnloader::NewL(aLib);
+ }
+
+EXPORT_C CPhoneFactoryBase::~CPhoneFactoryBase()
+//
+// D'Tor
+//
+ {
+ if (iLibUnloader)
+ {
+ LOGTEXT("About to call iLibUnloader");
+ iLibUnloader->Call();
+ }
+ }
+
+EXPORT_C void CPhoneFactoryBase::CPhoneFactoryBase_Reserved1()
+//
+// Reserved virtual function
+//
+ {}
+
+//
+// HEtelBufC definitions
+//
+
+
+//
+// HEtelBufC8
+//
+HEtelBufC8* HEtelBufC8::NewMaxLC(TInt aMaxLength,RHeap* aHeap)
+ {
+ __ASSERT_ALWAYS(aMaxLength>=0,Fault(EEtelFaultMaxDesLengthNegative));
+
+ HEtelBufC8* pH=NULL;
+ TInt size=sizeof(HEtelBufC8)+(aMaxLength*sizeof(TUint8));
+ if (aHeap!=NULL)
+ pH=(HEtelBufC8*)aHeap->AllocLC(size);
+ else
+ pH=(HEtelBufC8*)User::AllocLC(size);
+ pH->iLength=aMaxLength;
+ pH->iHeap=aHeap;
+ pH->Des().SetLength(aMaxLength);
+ return(pH);
+ }
+
+TPtr8 HEtelBufC8::Des()
+ {
+ TUint8* ptr = reinterpret_cast<TUint8*> (((reinterpret_cast<TInt> (this)) +
+ sizeof(HEtelBufC8))
+ );
+ return TPtr8(ptr,iLength,iLength);
+ }
+
+const TUint8* HEtelBufC8::Ptr() const
+ {
+ return reinterpret_cast<const TUint8*> (((reinterpret_cast<TInt> (this)) +
+ sizeof(HEtelBufC8))
+ );
+ }
+
+void HEtelBufC8::operator delete(TAny* aPtr)
+//
+// overloaded delete - deletes from priority client heap if iHeap is not NULL
+//
+ {
+ RHeap* heap=NULL;
+ if (aPtr!=NULL)
+ {
+ heap = (reinterpret_cast<HEtelBufC8*> (aPtr))->iHeap;
+ }
+
+ if (heap!=NULL)
+ {
+ reinterpret_cast<HEtelBufC8*> (aPtr)->iHeap->Free(aPtr);
+ }
+ else
+ {
+ User::Free(aPtr);
+ }
+ }
+
+//
+// HEtelBufC16
+//
+HEtelBufC16* HEtelBufC16::NewMaxLC(TInt aMaxLength,RHeap* aHeap)
+ {
+ __ASSERT_ALWAYS(aMaxLength>=0,Fault(EEtelFaultMaxDesLengthNegative));
+
+ HEtelBufC16* pH=NULL;
+ TInt size=sizeof(HEtelBufC16)+(aMaxLength*sizeof(TUint16));
+ if (aHeap!=NULL)
+ pH=(HEtelBufC16*)aHeap->AllocLC(size);
+ else
+ pH=(HEtelBufC16*)User::AllocLC(size);
+ pH->iLength=aMaxLength;
+ pH->iHeap=aHeap;
+ pH->Des().SetLength(aMaxLength);
+ return(pH);
+ }
+
+TPtr16 HEtelBufC16::Des()
+ {
+ TUint16* ptr=reinterpret_cast<TUint16*> ((reinterpret_cast<TInt> (this)+sizeof(HEtelBufC16)));
+ return TPtr16(ptr,iLength,iLength);
+ }
+
+const TUint16* HEtelBufC16::Ptr() const
+ {
+ return reinterpret_cast<const TUint16*> ((reinterpret_cast<TInt> (this)+sizeof(HEtelBufC16)));
+ }
+
+void HEtelBufC16::operator delete(TAny* aPtr)
+//
+// overloaded delete - deletes from priority client heap if iHeap is not NULL
+//
+ {
+ RHeap* heap=NULL;
+ if (aPtr!=NULL)
+ heap=reinterpret_cast<HEtelBufC16*> (aPtr)->iHeap;
+
+ if (heap!=NULL)
+ reinterpret_cast<HEtelBufC16*> (aPtr)->iHeap->Free(aPtr);
+ else
+ User::Free(aPtr);
+ }
+
+//
+// TDataPackage class contains the data pointers to be passed down to the TSY in ExtFunc()
+//
+TDataPackage::TDataPackage()
+ : iDes1(NULL),iDes2(NULL),iDes1u(NULL),iDes2u(NULL)
+ {}
+TDataPackage::TDataPackage(TDes8* aDes1, TDes8* aDes2)
+ : iDes1(aDes1),iDes2(aDes2),iDes1u(NULL),iDes2u(NULL)
+ {}
+
+TDataPackage::TDataPackage(TDes16* aDes1, TDes16* aDes2)
+ : iDes1(NULL),iDes2(NULL),iDes1u(aDes1),iDes2u(aDes2)
+ {}
+TDataPackage::TDataPackage(TDes8* aDes1, TDes16* aDes2)
+ : iDes1(aDes1),iDes2(NULL),iDes1u(NULL),iDes2u(aDes2)
+ {}
+
+EXPORT_C TDes8* TDataPackage::Des1n() const
+ {
+ __ASSERT_ALWAYS(iDes1,Fault(EEtelFaultDes1DoesNotExist));
+ return iDes1;
+ }
+EXPORT_C TDes8* TDataPackage::Des2n() const
+ {
+ __ASSERT_ALWAYS(iDes2,Fault(EEtelFaultDes2DoesNotExist));
+ return iDes2;
+ }
+EXPORT_C TDes16* TDataPackage::Des1u() const
+ {
+ __ASSERT_ALWAYS(iDes1u,Fault(EEtelFaultDes1DoesNotExist));
+ return iDes1u;
+ }
+EXPORT_C TDes16* TDataPackage::Des2u() const
+ {
+ __ASSERT_ALWAYS(iDes2u,Fault(EEtelFaultDes2DoesNotExist));
+ return iDes2u;
+ }
+
+EXPORT_C TAny* TDataPackage::Ptr1() const
+ {
+ if (iDes1u)
+ return reinterpret_cast<TAny*> (const_cast<TUint16*> (iDes1u->Ptr()));
+ if (iDes1)
+ return reinterpret_cast<TAny*> (const_cast<TUint8*> (iDes1->Ptr()));
+ return NULL;
+ }
+
+EXPORT_C TAny* TDataPackage::Ptr2() const
+ {
+ if (iDes2u)
+ return reinterpret_cast<TAny*> (const_cast<TUint16*> (iDes2u->Ptr()));
+ if (iDes2)
+ return reinterpret_cast<TAny*> (const_cast<TUint8*> (iDes2->Ptr()));
+ return NULL;
+ }
+
+/**
+* This helper utility returns the type of a packaged data structure.
+* It is very useful to know which type of variables (unicode or narrow) a package contains
+* before passing it to any functions. It could also help to provide more generic implementation
+* on the TSY, that currently assumes knowledge of the way the data are packaged.
+*
+*/
+
+EXPORT_C TDataPackage::TDataPackageType TDataPackage::Type() const
+ {
+ if(iDes1 && iDes2)
+ return EPackage1n2n;
+ else if (iDes1u && iDes2u)
+ return EPackage1u2u;
+ else if (iDes1 && iDes2u)
+ return EPackage1n2u;
+ else if (iDes1 && !iDes2)
+ return EPackage1n;
+ else if (iDes1u && !iDes2u)
+ return EPackage1u;
+ else
+ return EPackageUnknown;
+ }
+
+/**
+Non-exported static factory constructor. This class should only be instantiated by Etel server.
+*/
+CFaxSharedFileHandles* CFaxSharedFileHandles::NewL(const RMessage2& aMsg)
+ {
+ CFaxSharedFileHandles* obj = new(ELeave) CFaxSharedFileHandles();
+ CleanupStack::PushL(obj);
+ obj->ConstructL(aMsg);
+ CleanupStack::Pop(obj);
+ return obj;
+ }
+
+/**
+Destructor.
+
+@publishedPartner
+@released
+*/
+EXPORT_C CFaxSharedFileHandles::~CFaxSharedFileHandles()
+ {
+ iFile.Close();
+ }
+
+/**
+Default constructor.
+*/
+CFaxSharedFileHandles::CFaxSharedFileHandles()
+ {
+ //empty
+ }
+
+/**
+Reference to an adopted file.
+
+@return RFile& Reference to an open file handle.
+@publishedPartner
+@released
+*/
+EXPORT_C RFile& CFaxSharedFileHandles::File()
+ {
+ return iFile;
+ };
+
+/**
+Adopt the file during construction.
+*/
+void CFaxSharedFileHandles::ConstructL(const RMessage2& aMsg)
+ {
+ //Use the RMessage2 and EKA2 adopt functions to adopt the file. Slots 0 & 2 contain relevant session handles.
+ User::LeaveIfError(iFile.AdoptFromClient(aMsg, 0, 2));
+ }