author | mikek |
Sun, 27 Jun 2010 21:43:55 +0100 | |
branch | GCC_SURGE |
changeset 181 | bd8f1e65581b |
parent 0 | a41df078684a |
permissions | -rw-r--r-- |
// Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies). // All rights reserved. // This component and the accompanying materials are made available // under the terms of 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 <e32hal.h> #include <hal.h> #include <e32math.h> #include <domainmanager.h> #ifdef __WINS__ #include <e32wins.h> #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<TSize> 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<TSize> size; iCurMsg.ReadL(0, size); // pW->SetSize(size()); // r=KErrNone; r=KErrNotSupported; } break; } case EConsoleSetWindowPosAbs: { if (pW) { TPckgBuf<TPoint> 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<TPoint> point; iCurMsg.ReadL(0, point); pW->SetCursorPosAbs(point()); r=KErrNone; } break; } case EConsoleSetCursorPosRel: { if (pW) { TPckgBuf<TPoint> point; iCurMsg.ReadL(0, point); pW->SetCursorPosRel(point()); r=KErrNone; } break; } case EConsoleCursorPos: { if (pW) { TPckgBuf<TPoint> point; point()=pW->CursorPosition(); aMessage.WriteL(0,point); r=KErrNone; } break; } case EConsoleSize: { if (pW) { TPckgBuf<TSize> size; size()=pW->Size(); aMessage.WriteL(0,size); r=KErrNone; } break; } case EConsoleScreenSize: { if (pW) { TPckgBuf<TSize> 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();pB<b.Ptr()+b.Length();pB++) { switch(*pB) { case '+': indicator=ETrue; break; case '-': indicator=EFalse; break; case 'S': pW->ControlScrollBars(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<TUint8> 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<TMediaPswdReplyNotifyInfoV1> 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<KMaxMediaPassword> 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<TMediaPswdSendNotifyInfoV1Debug> 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<const TUint8 *>(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<const CNotifierServer*>(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<TInt>(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;ii<count;ii++) { (*iObservedList)[ii]->Release(); } delete iObservedList; } if (iLibraries) { const TInt count=iLibraries->Count(); for (TInt ii=0;ii<count;ii++) { (*iLibraries)[ii].Close(); } delete iLibraries; } delete iChannelMonitor; delete iActivityMonitor; delete iQueue; } void CNotifierManager::RegisterL(RFs& aFs) { #ifdef SUPPORT_OLD_PLUGIN_PATH TBool old; for(old=0; old<2; old++) { #endif TFindFile* findFile=new(ELeave) TFindFile(aFs); CleanupStack::PushL(findFile); TParse* fileNameParser=new(ELeave) TParse; CleanupStack::PushL(fileNameParser); CDir* directory=NULL; TInt error; #ifdef SUPPORT_OLD_PLUGIN_PATH _LIT(KNotifierPlugInOldSearchPath,"\\system\\tnotifiers\\"); if(old) error=findFile->FindWildByDir(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; i<numberOfEntries; ++i) { const TEntry& entry=(*directory)[i]; fileNameParser->SetNoWild(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<MNotifierBase2>* array=REINTERPRET_CAST(CArrayPtr<MNotifierBase2>*,aPtr); const TInt count=array->Count(); for (TInt ii=0;ii<count;ii++) { (*array)[ii]->Release(); } 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<MNotifierBase2>* array=REINTERPRET_CAST(CArrayPtr<MNotifierBase2>*,(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<MNotifierBase2>(6); iLibraries=new(ELeave) CArrayFixFlat<RLibrary>(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;ii<count;ii++) { MNotifierBase2* notif=(*iObservedList)[ii]; MNotifierBase2::TNotifierInfo info=notif->Info(); 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;jj<count;jj++) { MNotifierBase2* notifForUpdate=(*iObservedList)[ii]; MNotifierBase2::TNotifierInfo infoForUpdate=notifForUpdate->Info(); 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;ii<count;ii++) { MNotifierBase2* notif=(*iObservedList)[ii]; MNotifierBase2::TNotifierInfo info=notif->Info(); 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;ii<count;ii++) { MNotifierBase2* notif=(*iObservedList)[ii]; MNotifierBase2::TNotifierInfo info=notif->Info(); 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;jj<count;jj++) { MNotifierBase2* notifForUpdate=(*iObservedList)[ii]; MNotifierBase2::TNotifierInfo infoForUpdate=notifForUpdate->Info(); 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;ii<count;ii++) { MNotifierBase2* notif=(*iObservedList)[ii]; MNotifierBase2::TNotifierInfo info=notif->Info(); 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;jj<count;jj++) { MNotifierBase2* notifForUpdate=(*iObservedList)[ii]; MNotifierBase2::TNotifierInfo infoForUpdate=notifForUpdate->Info(); 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;ii<count;ii++) { MNotifierBase2* notif=(*iObservedList)[ii]; if (notif->Info().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;ii<count;ii++) { if (iMonitor[ii].iChannel==aChannel) return ETrue; } return EFalse; } TInt CChannelMonitor::ActivityLevel(TUid aChannel) const { const TInt count=iMonitor.Count(); for (TInt ii=0;ii<count;ii++) { TChannelActivity activity=iMonitor[ii]; if (activity.iChannel==aChannel) return activity.iHighestPriorityRunning; } return 0; } void CChannelMonitor::UpdateChannel(TUid aChannel,TInt aLevel) { const TInt count=iMonitor.Count(); for (TInt ii=0;ii<count;ii++) { TChannelActivity& activity=iMonitor[ii]; if (activity.iChannel==aChannel) { activity.iHighestPriorityRunning=aLevel; break; } } } CChannelMonitor::CChannelMonitor() :iMonitor(3) {} // // class CNotifierActivity // CNotifierActivity* CNotifierActivity::NewLC(const MNotifierBase2::TNotifierInfo& aInfo,TInt aClientId) { // static CNotifierActivity* self=new(ELeave) CNotifierActivity(aInfo); CleanupStack::PushL(self); self->ConstructL(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;ii<count;ii++) { TInt clientId=iClientArray[ii]; if (clientId==aClientId) { index=ii; break; } } return index; } CNotifierActivity::CNotifierActivity(const MNotifierBase2::TNotifierInfo& aInfo) : iInfo(aInfo), iClientArray(1) {} void CNotifierActivity::ConstructL(TInt aClientId) { iClientArray.AppendL(aClientId); } // // class CActivityMonitor // CActivityMonitor* CActivityMonitor::NewL() { // static CActivityMonitor* self=new(ELeave) CActivityMonitor(); return self; } CActivityMonitor::~CActivityMonitor() { iMonitor.ResetAndDestroy(); } void CActivityMonitor::AddL(const MNotifierBase2::TNotifierInfo& aInfo,TInt aClientId) { const TInt index=Find(aInfo.iUid,aInfo.iChannel); if (index==KErrNotFound) { CNotifierActivity* activity=CNotifierActivity::NewLC(aInfo,aClientId); iMonitor.AppendL(activity); CleanupStack::Pop(); // activity } else { iMonitor[index]->iClientArray.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 (ii<iMonitor.Count()) { CNotifierActivity* ptr=iMonitor[ii]; TInt index=ptr->Find(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;ii<count;ii++) { MNotifierBase2::TNotifierInfo info=iMonitor[ii]->iInfo; 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;ii<count;ii++) { CNotifierActivity* ptr=iMonitor[ii]; if (ptr->Find(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;ii<count;ii++) { if (iMonitor[ii]->iInfo.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;ii<count;ii++) { CNotifierActivity* ptr=iMonitor[ii]; if (ptr->iInfo.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;ii<count;ii++) { CQueueItem* item=iQueue[ii]; if (item->iInfo.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;ii<count;ii++) { CQueueItem* item=iQueue[ii]; if (item->iInfo.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;ii<count;ii++) { CQueueItem* item=iQueue[ii]; if (item->iInfo.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); }