diff -r 000000000000 -r a41df078684a kernel/eka/ewsrv/ws_main.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/kernel/eka/ewsrv/ws_main.cpp Mon Oct 19 15:55:17 2009 +0100 @@ -0,0 +1,2198 @@ +// Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies). +// All rights reserved. +// This component and the accompanying materials are made available +// under the terms of the License "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: +// e32\ewsrv\ws_main.cpp +// +// + +#include "ws_std.h" +#include +#include +#include +#include +#ifdef __WINS__ +#include +#endif + +GLREF_D CKeyTranslator *KeyTranslator; +GLREF_D CKeyRepeat* KeyRepeat; + +// password notifier support functions +LOCAL_C void RenderPassword(RConsole *aCon, TInt aPWLeft, const TDesC& aPW); + +_LIT(KShellProcessName, "ESHELL"); +_LIT(KShellCommandLine, "/p"); + +// +// class CKeyRepeat +// + +CKeyRepeat::CKeyRepeat(TInt aPriority) : CTimer(aPriority) +// +// Constructor. Set default repeat delay and rate +// + { + iDelay=EDefaultKeyRepeatDelay; + iRate=EDefaultKeyRepeatRate; + } + +void CKeyRepeat::ConstructL() + { + + CTimer::ConstructL(); + CActiveScheduler::Add(this); + } + +void CKeyRepeat::RunL() +// +// Send a repeat keypress to the window +// + { + + After(iRate); + CWsWindow::KeyPress(iKeyData); + } + +void CKeyRepeat::Request(TKeyData& aKeyData) +// +// Request a repeat event +// + { + + iKeyData=aKeyData; + Cancel(); + After(iDelay); + } + +void CKeyRepeat::SetRepeatTime(TInt aDelay,TInt aRate) + { + + iDelay=aDelay; + iRate=aRate; + } + +void CKeyRepeat::RepeatTime(TInt& aDelay,TInt& aRate) + { + + aDelay=iDelay; + aRate=iRate; + } + +// +// class CWsSession +// + +CWsSession::CWsSession() + { + iTestFast = (UserSvr::DebugMask(2)&0x00000002) ? 1 : 0; + } + +CWsSession::~CWsSession() +// +// Destructor +// + { + + delete iWindow; + } + +// +// class CWsServer +// + +void CWsServer::New() +// +// Create a new CWsServer. +// + { + + CWsServer *pS=new CWsServer(EPriority); + __ASSERT_ALWAYS(pS!=NULL,Fault(ECreateServer)); + pS->SetPinClientDescriptors(EFalse); // don't pin because client interface can't cope with errors if pin fails under real or simulated OOM + TInt r=pS->Start(KE32WindowServer); + __ASSERT_ALWAYS(r==KErrNone,Fault(EStartServer)); + RProcess::Rendezvous(KErrNone); + + } + +CWsServer::CWsServer(TInt aPriority) +// +// Constructor. +// + : CServer2(aPriority) + { + } + +CSession2* CWsServer::NewSessionL(const TVersion& aVersion,const RMessage2&) const +// +// Create a new client for this server. +// + { + + TVersion v(KW32MajorVersionNumber,KW32MinorVersionNumber,KE32BuildVersionNumber); + TBool r=User::QueryVersionSupported(v,aVersion); + if (!r) + User::Leave(KErrNotSupported); + return new(ELeave) CWsSession; + } + +void CWsSession::ServiceL(const RMessage2& aMessage) +// +// Handle messages for this session. +// + { + + iCurMsg = aMessage; + CWsWindow::WaitOnService(); + CWsWindow* pW=iWindow; + TInt r=EPrematureOperation; + TBool delayCompletion=EFalse; + switch (aMessage.Function()) + { + case EConsoleCreate: + { + if (pW) + { + delete pW; + iWindow=NULL; + } + pW=new CWsWindow; + if (!pW) + { + r=EWindowOutOfMemory; + break; + } + iWindow=pW; + pW->iAllowResize=ETrue; + pW->iIsVisible=ETrue; + pW->iOnTop=EFalse; + pW->SetCursorHeight(50); + pW->iKQueue.SetOffset(_FOFF(SWsKey,iLink)); + break; + } + case EConsoleSet: + { + if (!pW) + { + pW=new(ELeave) CWsWindow; + iWindow=pW; + pW->iAllowResize=ETrue; + pW->iIsVisible=ETrue; + pW->iOnTop=EFalse; + pW->SetCursorHeight(50); + pW->iKQueue.SetOffset(_FOFF(SWsKey,iLink)); + } + pW->iAllowSlide=ETrue; + TFileName name; + iCurMsg.ReadL(0, name); + pW->iTitle=name; + TPckgBuf size; + iCurMsg.ReadL(1, size); + TRAP(r,pW->CreateL(size())); + if (r != KErrNone) + { + delete pW; + iWindow=NULL; + } + break; + } + case EConsoleClearScreen: + { + if (pW) + { + pW->Clear(); + r=KErrNone; + } + break; + } + case EConsoleClearToEndOfLine: + { + if (pW) + { + pW->ClearToEndOfLine(); + r=KErrNone; + } + break; + } + case EConsoleSetTitle: + { + if (pW) + { + TFileName name; + iCurMsg.ReadL(0, name); + pW->SetTitle(name); + r=KErrNone; + } + break; + } + case EConsoleSetSize: + { + if (pW) + { + TPckgBuf size; + iCurMsg.ReadL(0, size); +// pW->SetSize(size()); +// r=KErrNone; + r=KErrNotSupported; + } + break; + } + case EConsoleSetWindowPosAbs: + { + if (pW) + { + TPckgBuf point; + iCurMsg.ReadL(0, point); + pW->SetWindowPosAbs(point()); + r=KErrNone; + } + break; + } + case EConsoleSetCursorHeight: + { + if (pW) + { + pW->SetCursorHeight(aMessage.Int0()); + r=KErrNone; + } + break; + } + case EConsoleSetCursorPosAbs: + { + if (pW) + { + TPckgBuf point; + iCurMsg.ReadL(0, point); + pW->SetCursorPosAbs(point()); + r=KErrNone; + } + break; + } + case EConsoleSetCursorPosRel: + { + if (pW) + { + TPckgBuf point; + iCurMsg.ReadL(0, point); + pW->SetCursorPosRel(point()); + r=KErrNone; + } + break; + } + case EConsoleCursorPos: + { + if (pW) + { + TPckgBuf point; + point()=pW->CursorPosition(); + aMessage.WriteL(0,point); + r=KErrNone; + } + break; + } + case EConsoleSize: + { + if (pW) + { + TPckgBuf size; + size()=pW->Size(); + aMessage.WriteL(0,size); + r=KErrNone; + } + break; + } + case EConsoleScreenSize: + { + if (pW) + { + TPckgBuf size; + size()=CWsWindow::ScreenSize; + aMessage.WriteL(0,size); + r=KErrNone; + } + break; + } + case EConsoleControl: + { + if (pW) + { + TBool indicator=ETrue; + TInt offset=0; + TBuf<0x100> b; + do + { + iCurMsg.ReadL(0,b,offset); + for (const TText* pB=b.Ptr();pBControlScrollBars(indicator); + break; + case 'W': + pW->ControlWrapLock(indicator); + break; + case 'P': + pW->ControlPointerEvents(indicator); + break; + case 'L': + pW->ControlScrollLock(indicator); + break; + case 'V': + pW->ControlVisibility(indicator); + break; + case 'C': + pW->ControlCursorRequired(indicator); + break; + case 'M': + pW->ControlMaximised(indicator); + break; + case 'N': + pW->ControlNewLineMode(indicator); + break; + case 'O': + pW->ControlOnTop(indicator); + break; + case 'I': + pW->ControlInformAllMouse(indicator); + break; + case 'R': + pW->ControlRawEventMode(indicator); + break; + case 'A': + pW->ControlAllowResize(indicator); + } + } + offset+=b.Length(); + } + while (b.Length()==b.MaxLength()); + r=KErrNone; + } + break; + } + case EConsoleWrite: + { + if (pW) + { + switch(iTestFast) + { + case 0: + { + TInt offset=0; + TBuf<0x100> b; + do + { + iCurMsg.ReadL(0,b,offset); + pW->Write(b); + offset+=b.Length(); + } + while (b.Length()==b.MaxLength()); + pW->WriteDone(); + } + r=KErrNone; + break; + + case 1: + { + pW->Write(_L("Output suppressed because TESTFAST mode is set...")); + pW->WriteDone(); + ++iTestFast; + } + r=KErrNone; + break; + + default: + r=KErrNone; + break; + } + } + break; + } + case EConsoleRead: + { + if (pW) + { + if (pW->EnqueReadRequest(aMessage)) + { + delayCompletion=ETrue; + r=KErrNone; + } + else + r=EDoubleReadRequest; + } + break; + } + case EConsoleReadCancel: + { + if (pW) + { + pW->DequeReadRequest(); + r=KErrNone; + } + break; + } + case EConsoleDestroy: + { + if (pW) + { + delete pW; + iWindow=NULL; + r=KErrNone; + } + break; + } + case EConsoleSetMode: + { + r=CWsWindow::SetMode((TVideoMode)aMessage.Int0()); + break; + } + case EConsoleSetPaletteEntry: + { + CWsWindow::ScreenDriver->SetPaletteEntry((TColorIndex)aMessage.Int0(),(TUint8)aMessage.Int1(),(TUint8)aMessage.Int2(),(TUint8)aMessage.Int3()); + pW->Redraw(); + r=KErrNone; + break; + } + case EConsoleGetPaletteEntry: + { + TUint8 r,g,b; + TPckgBuf red,green,blue; + CWsWindow::ScreenDriver->GetPaletteEntry((TColorIndex)aMessage.Int0(),r,g,b); + red()=r; green()=g; blue()=b; + aMessage.WriteL(1,red); + aMessage.WriteL(2,green); + aMessage.WriteL(3,blue); + } + r=KErrNone; + break; + case EConsoleSetTextColors: + { + if(pW) + { + pW->iFgColor=(TColorIndex)aMessage.Int0(); + pW->iBgColor=(TColorIndex)aMessage.Int1(); + } + r=KErrNone; + break; + } + case EConsoleSetUIColors: + { + CWsWindow::WindowBgColor=(TColorIndex)aMessage.Int0(); + CWsWindow::BorderColor=(TColorIndex)aMessage.Int1(); + CWsWindow::ScreenColor=(TColorIndex)aMessage.Int2(); + CWsWindow::ChangeUIColors(); + r=KErrNone; + break; + } + case EConsoleSetTextAttribute: + { + if(pW) + pW->SetTextAttribute((TTextAttribute)aMessage.Int0()); + r=KErrNone; + break; + } + default: + r=KErrNotSupported; + } + if (!delayCompletion) + aMessage.Complete(r); + CWsWindow::SignalService(); + } + +void CWsSession::ServiceError(const RMessage2& aMessage,TInt aError) + { + if (!aMessage.IsNull()) + { + if (aError>0) + { + aMessage.Panic(_L("WServ panic"),aError); + } + else + { + aMessage.Complete(aError); + } + } + } + +CWsServer::~CWsServer() +// +// Destructor +// + { + } + +// +// class CEvent +// + +void CEvent::New() +// +// Create the CEvent active object. +// + { + + CEvent *pE=new CEvent(EPriority); + __ASSERT_ALWAYS(pE!=NULL,Fault(ECreateEvent)); + pE->CaptureKeys=new CCaptureKeys(); + __ASSERT_ALWAYS(pE->CaptureKeys!=NULL,Fault(ECreateEvent)); + + pE->CaptureKeys->Construct(); + + CActiveScheduler::Add(pE); + UserSvr::CaptureEventHook(); + pE->Request(); + } + +CEvent::~CEvent() +// +// Destroy the CEvent active object +// + { + + Cancel(); + } + +#pragma warning( disable : 4705 ) // statement has no effect +CEvent::CEvent(TInt aPriority) +// +// Constructor +// + : CActive(aPriority) + { + } +#pragma warning( default : 4705 ) + +void CEvent::Request() +// +// Issue a request for the next event. +// + { + + UserSvr::RequestEvent(iEvent,iStatus); + SetActive(); + } + +void CEvent::DoCancel() +// +// Cancel a pending event. +// + { + + UserSvr::RequestEventCancel(); + } + +void CEvent::RunL() +// +// Event has completed. +// + { + + if (CWsWindow::RawEventMode()) + { + KeyRepeat->Cancel(); + CWsWindow::QueueRawEvent(iEvent.Event()); + Request(); + return; + } + switch(iEvent.Event().Type()) + { + case TRawEvent::ERedraw: + CWsWindow::Redraw(); + break; + case TRawEvent::EButton1Down: + if(!CWsWindow::MouseIsCaptured) + { + CWsWindow::MouseMove(iEvent.Event().Pos()); + CWsWindow::MouseLeftButton(); + } + else + CWsWindow::InformTopMouse(iEvent.Event().Pos()); + break; + case TRawEvent::EButton1Up: + if(!CWsWindow::MouseIsCaptured) + { + CWsWindow::MouseMove(iEvent.Event().Pos()); + CWsWindow::MouseLeftButtonUp(); + } + break; + case TRawEvent::EButton2Down: + break; + case TRawEvent::EButton2Up: + break; + case TRawEvent::EButton3Down: + break; + case TRawEvent::EButton3Up: + break; + case TRawEvent::EPointerMove: + CWsWindow::MouseMove(iEvent.Event().Pos()); + break; + case TRawEvent::EInactive: + KeyRepeat->Cancel(); + break; + case TRawEvent::EActive: + break; + case TRawEvent::EUpdateModifiers: + KeyTranslator->UpdateModifiers(iEvent.Event().Modifiers()); + break; + case TRawEvent::EKeyDown: + { + TKeyData keyData; + if (KeyTranslator->TranslateKey(iEvent.Event().ScanCode(), EFalse,*CaptureKeys,keyData)) + CWsWindow::KeyPress(keyData); + if (keyData.iModifiers&EModifierAutorepeatable) + KeyRepeat->Request(keyData); + break; + } + case TRawEvent::EKeyUp: + { + TKeyData keyData; + KeyRepeat->Cancel(); + if (KeyTranslator->TranslateKey(iEvent.Event().ScanCode(), ETrue,*CaptureKeys,keyData)) + CWsWindow::KeyPress(keyData); + break; + } + case TRawEvent::ESwitchOn: + case TRawEvent::ECaseOpen: + HAL::Set(HAL::EDisplayState, 1); + { + RDmDomainManager mgr; + TInt r = mgr.Connect(); + if (r != KErrNone) + User::Panic(_L("EWSRV SwitchOn0"), r); + TRequestStatus status; + mgr.RequestDomainTransition(KDmIdUiApps, EPwActive, status); + User::WaitForRequest(status); + if (status.Int() != KErrNone) + User::Panic(_L("EWSRV SwitchOn1"), status.Int()); + mgr.Close(); + } + break; + case TRawEvent::EPointerSwitchOn: +#if defined(_DEBUG) + User::Beep(440,250000); +#endif + break; + case TRawEvent::ESwitchOff: + { + RDmDomainManager mgr; + TInt r = mgr.Connect(); + if (r != KErrNone) + User::Panic(_L("EWSRV SwitchOff0"), r); + TRequestStatus status; + mgr.RequestSystemTransition(EPwStandby, status); + User::WaitForRequest(status); + if (status.Int() != KErrNone) + User::Panic(_L("EWSRV SwitchOff1"), status.Int()); + mgr.Close(); + } + break; + case TRawEvent::ECaseClose: + { + RDmDomainManager mgr; + TInt r = mgr.Connect(); + if (r != KErrNone) + User::Panic(_L("EWSRV CaseClosed"), r); + TRequestStatus status; + mgr.RequestDomainTransition(KDmIdUiApps, EPwStandby, status); + User::WaitForRequest(status); + if (status.Int() != KErrNone) + User::Panic(_L("EWSRV CaseClosed1"), status.Int()); + mgr.Close(); + } + HAL::Set(HAL::EDisplayState, 0); + break; + case TRawEvent::ENone: + break; + default: + break; + } + Request(); + } + +LOCAL_C void RenderPassword(RConsole *aCon, TInt aPWLeft, const TDesC& aPW) +// pre: aCon points to a console being used to read a password. +// aPWLeft is the column number from which the left brace should be drawn. +// aPasswd is a valid password. +// post: the password is rendered onto the console and followed by a '#' and +// padding spaces. Everything is enclosed in a pair of square brackets. + { + aCon->SetCursorPosAbs(TPoint(aPWLeft, 3)); + aCon->Write(_L("[")); + aCon->Write(aPW); + aCon->Write(_L("#")); + + TInt i; + for (i = 0; i < KMaxMediaPassword - aPW.Length(); i++) + { + aCon->Write(_L(" ")); + } + + aCon->Write(_L("]")); + } + + +void CNotifierSession::RunPasswordWindowL(const RMessage2 &aMsg) +// +// Eight unicode chars are mapped to (up to) sixteen bytes. Remainder of array is +// zeroed. Message is completed in CNotifierSession::ServiceL(). +// + { + // local copies of dialog data, 5 * (8 + 32 * 2) bytes + TBuf<0x20> line1, line2, unlockBtn, storeBtn, cancelBtn; + line1.Copy(_L("Password notifier")); + line2.Copy(_L("Enter password")); + unlockBtn.Copy(_L("Unlock")); + storeBtn.Copy(_L("Store")); + cancelBtn.Copy(_L("Cancel")); + + TPckgBuf reply; + + // Format the console window. + + const TInt KPasswordBarLen(1 + KMaxMediaPassword + 1 + 1); + const TInt KButtonBarLen( + 1 + unlockBtn.Length() + 1 + + 1 + 1 + cancelBtn.Length() + 1 + + 1 + 1 + storeBtn.Length() + 1); + + // Work out width of window. + // (Buttons are enclosed by angle brackets and separted by a space.) + // (Password is followed by '#' and delimited by square brackets.) + // If KButtonBarLen is at least as long as any other line then it will write + // to the bottom right corner and cause the console to scroll. To counter + // this, an extra padding character is added if necessary. + + TInt width; + width = Max(line1.Length(), line2.Length()); + width = Max(width, KPasswordBarLen); + width = KButtonBarLen >= width ? KButtonBarLen + 1: width; + + // Create the window and render its contents. + + RConsole con; + con.Create(); + con.Control(_L("-Visible")); + TInt r = con.Init(_L(""), TSize(width, 2 + 1 + 1 + 1 + 1)); + if (KErrNone != r) + { + PanicClient(aMsg, ENotifierPanicPasswordWindow); + User::Leave(KErrGeneral); + } + con.Control(_L("+Max -Cursor -AllowResize +OnTop")); + + con.SetCursorPosAbs(TPoint(0, 0)); + con.Write(line1); + con.SetCursorPosAbs(TPoint(0, 1)); + con.Write(line2); + const TInt KPasswordLeft((width - KPasswordBarLen) / 2); + con.SetCursorPosAbs(TPoint(KPasswordLeft, 3)); + con.Write(_L("[# ]")); + con.SetCursorPosAbs(TPoint((width - KButtonBarLen) / 2, 5)); + con.Write(_L("<")); + con.Write(unlockBtn); + con.Write(_L("> <")); + con.Write(storeBtn); + con.Write(_L("> <")); + con.Write(cancelBtn); + con.Write(_L(">")); + + // Allow the user to edit the password until they either press enter or escape. + + TBool done(EFalse); + TBuf pw; + pw.Zero(); + TMediaPswdNotifyExitMode em(EMPEMUnlock); // avoid VC warning C4701 (used w/o init). + + const TInt sendInfoLen = User::LeaveIfError(aMsg.GetDesLength(1)); + + if (sendInfoLen == sizeof(TMediaPswdSendNotifyInfoV1Debug)) + { + // debug mode - wait for specified period and close notifier + + TPckgBuf sendDbg; + aMsg.ReadL(1, sendDbg); + if (sendDbg().iSleepPeriod >= 0) + User::After(sendDbg().iSleepPeriod); + else + { + TTime now; + now.HomeTime(); + TInt64 seed = now.Int64(); + User::After(Math::Rand(seed) % -(sendDbg().iSleepPeriod)); + } + + reply().iEM = sendDbg().iEM; + Mem::Copy(reply().iPW, sendDbg().iPW, KMaxMediaPassword); + } + else + { + RenderPassword(&con, KPasswordLeft, pw); + do + { + TConsoleKey key; + + con.Read(key); + TInt keyCode = key.Code(); + + switch (keyCode) + { + case EKeyEscape: + em = EMPEMCancel; + done = ETrue; + break; + + case EKeyEnter: + em = EMPEMUnlock; + done = ETrue; + break; + + case EKeySpace: + em = EMPEMUnlockAndStore; + done = ETrue; + break; + + case EKeyBackspace: + if (pw.Length() > 0) + { + pw.SetLength(pw.Length() - 1); + RenderPassword(&con, KPasswordLeft, pw); + } + break; + + default: // interpret other keys as pw contents + TChar ch(keyCode); + // unicode encoding, so number of password characters is half byte length + if (ch.IsPrint() && pw.Length() < KMaxMediaPassword / 2) + { + pw.Append(ch); + RenderPassword(&con, KPasswordLeft, pw); + } + break; + } + } while (! done); + + // Fill the TMediaPswdReplyNotifyInfoV1 structure. + + if (em == EMPEMUnlock || em == EMPEMUnlockAndStore) + { + const TInt byteLen = pw.Length() * 2; + + // zero entire array; and then copy in valid section of TMediaPassword, + // not converting Unicode to ASCII. + TPtr8 pt8(reply().iPW, KMaxMediaPassword); // length = 0 + pt8.FillZ(KMaxMediaPassword); // length = KMaxMediaPassword + pt8.Zero(); // length = 0 + // length = byteLen + pt8.Copy(reinterpret_cast(pw.Ptr()), byteLen); + } + + // Set exit mode to tell user how dialog handled. + + reply().iEM = em; + } // else (sendInfoLen == sizeof(TMediaPswdSendNotifyInfoV1Debug)) + + con.Destroy(); + + aMsg.WriteL(2, reply); + } + +// +// class MNotifierBase2 +// + +void MNotifierBase2::SetManager(MNotifierManager* aManager) + { + iManager=aManager; + } + +// +// class CNotifierServer +// + +_LIT(__NOTIFIER_SERVER,"TextNotifierSrvr"); + +CNotifierServer* CNotifierServer::NewL() + { + CNotifierServer* server=new(ELeave) CNotifierServer(200); + CleanupStack::PushL(server); + server->ConstructL(); + server->StartL(__NOTIFIER_NAME); + CleanupStack::Pop(); // server + return server; + } + +CNotifierServer::~CNotifierServer() + { + SetIsExiting(); + delete iManager; + } + +void CNotifierServer::SetIsExiting() + { + iExiting=ETrue; + } + +TBool CNotifierServer::IsExiting() const + { + return iExiting; + } + +CNotifierServer::CNotifierServer(TInt aPriority) + : CServer2(aPriority) + {} + +void CNotifierServer::ConstructL() + { + iManager=CNotifierManager::NewL(); + RFs fs; + User::LeaveIfError(fs.Connect()); + CleanupClosePushL(fs); + iManager->RegisterL(fs); + CleanupStack::PopAndDestroy(); // fs.Close() + } + +CSession2* CNotifierServer::NewSessionL(const TVersion &aVersion,const RMessage2&) const + { + TVersion v(1,0,0); // !! liaise with E32 + if (!User::QueryVersionSupported(v,aVersion)) + User::Leave(KErrNotSupported); + return new(ELeave) CNotifierSession(*this); + } + +// +// class CNotifierSession +// + +CNotifierSession::CNotifierSession(const CNotifierServer& aServer) + { + iServer=&aServer; + iClientId=(TInt)this; + } + +CNotifierSession::~CNotifierSession() + { + const CNotifierServer* server=static_cast(Server()); + if (!server->IsExiting()) + { + server->Manager()->HandleClientExit(iClientId); + } + } + +void CNotifierSession::ServiceL(const RMessage2 &aMessage) + { + TBool completeMessage=ETrue; + switch (aMessage.Function()) + { + case ENotifierNotify: + DisplayAlertL(aMessage); + break; + case ENotifierNotifyCancel: + // do nothing - this server doesn't support cancelling RNotifier::Notify - the client will just have to wait + break; + case ENotifierInfoPrint: + DisplayInfoMsgL(aMessage); + break; + case EStartNotifier: + DoStartNotifierL(aMessage); + break; + case ECancelNotifier: + iServer->Manager()->NotifierCancel(TUid::Uid(aMessage.Int0())); + break; + case EUpdateNotifierAndGetResponse: + case EUpdateNotifier: + DoUpdateNotifierL(aMessage); + break; + case EStartNotifierAndGetResponse: + { + if (aMessage.Int0()==KMediaPasswordNotifyUid) + { + RunPasswordWindowL(aMessage); + } + else + { + TBool cleanupComplete=ETrue; + StartNotifierAndGetResponseL(aMessage,cleanupComplete); + // if the plug-in starts successfully, it has + // responsibility for completing the message (either + // synchronously or asynchronously) + completeMessage=EFalse; + } + } + break; + default: + aMessage.Complete(KErrNotSupported); + break; + } + if (completeMessage && !aMessage.IsNull()) + { + aMessage.Complete(KErrNone); + } + } + +void CNotifierSession::DisplayAlertL(const RMessage2& aMessage) + { + const TInt lengthOfCombinedBuffer=User::LeaveIfError(aMessage.GetDesLength(1)); + const TInt lengthOfLine1=(STATIC_CAST(TUint,aMessage.Int2())>>16); + const TInt lengthOfLine2=(aMessage.Int2()&KMaxTUint16); + const TInt lengthOfBut1=(STATIC_CAST(TUint,aMessage.Int3())>>16); + const TInt lengthOfBut2=(aMessage.Int3()&KMaxTUint16); + if (lengthOfCombinedBuffer!=lengthOfLine1+lengthOfLine2+lengthOfBut1+lengthOfBut2) + { + PanicClient(aMessage,ENotifierPanicInconsistentDescriptorLengths); + return; + } + HBufC* const combinedBuffer=HBufC::NewLC(lengthOfCombinedBuffer); + {TPtr combinedBuffer_asWritable(combinedBuffer->Des()); + aMessage.ReadL(1,combinedBuffer_asWritable);} + const TPtrC line1(combinedBuffer->Left(lengthOfLine1)); + const TPtrC line2(combinedBuffer->Mid(lengthOfLine1,lengthOfLine2)); + const TPtrC but1(combinedBuffer->Mid(lengthOfLine1+lengthOfLine2,lengthOfBut1)); + const TPtrC but2(combinedBuffer->Mid(lengthOfLine1+lengthOfLine2+lengthOfBut1,lengthOfBut2)); + TInt buttons, len, offset; + if (lengthOfBut2==0) + { + buttons=1; + len=lengthOfBut1+2; + } + else + { + buttons=2; + len=lengthOfBut1+lengthOfBut2+5; + } + if (lengthOfLine1>len) + len=lengthOfLine1; + if (lengthOfLine2>len) + len=lengthOfLine2; + RConsole con; + con.Create(); + TSize scsz; + con.ScreenSize(scsz); + con.Control(_L("-Visible")); + TInt ww=Min(len,scsz.iWidth-4); + TInt wh=3; + if ((lengthOfBut1+lengthOfBut2+5)>ww) + wh++; + if (lengthOfLine1>ww) + wh++; + if (lengthOfLine2>ww) + wh++; + con.Init(_L(""),TSize(ww,wh)); + con.Control(_L("+Max -Cursor -Allowresize +Ontop +Wrap")); + con.Write(line1); + con.SetCursorPosAbs(TPoint(0,1)); + con.Write(line2); + if (buttons==2) + offset=(len-lengthOfBut1-lengthOfBut2-5)/2; + else + offset=(len-lengthOfBut1-2)/2; + con.SetCursorPosAbs(TPoint(offset,2)); + con.Write(_L("<")); + con.Write(but1); + con.Write(_L(">")); + if(buttons==2) + { + con.Write(_L(" <")); + con.Write(but2); + con.Write(_L(">")); + } + + TConsoleKey key; + TInt keycode; + do + { + con.Read(key); + keycode=key.Code(); + } + while((keycode!=EKeyEscape&&keycode!=EKeyEnter&&buttons==2)||(keycode!=EKeyEnter&&buttons==1)); + if(keycode==EKeyEscape) + keycode=0; + else + keycode=1; + con.Destroy(); + aMessage.WriteL(0,TPckgC(keycode)); + CleanupStack::PopAndDestroy(combinedBuffer); + } + +TInt CNotifierSession::InfoPrintThread(TAny* aMessage) + { + TBuf<0x50> des; // 0x50 max size of message + RConsole con; + des=*(TBuf<0x50> *)aMessage; + TInt l=des.Length(); + NotifierSemaphore.Signal(); + con.Create(); + con.Control(_L("-Visible")); + TSize size; + con.ScreenSize(size); + TInt ww=Min(size.iWidth-6,l); + TInt wh=(l+ww-1)/ww; + if (wh==0) + wh=1; + con.Init(_L(""),TSize(ww,wh)); + con.Control(_L("+Maximise")); + con.SetWindowPosAbs(TPoint(size.iWidth-ww-4,1)); + con.Control(_L("+Wrap +Ontop")); + con.Write(des); + + User::After(1300000); + con.Destroy(); + return KErrNone; + } + +void CNotifierSession::DisplayInfoMsgL(const RMessage2& aMessage) + { + TInt r; + TBuf<0x50> des; // 0x50 max size of message lines + aMessage.ReadL(0,des); + RThread thread; + do + { + r=thread.Create(_L("Info Window"),InfoPrintThread,KDefaultStackSize,&User::Allocator(),(TAny*)&des); + if(r==KErrAlreadyExists) + User::After(200000); + } while(r==KErrAlreadyExists); + User::LeaveIfError(r); + thread.Resume(); + NotifierSemaphore.Wait(); + thread.Close(); + } + +void CNotifierSession::DoStartNotifierL(const RMessage2& aMessage) + { + const TUid targetUid={aMessage.Int0()}; + HBufC8* const inputBuffer=HBufC8::NewLC(User::LeaveIfError(aMessage.GetDesLength(1))); + {TPtr8 input(inputBuffer->Des()); + aMessage.ReadL(1,input);} + TPtrC8 output(0,0); + iServer->Manager()->NotifierStartL(targetUid,*inputBuffer,&output,iClientId); + if(aMessage.Int2()) + aMessage.WriteL(2,output); + CleanupStack::PopAndDestroy(inputBuffer); + } + +void CNotifierSession::DoUpdateNotifierL(const RMessage2& aMessage) + { + const TUid targetUid={aMessage.Int0()}; + HBufC8* const inputBuffer=HBufC8::NewLC(User::LeaveIfError(aMessage.GetDesLength(1))); + {TPtr8 input(inputBuffer->Des()); + aMessage.ReadL(1, input);} + HBufC8* const outputBuffer=HBufC8::NewLC(User::LeaveIfError(aMessage.GetDesMaxLength(2))); + {TPtr8 output(outputBuffer->Des()); + iServer->Manager()->NotifierUpdateL(targetUid,*inputBuffer,&output,iClientId);} + aMessage.WriteL(2,*outputBuffer); + CleanupStack::PopAndDestroy(2,inputBuffer); + } + +void CNotifierSession::StartNotifierAndGetResponseL(const RMessage2& aMessage,TBool& aCleanupComplete) + { + const TUid targetUid={aMessage.Int0()}; + HBufC8* const inputBuffer=HBufC8::NewLC(User::LeaveIfError(aMessage.GetDesLength(1))); + {TPtr8 input(inputBuffer->Des()); + aMessage.ReadL(1,input);} + iServer->Manager()->NotifierStartAndGetResponseL(targetUid,*inputBuffer,2,aMessage,iClientId,aCleanupComplete); + CleanupStack::PopAndDestroy(inputBuffer); + } + +void CNotifierSession::PanicClient(const RMessage2& aMessage,TNotifierPanic aCode) + { + aMessage.Panic(__NOTIFIER_SERVER,aCode); + } + +// +// class CNotifierManager +// + +const TInt KNullClientId=0; + +CNotifierManager* CNotifierManager::NewL() + { + CNotifierManager* self=new(ELeave) CNotifierManager; + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +CNotifierManager::~CNotifierManager() + { + if (iObservedList) + { + const TInt count=iObservedList->Count(); + for (TInt ii=0;iiRelease(); + } + delete iObservedList; + } + if (iLibraries) + { + const TInt count=iLibraries->Count(); + for (TInt ii=0;iiFindWildByDir(KNotifierPlugInExt, KNotifierPlugInOldSearchPath, directory); + else +#endif + error=findFile->FindWildByDir(KNotifierPlugInExt, KNotifierPlugInSearchPath, directory); + for (; error!=KErrNotFound; error=findFile->FindWild(directory)) + { + CleanupStack::PushL(directory); + User::LeaveIfError(error); + const TInt numberOfEntries=directory->Count(); + for (TInt i=0; iSetNoWild(entry.iName, &findFile->File(), NULL); // findFile->File() returns a reference rather than an object, therefore taking the address of it is fine + + if (entry.iType[0].iUid==0x10000079) + { + // It's a DLL + if( (entry.iType[1]==KUidTextNotifierPlugInV2)) + { + // Its a notifier... + TPtrC path(fileNameParser->DriveAndPath()); + TPtrC name(fileNameParser->NameAndExt()); + DoAddPlugInL(path,name,entry.iType); + } + } + } + CleanupStack::PopAndDestroy(); // directory + directory=NULL; + } + delete directory; + CleanupStack::PopAndDestroy(2); // fileNameParser and findFile +#ifdef SUPPORT_OLD_PLUGIN_PATH + } +#endif + } + +LOCAL_C void DeleteTemp(TAny* aPtr) + { + CArrayPtr* array=REINTERPRET_CAST(CArrayPtr*,aPtr); + const TInt count=array->Count(); + for (TInt ii=0;iiRelease(); + } + delete array; + } + + + +void CNotifierManager::DoAddPlugInL(const TDesC& aPath,const TDesC& aFileName,const TUidType& aUidType) + { + RLibrary lib; + User::LeaveIfError(lib.Load(aFileName,aPath,aUidType)); + CleanupClosePushL(lib); + iLibraries->AppendL(lib); + CleanupStack::Pop(); // lib + TLibraryFunction libEntry=lib.Lookup(1); + CArrayPtr* array=REINTERPRET_CAST(CArrayPtr*,(libEntry)()); + User::LeaveIfNull(array); + CleanupStack::PushL(TCleanupItem(DeleteTemp,array)); + while (array->Count()>0) + { + MNotifierBase2* notif=(*array)[0]; + { + iObservedList->AppendL(notif); + array->Delete(0); + notif->SetManager(this); + } + MNotifierBase2::TNotifierInfo info=notif->RegisterL(); + if (!iChannelMonitor->AlreadyHasChannel(info.iChannel)) + iChannelMonitor->AddNewChannelL(info.iChannel); + } + CleanupStack::PopAndDestroy(); // array + } + +CNotifierManager::CNotifierManager() + {} + +void CNotifierManager::ConstructL() + { + iObservedList=new(ELeave) CArrayPtrSeg(6); + iLibraries=new(ELeave) CArrayFixFlat(2); + iChannelMonitor=CChannelMonitor::NewL(); + iActivityMonitor=CActivityMonitor::NewL(); + iQueue=CNotifierQueue::NewL(); + } + +struct SActivityCleanup + { + CActivityMonitor* iMonitor; + TUid iNotifier; + TInt iClientId; + }; + +LOCAL_C void CleanupActivityMonitor(TAny* aPtr) + { + SActivityCleanup& cleanup=*REINTERPRET_CAST(SActivityCleanup*,aPtr); + cleanup.iMonitor->Remove(cleanup.iNotifier,cleanup.iClientId); + } + +void CNotifierManager::NotifierStartL(TUid aNotifierUid,const TDesC8& aBuffer,TPtrC8* aResponse,TInt aClientId) + { + TInt result=KErrNotFound; + const TInt count=iObservedList->Count(); + for (TInt ii=0;iiInfo(); + if (info.iUid==aNotifierUid) + { + if (iActivityMonitor->IsNotifierActive(aNotifierUid,info.iChannel)) + { + result=KErrAlreadyExists; + } + else if (info.iPriority>iChannelMonitor->ActivityLevel(info.iChannel)) + { + TUid notifier; + MNotifierBase2::TNotifierPriority priority; + const TBool channelWasActive=iActivityMonitor->IsChannelActive(info.iChannel,notifier,priority); + iActivityMonitor->AddL(info,aClientId); + SActivityCleanup cleanup; + cleanup.iMonitor=iActivityMonitor; + cleanup.iNotifier=aNotifierUid; + cleanup.iClientId=aClientId; + CleanupStack::PushL(TCleanupItem(CleanupActivityMonitor,&cleanup)); + TPtrC8 response(notif->StartL(aBuffer)); + if(aResponse) + aResponse->Set(response); + CleanupStack::Pop(); // cleanup; + if (channelWasActive) + { + for (TInt jj=0;jjInfo(); + if (infoForUpdate.iUid==notifier && infoForUpdate.iChannel==info.iChannel) + { + TRAP_IGNORE(notifForUpdate->UpdateL(KNotifierPaused)); + } + } + } + iChannelMonitor->UpdateChannel(info.iChannel,info.iPriority); + if (result!=ENotExtRequestQueued) + { + result=ENotExtRequestCompleted; + } + } + else + { + if (iQueue->IsAlreadyQueued(info.iUid,info.iChannel)) + { + result=KErrAlreadyExists; + } + else + { + CQueueItem* queueCopy=CQueueItem::NewL(info,aBuffer,aClientId); + CleanupStack::PushL(queueCopy); + iQueue->QueueItemL(queueCopy); + CleanupStack::Pop(); // queueCopy + result=ENotExtRequestQueued; + } + } + } + } + User::LeaveIfError(result); + } + +TInt CNotifierManager::NotifierUpdateL(TUid aNotifierUid,const TDesC8& aBuffer,TDes8* aResponse,TInt aClientId) + { + TInt result=KErrNotFound; + const TInt count=iObservedList->Count(); + for (TInt ii=0;iiInfo(); + if (info.iUid==aNotifierUid) + { + if (iActivityMonitor->IsNotifierActive(aNotifierUid,info.iChannel)) + { + if (!iActivityMonitor->IsClientPresent(aNotifierUid,info.iChannel,aClientId)) + { + iActivityMonitor->AddL(info,aClientId); + } + if (aResponse==NULL) + { + notif->UpdateL(aBuffer); + } + else + { + aResponse->Copy(notif->UpdateL(aBuffer)); + } + } + else + { + ; // not all channels have been started yet so update the queue + } + result=KErrNone; + } + } + return result; + } + +void CNotifierManager::NotifierStartAndGetResponseL(TUid aNotifierUid,const TDesC8& aBuffer,TInt aReplySlot, + const RMessage2& aMessage,TInt aClientId,TBool& aCleanupComplete) + { + NotifierStartAndGetResponseL(aNotifierUid,TUid::Null(),aBuffer,aReplySlot,aMessage,aClientId,aCleanupComplete); + } + +void CNotifierManager::NotifierStartAndGetResponseL(TUid aNotifierUid,TUid aChannelUid,const TDesC8& aBuffer,TInt aReplySlot, + const RMessage2& aMessage,TInt aClientId,TBool& aCleanupComplete) + { + TInt result=KErrNotFound; + const TInt count=iObservedList->Count(); + for (TInt ii=0;iiInfo(); + if (info.iUid==aNotifierUid && (aChannelUid==TUid::Null() || info.iChannel==aChannelUid)) + { + if (iActivityMonitor->IsNotifierActive(aNotifierUid,info.iChannel)) + { + notif->StartL(aBuffer,aReplySlot,aMessage); // asynch notifier can decide whether to support multiple clients + result=KErrNone; + } + else if (info.iPriority>iChannelMonitor->ActivityLevel(info.iChannel)) + { + TUid notifier; + MNotifierBase2::TNotifierPriority priority; + const TBool channelWasActive=iActivityMonitor->IsChannelActive(info.iChannel,notifier,priority); + iActivityMonitor->AddL(info,aClientId); + SActivityCleanup activityCleanup; + activityCleanup.iMonitor=iActivityMonitor; + activityCleanup.iNotifier=aNotifierUid; + activityCleanup.iClientId=aClientId; + CleanupStack::PushL(TCleanupItem(CleanupActivityMonitor,&activityCleanup)); + aCleanupComplete=EFalse; + // IMPORTANT, aMessage needs to be a full RMessage object until suport for V1 notifiers is removed + // I.e. until CNotifierBaseAdaptor is removed + notif->StartL(aBuffer,aReplySlot,aMessage); + CleanupStack::Pop(&activityCleanup); + if (channelWasActive) + { + for (TInt jj=0;jjInfo(); + if (infoForUpdate.iUid==notifier && infoForUpdate.iChannel==info.iChannel) + { + TRAP_IGNORE(notifForUpdate->UpdateL(KNotifierPaused)); + } + } + } + iChannelMonitor->UpdateChannel(info.iChannel,info.iPriority); + result=KErrNone; + } + else + { + if (iQueue->IsAlreadyQueued(info.iUid,info.iChannel)) + { + result=KErrAlreadyExists; + } + else + { + CQueueItem* queueCopy=CQueueItem::NewL(info,aBuffer,aReplySlot,aMessage,aClientId); + CleanupStack::PushL(queueCopy); + iQueue->QueueItemL(queueCopy); + CleanupStack::Pop(queueCopy); + result=ENotExtRequestQueued; + } + } + } + } + User::LeaveIfError(result); + } + +TInt CNotifierManager::NotifierCancel(TUid aNotifierUid) + { + TInt result=KErrNotFound; + const TInt count=iObservedList->Count(); + for (TInt ii=0;iiInfo(); + if (info.iUid==aNotifierUid) + { + notif->Cancel(); + iActivityMonitor->RemoveNotifier(aNotifierUid,info.iChannel); + MNotifierBase2::TNotifierPriority priority=MNotifierBase2::ENotifierPriorityLowest; + TUid notifier; + //check channel activity and get highest priority on channnel + if (iActivityMonitor->IsChannelActive(info.iChannel,notifier,priority)) + { + + //check if priority of a queued item on the same channel is + //greater + MNotifierBase2::TNotifierPriority queuePriority= + (MNotifierBase2::TNotifierPriority)iQueue->GetHighestQueuePriority(info.iChannel); + if (queuePriority>priority) + { + iChannelMonitor->UpdateChannel(info.iChannel,MNotifierBase2::ENotifierPriorityLowest); + CQueueItem* next=iQueue->FetchItem(info.iChannel); + if (next) + { + TUid notif=next->iInfo.iUid; + TRAPD(err,StartFromQueueL(next)); + if (err!=KErrNone) + { + NotifierCancel(notif); + } + } + } + else + { + for (TInt jj=0;jjInfo(); + if (infoForUpdate.iUid==notifier && infoForUpdate.iChannel==info.iChannel) + { + TRAP_IGNORE(notifForUpdate->UpdateL(KNotifierPaused)); + } + } + iChannelMonitor->UpdateChannel(info.iChannel,priority); + } + } + else + { + iChannelMonitor->UpdateChannel(info.iChannel,MNotifierBase2::ENotifierPriorityLowest); + CQueueItem* next=iQueue->FetchItem(info.iChannel); + if (next) + { + TUid notif=next->iInfo.iUid; + TRAPD(err,StartFromQueueL(next)); + if (err!=KErrNone) + { + NotifierCancel(notif); + } + } + } + result=KErrNone; + } + } + return result; + } + +struct SCleanupMessage + { + TBool* iDoCleanup; + RMessage2* iMessage; + }; + +LOCAL_C void CleanupStartAndGetResponse(TAny* aPtr) + { + SCleanupMessage& cleanup=*REINTERPRET_CAST(SCleanupMessage*,aPtr); + if (cleanup.iDoCleanup) + { + cleanup.iMessage->Complete(KErrNoMemory); + } + } + +void CNotifierManager::StartFromQueueL(CQueueItem* aItem) + { + CleanupStack::PushL(aItem); + TPtr8 buffer=aItem->iBuffer->Des(); + if (aItem->iAsynchronous) + { + SCleanupMessage cleanup; + TBool doCleanup=ETrue; + cleanup.iDoCleanup=&doCleanup; + cleanup.iMessage=&aItem->iMessage; + CleanupStack::PushL(TCleanupItem(CleanupStartAndGetResponse,&cleanup)); + // IMPORTANT, aItem->iMessage needs to be a full RMessage object until suport for V1 notifiers is removed + // I.e. until CNotifierBaseAdaptor is removed + NotifierStartAndGetResponseL(aItem->iInfo.iUid,aItem->iInfo.iChannel,buffer,aItem->iReplySlot,aItem->iMessage,aItem->iClientId,doCleanup); + CleanupStack::Pop(&cleanup); + } + else + { + NotifierStartL(aItem->iInfo.iUid,buffer,NULL,aItem->iClientId); + } + CleanupStack::PopAndDestroy(); // aItem + CQueueItem* update=iQueue->FetchItem(aItem->iInfo.iChannel); + while (update) + { + CleanupStack::PushL(update); + NotifierUpdateL(update->iInfo.iUid,*update->iBuffer,NULL,update->iClientId); + CleanupStack::PopAndDestroy(); // update + update=iQueue->FetchItem(aItem->iInfo.iChannel); + } + } + +void CNotifierManager::HandleClientExit(TInt aClientId) + { + TUid notifier=KNullUid; + while (iActivityMonitor->NotifierForClient(notifier,aClientId)) + { + const TInt count=iObservedList->Count(); + for (TInt ii=0;iiInfo().iUid==notifier) + { + NotifierCancel(notifier); + } + } + iActivityMonitor->Remove(notifier,aClientId); + } + iActivityMonitor->RemoveClient(aClientId); + iQueue->RemoveClient(aClientId); + } + +void CNotifierManager::StartNotifierL(TUid aNotifierUid,const TDesC8& aBuffer,TDes8& aResponse) + { + TPtrC8 response(0,0); + NotifierStartL(aNotifierUid,aBuffer, &response,KNullClientId); + aResponse.Copy(response); + } + +void CNotifierManager::CancelNotifier(TUid aNotifierUid) + { + NotifierCancel(aNotifierUid); + } + +void CNotifierManager::UpdateNotifierL(TUid aNotifierUid,const TDesC8& aBuffer,TDes8& aResponse) + { + NotifierUpdateL(aNotifierUid,aBuffer,&aResponse,KNullClientId); + } + +// +// class CChannelMonitor +// + +CChannelMonitor* CChannelMonitor::NewL() + { + CChannelMonitor* self=new(ELeave) CChannelMonitor; + return self; + } + +TBool CChannelMonitor::AlreadyHasChannel(TUid aChannel)const + { + const TInt count=iMonitor.Count(); + for (TInt ii=0;iiConstructL(aClientId); + return self; + } + +CNotifierActivity::~CNotifierActivity() + { + iClientArray.Reset(); + } + +TInt CNotifierActivity::Find(TInt aClientId) const + { + TInt index=KErrNotFound; + const TInt count=iClientArray.Count(); + for (TInt ii=0;iiiClientArray.AppendL(aClientId); + } + } + +void CActivityMonitor::Remove(TUid aNotifierUid,TInt aClientId) + { + const TInt index=Find(aNotifierUid); + if (index!=KErrNotFound) + { + CNotifierActivity* activity=iMonitor[index]; + const TInt clientIndex=activity->Find(aClientId); + if (clientIndex!=KErrNotFound) + { + if (activity->iClientArray.Count()==1) + { + delete activity; + iMonitor.Delete(index); + } + else + { + activity->iClientArray.Delete(index); + } + } + } + } + +void CActivityMonitor::RemoveNotifier(TUid aNotifierUid,TUid aChannel) + { + const TInt index=Find(aNotifierUid,aChannel); + if (index!=KErrNotFound) + { + delete iMonitor[index]; + iMonitor.Delete(index); + } + } + +void CActivityMonitor::RemoveClient(TInt aClientId) + { + TInt ii=0; + while (iiFind(aClientId); + if (index!=KErrNotFound) + { + ptr->iClientArray.Delete(index); + } + if (ptr->iClientArray.Count()==0) + { + iMonitor.Delete(ii); + } + else + { + ++ii; + } + } + } + +TBool CActivityMonitor::IsNotifierActive(TUid aNotifierUid,TUid aChannel) const + { + const TInt index=Find(aNotifierUid,aChannel); + return (index!=KErrNotFound); + } + +TBool CActivityMonitor::IsClientPresent(TUid aNotifierUid,TUid aChannel,TInt aClientId) const + { + TBool found=EFalse; + const TInt index=Find(aNotifierUid,aChannel); + if (index!=KErrNotFound) + { + found=(iMonitor[index]->Find(aClientId)!=KErrNotFound); + } + return found; + } + +TBool CActivityMonitor::IsChannelActive(TUid aChannel,TUid& aNotifier,MNotifierBase2::TNotifierPriority& aHighestPriority) const + { + TBool ret=EFalse; + const TInt count=iMonitor.Count(); + for (TInt ii=0;iiiInfo; + if (info.iChannel==aChannel) + { + ret=ETrue; + if ((MNotifierBase2::TNotifierPriority)info.iPriority>aHighestPriority) + { + aNotifier=info.iUid; + aHighestPriority=(MNotifierBase2::TNotifierPriority)info.iPriority; + } + } + } + return ret; + } + +TBool CActivityMonitor::NotifierForClient(TUid& aNotifierUid,TInt aClientId) const + { + TBool isOnlyClient=EFalse; + aNotifierUid=KNullUid; + const TInt count=iMonitor.Count(); + for (TInt ii=0;iiFind(aClientId)!=KErrNotFound) + { + aNotifierUid=ptr->iInfo.iUid; + isOnlyClient=ptr->iClientArray.Count()==1; + break; + } + } + return isOnlyClient; + } + +CActivityMonitor::CActivityMonitor() + : iMonitor(1) + {} + +TInt CActivityMonitor::Find(TUid aNotifierUid) const + { + TInt index=KErrNotFound; + const TInt count=iMonitor.Count(); + for (TInt ii=0;iiiInfo.iUid==aNotifierUid) + { + index=ii; + break; + } + } + return index; + } + +TInt CActivityMonitor::Find(TUid aNotifierUid,TUid aChannel) const + { + TInt index=KErrNotFound; + const TInt count=iMonitor.Count(); + for (TInt ii=0;iiiInfo.iUid==aNotifierUid && ptr->iInfo.iChannel==aChannel) + { + index=ii; + break; + } + } + return index; + } + +// +// class CQueueItem +// + +CQueueItem* CQueueItem::NewL(const MNotifierBase2::TNotifierInfo& aInfo,const TDesC8& aBuffer, + TInt aReplySlot,const RMessage2& aMessage,TInt aClientId) //Asynchronous + { + CQueueItem* self=new(ELeave) CQueueItem(aInfo); + CleanupStack::PushL(self); + self->ConstructL(aBuffer,aMessage,aClientId,aReplySlot); + CleanupStack::Pop(); // self + return self; + } + +CQueueItem* CQueueItem::NewL(const MNotifierBase2::TNotifierInfo& aInfo,const TDesC8& aBuffer,TInt aClientId) //synchronous + { + CQueueItem* self=new(ELeave) CQueueItem(aInfo); + CleanupStack::PushL(self); + self->ConstructL(aBuffer,aClientId); + CleanupStack::Pop(); // self + return self; + } + +CQueueItem::~CQueueItem() + { + delete iBuffer; + } + +CQueueItem::CQueueItem(const MNotifierBase2::TNotifierInfo& aInfo) + : iInfo(aInfo) + {} + +void CQueueItem::ConstructL(const TDesC8& aBuffer,TInt aClientId) + { + iBuffer=aBuffer.AllocL(); + iClientId=aClientId; + iAsynchronous=EFalse; + } + +void CQueueItem::ConstructL(const TDesC8& aBuffer,const RMessage2& aMessage,TInt aClientId,TInt aReplySlot) + { + iBuffer=aBuffer.AllocL(); + iAsynchronous=ETrue; + iMessage=aMessage; + iClientId=aClientId; + iReplySlot=aReplySlot; + } + +// +// class CNotifierQueue +// + +CNotifierQueue* CNotifierQueue::NewL() + { + CNotifierQueue* self=new(ELeave) CNotifierQueue; + return self; + } + +CQueueItem* CNotifierQueue::FetchItem(TUid aChannel) + { + CQueueItem* result=NULL; + const TInt count=iQueue.Count(); + TInt priority=MNotifierBase2::ENotifierPriorityLowest-1; + TInt index=KErrNotFound; + for (TInt ii=0;iiiInfo.iChannel==aChannel && item->iInfo.iPriority>priority) + { + index=ii; + priority=item->iInfo.iPriority; + result=item; + } + } + if (index!=KErrNotFound) + { + iQueue.Delete(index); + } + return result; + } + +TBool CNotifierQueue::IsAlreadyQueued(TUid aNotifier,TUid aChannel) const + { + TBool ret=EFalse; + const TInt count=iQueue.Count(); + for (TInt ii=0;iiiInfo.iUid==aNotifier && item->iInfo.iChannel==aChannel) + { + ret=ETrue; + break; + } + } + return ret; + } + +void CNotifierQueue::RemoveClient(TInt aClientId) + { + const TInt count=iQueue.Count(); + for (TInt ii=count-1;ii>=0;ii--) + { + CQueueItem* item=iQueue[ii]; + TInt clientId=item->iClientId; + if (clientId==aClientId) + { + iQueue.Delete(ii); + } + } + } + + +TInt CNotifierQueue::GetHighestQueuePriority(TUid aChannel) + { + const TInt count=iQueue.Count(); + TInt priority=MNotifierBase2::ENotifierPriorityLowest-1; + + for (TInt ii=0;iiiInfo.iChannel==aChannel && item->iInfo.iPriority>priority) + { + priority=item->iInfo.iPriority; + } + } + + return priority; + } + + +void CWsActiveScheduler::New() +// +// Create and install the active scheduler. +// + { + + CWsActiveScheduler *pA=new CWsActiveScheduler; + __ASSERT_ALWAYS(pA!=NULL,Fault(ECreateScheduler)); + CActiveScheduler::Install(pA); + } + +void CWsActiveScheduler::Error(TInt) const +// +// Called if any Run() method leaves. +// + { + } + + +TInt NotifierServerThread(TAny*) + { + CTrapCleanup* CleanUpStack=CTrapCleanup::New(); + CWsActiveScheduler::New(); + TRAP_IGNORE(CNotifierServer::NewL()); + CNotifierSession::NotifierSemaphore.Signal(); + CWsActiveScheduler::Start(); + delete CleanUpStack; + return(0); + } + + +_LIT(KLitKeyDataDllNameBase, "EKDATA"); +_LIT(TwoDigExt,".%02d"); + +GLDEF_C TInt E32Main() + { + UserSvr::WsRegisterThread(); + UserSvr::WsRegisterSwitchOnScreenHandling(ETrue); + User::SetProcessCritical(User::ESystemPermanent); + User::SetCritical(User::ESystemPermanent); + + CWsActiveScheduler::New(); + CWsServer::New(); + CWsWindow::New(); + CEvent::New(); + + KeyTranslator=CKeyTranslator::New(); + if (!KeyTranslator) + Fault(ENoKeyboardTranslator); + +// Change keyboard mapping according to information in the HAL +// This code is the same as WSERV + TInt keyboardIndex; + if (HAL::Get(HALData::EKeyboardIndex,keyboardIndex)==KErrNone) + { + TBuf<16> keyDataDllName(KLitKeyDataDllNameBase); + keyDataDllName.AppendFormat(TwoDigExt, keyboardIndex); + KeyTranslator->ChangeKeyData(keyDataDllName); + } + + KeyRepeat=new(ELeave) CKeyRepeat(CKeyRepeat::EKeyRepeatPriority); + TRAPD(r,KeyRepeat->ConstructL()); + if (r!=KErrNone) + User::Panic(_L("KEYREPEAT"),r); + +#ifndef __WINS__ + if (UserSvr::TestBootSequence()) + { + RDebug::Print(_L("WS_MAIN: TestBootSequence=TRUE, not loading ESHELL.EXE")); + } +#else + if (EmulatorAutoRun()) + { // don't start ESHELL if we used a self-bootstrapping EXE + } +#endif + else + { + RProcess shell; + r=shell.Create(KShellProcessName, KShellCommandLine); + __ASSERT_ALWAYS(r==KErrNone,Fault(ECreateShell)); + shell.Resume(); + shell.Close(); + } + + RThread t; + r=CNotifierSession::NotifierSemaphore.CreateLocal(0); + if (r!=KErrNone) + Fault(ECreateNotifierSemaphore); + r=t.Create(_L("NotifierServer"),NotifierServerThread,KDefaultStackSize,0x2000,0x100000,NULL); + if (r!=KErrNone) + Fault(ECreateNotifierThread); + t.Resume(); + CNotifierSession::NotifierSemaphore.Wait(); + + CWsActiveScheduler::Start(); + UserSvr::ReleaseEventHook(); + return(KErrNone); + } +