windowing/windowserver/nga/SERVER/openwfc/WSTOP.CPP
changeset 0 5d03bc08d59c
child 36 01a6848ebfd7
child 163 bbf46f59e123
equal deleted inserted replaced
-1:000000000000 0:5d03bc08d59c
       
     1 // Copyright (c) 1994-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // Top level window server code
       
    15 // 
       
    16 //
       
    17 
       
    18 #include "wstop.h"
       
    19 
       
    20 #include <hal.h>
       
    21 #include <graphics/fbsdefs.h>
       
    22 #include "W32STD.H"
       
    23 #include "ANIM.H"
       
    24 #include "gc.h"
       
    25 #include "playbackgc.h"
       
    26 #include "rootwin.h"
       
    27 #include "windowgroup.h"
       
    28 #include "EVENT.H"
       
    29 #include "KEYCLICK.H"
       
    30 #include "panics.h"
       
    31 #include "inifile.h"
       
    32 #include "pointer.h"
       
    33 #include "WSGRAPHICDRAWERFACTORY.H"
       
    34 #include "redrawmsgwindow.h"
       
    35 #include <Graphics/WSGRAPHICDRAWERINTERFACE.H>
       
    36 #include "WsMemMgr.h"
       
    37 #include "backedupwindow.h"
       
    38 #include "wsfont.h"
       
    39 #include "registeredsurfacemap.h"
       
    40 #include <EGL/egl.h>
       
    41 
       
    42 #ifdef SYMBIAN_PROCESS_MONITORING_AND_STARTUP
       
    43 #include <e32power.h>
       
    44 #endif
       
    45 
       
    46 #include "registeredsurfacemap.h"
       
    47 #include "windowelementset.h"
       
    48 #include "wspluginmanager.h"
       
    49 
       
    50 // IDs of p&s properties that optionally contain callbacks that may be used
       
    51 // to release singletons owned by libraries at shutdown in order to make 
       
    52 // the memory leak tests work.
       
    53 // By convention, the ID is the same as the UID3 of the libary.
       
    54 static TBool gReleaseSingletonsOnExit = EFalse;
       
    55 static const TUid KOpenWfcImplCleanupKey = {0x10286FC4};     
       
    56 static const TUid KOpenWfcInteropCleanupKey = {0x10286FC5};
       
    57 
       
    58 typedef CDebugLogBase *(*CreateDebugLog)(TBool aIsFirst, TDesC &aParams);
       
    59 
       
    60 CWsActiveScheduler* CWsActiveScheduler::Static()
       
    61 	{
       
    62 	return static_cast<CWsActiveScheduler*>(CActiveScheduler::Current());
       
    63 	}
       
    64 
       
    65 CWsActiveScheduler::CWsActiveScheduler(): iNumSamples(100)
       
    66 	{
       
    67 	iRun = User::FastCounter();
       
    68 	if((KErrNone == HAL::Get(HALData::EFastCounterFrequency,iFastCounterFreq)) && iFastCounterFreq)
       
    69 		{
       
    70 		iData = reinterpret_cast<TSample*>(User::AllocZ(sizeof(TSample)*iNumSamples));
       
    71 		}
       
    72 	}
       
    73 	
       
    74 CWsActiveScheduler::~CWsActiveScheduler()
       
    75 	{
       
    76 	User::FreeZ(reinterpret_cast<void*&>(iData));
       
    77 	}
       
    78 void CWsActiveScheduler::PrepareDraw()
       
    79 	{
       
    80 	iRunDraw = User::FastCounter();
       
    81 	}
       
    82 	
       
    83 void CWsActiveScheduler::CancelPrepare()
       
    84 	{
       
    85 	}
       
    86 	
       
    87 void CWsActiveScheduler::StartDraw()
       
    88 	{
       
    89 	TTime now;
       
    90 	now.UniversalTime();
       
    91 	TUint64 duration = now.MicroSecondsFrom(iRunDraw).Int64();
       
    92 	iPreparing += duration;
       
    93 	iRunDraw = now;
       
    94 	if(iData)
       
    95 		{
       
    96 		iData[iCurrent].iStart = iRunDraw;
       
    97 		}
       
    98 	iDraws++;
       
    99 	}
       
   100 
       
   101 void CWsActiveScheduler::DrawStats(TInt& aUpdatesPerSecond,TInt64& aPixelsPerSecond,TInt aWindowInSeconds) const
       
   102 	{
       
   103 	aUpdatesPerSecond = 0;
       
   104 	aPixelsPerSecond = 0;
       
   105 	if(iData)
       
   106 		{
       
   107 		// work out statistic
       
   108 		TTime window;
       
   109 		window.UniversalTime();
       
   110 		window -= TTimeIntervalSeconds(aWindowInSeconds);
       
   111 		TUint32 pixels = 0;
       
   112 		TInt64 duration = 0;
       
   113 		for(TUint i=0; i<iNumSamples; i++)
       
   114 			{
       
   115 			if(iData[i].iStart >= window)
       
   116 				{
       
   117 				pixels += iData[i].iPixels;
       
   118 				duration += iData[i].iDuration;
       
   119 				aUpdatesPerSecond++;
       
   120 				}
       
   121 			}
       
   122 		if(aUpdatesPerSecond && duration)
       
   123 			{
       
   124 			const TReal pixelsPerMicroSecond = (static_cast<TReal>(pixels) / static_cast<TReal>(duration));
       
   125 			aPixelsPerSecond = static_cast<TInt64>(pixelsPerMicroSecond * 1000000.0);
       
   126 			aUpdatesPerSecond /= aWindowInSeconds;
       
   127 			}
       
   128 		}
       
   129 	}
       
   130 
       
   131 void CWsActiveScheduler::StopDraw(TInt aPixelsUpdated)
       
   132 	{
       
   133 	TTime now;
       
   134 	now.UniversalTime();
       
   135 	TUint32 duration = now.MicroSecondsFrom(iRunDraw).Int64();
       
   136     // do recording
       
   137 	if(iData)
       
   138 		{
       
   139 		iData[iCurrent].iDuration = now.MicroSecondsFrom(iData[iCurrent].iStart).Int64();
       
   140 		iData[iCurrent].iPixels = aPixelsUpdated;
       
   141 		if(++iCurrent >= iNumSamples)
       
   142 			{
       
   143 			iCurrent = 0;
       
   144 			}
       
   145 		}
       
   146 	iDrawing += duration;
       
   147 	}
       
   148 
       
   149 void CWsActiveScheduler::WaitForAnyRequest()
       
   150 	{
       
   151 	TTime stop;
       
   152 	stop.UniversalTime();
       
   153 	iTotal += stop.MicroSecondsFrom(iRun).Int64();
       
   154 	CActiveScheduler::WaitForAnyRequest();
       
   155 	iRequests++;
       
   156 	iRun.UniversalTime();
       
   157 	iIdle += iRun.MicroSecondsFrom(stop).Int64();
       
   158 	}
       
   159 
       
   160 	
       
   161 void CWsActiveScheduler::Error(TInt /*aError*/) const
       
   162 	{
       
   163 	iErrors++;
       
   164 	}
       
   165 
       
   166 void CWsActiveScheduler::AccumReclaimedIdleTime(TInt64 aMicroSeconds)
       
   167 	{
       
   168 	iReclaimedIdleTime += aMicroSeconds;
       
   169 	}
       
   170 	
       
   171 
       
   172 GLREF_C void StateDump(CWsRootWindow* aRootWindow);
       
   173 GLREF_C void HeapDump();
       
   174 
       
   175 // Static objects that need to be destroyed on exit
       
   176 GLDEF_D CDebugLogBase *wsDebugLog=NULL;
       
   177 GLDEF_D TInt wsDebugLogLevel=0;
       
   178 GLDEF_D CIniFile *WsIniFile=NULL;
       
   179 //
       
   180 GLDEF_D TPtr nullDescriptor(NULL,0);
       
   181 
       
   182 LOCAL_D CWsActiveScheduler *TheActiveScheduler;
       
   183 
       
   184 CScreen* CWsTop::iCurrentFocusScreen;
       
   185 CArrayPtrFlat<CScreen>* CWsTop::iScreens ;
       
   186 TInt CWsTop::iNumberOfScreens ;
       
   187 CWsTop::CShellStarter* CWsTop::iShellStarter;
       
   188 
       
   189 CWsPluginManager *CWsTop::iPluginManager;
       
   190 CWindowServer *CWsTop::iServer;
       
   191 RLibrary CWsTop::iDebugLib;
       
   192 CWsShellLogon *CWsTop::iShell;
       
   193 const CWsClient *CWsTop::iShellClient;
       
   194 TBool CWsTop::iPreviousShellClient=EFalse;
       
   195 TInt CWsTop::iShellBootMode;
       
   196 TBool CWsTop::iShuttingDown;
       
   197 TBool CWsTop::iIsFirstLog=ETrue;
       
   198 CWsWindowBase *CWsTop::iWindowToSendOffEventsTo=NULL;
       
   199 RTimer CWsTop::iTimer;
       
   200 TBool CWsTop::iIgnoreSwitchOffEvent=EFalse;
       
   201 TBool CWsTop::iFadeEnabled=ETrue;
       
   202 TBool CWsTop::iFinishEveryFlush=EFalse;
       
   203 TBool CWsTop::iMultiFocusPolicy=EFalse;
       
   204 #if defined(__WINS__)
       
   205 TFullName WsSemName;
       
   206 #endif
       
   207 const CWsClient* CWsTop::iTriggerHeapCheckOnClientExit=NULL;
       
   208 TWsCheckHeapOnDisconnectMode CWsTop::iHeapCheckMode=EWsCheckHeapOnDisconnectModeNone;
       
   209 TInt CWsTop::iCheckHeapResult=KErrNotReady;
       
   210 TBool CWsTop::iDoHeapCheckAndRestart=EFalse;
       
   211 #define RFbsSession_SendCommand_ShutDownMessage 1	// A FBS message that is not published yet and probably never will be.
       
   212 
       
   213 static void DefineSingletonKey(const TUid& aSingletonKey)
       
   214 /**
       
   215  * Defines a new property for a singleton key. WServ must only process 
       
   216  * singleton keys that it created to prevent a malicious process with the 
       
   217  * WriteDeviceData capability causing arbitrary functions to be executed.
       
   218  * 
       
   219  * @param   aSingeltonKey   The UID of the singleton key to define.
       
   220  */
       
   221     {
       
   222     RThread t;      
       
   223     TUid category = { t.SecureId().iId };
       
   224     RProperty prop;
       
   225     
       
   226     // Write access is restricted to THIS process
       
   227     TInt err = prop.Define( category, aSingletonKey.iUid, 
       
   228             RProperty::EByteArray, TSecurityPolicy( t.SecureId() ), 
       
   229             TSecurityPolicy( t.SecureId() ), sizeof( TCallBack ) );
       
   230     
       
   231     if ( err == KErrNone )
       
   232         {
       
   233         TCallBack cb( NULL, NULL );
       
   234         TPckgC<TCallBack> cbPckg( cb );
       
   235         
       
   236         // Any error should cause the properties to be ignored
       
   237         err = prop.Set( category, aSingletonKey.iUid, cbPckg );    
       
   238         }      
       
   239     
       
   240     if ( err != KErrNone )
       
   241         {
       
   242         // A problem occured / the property already existed so for safety
       
   243         // the release code should be skipped.
       
   244         gReleaseSingletonsOnExit = EFalse;
       
   245         }
       
   246     
       
   247     prop.Close();
       
   248     t.Close();
       
   249     }
       
   250 
       
   251 static void DeleteSingleton( const TUid& aSingletonKey )
       
   252 /**
       
   253  * Deletes a singleton object that was created on WServ's main heap.
       
   254  * 
       
   255  * @pre     The ws plugins have not been unloaded.
       
   256  * @param   aSingletonKey   The UID of the singleton which correponds to an
       
   257  *                          RProperty within WServ's category.                       
       
   258  */
       
   259     {   
       
   260     if ( gReleaseSingletonsOnExit )
       
   261         {
       
   262         RThread t;
       
   263         TPckgBuf<TCallBack> cb;
       
   264         RProperty prop; 
       
   265         TInt err = prop.Get(TUid::Uid(t.SecureId().iId), aSingletonKey.iUid, cb);
       
   266         if (err == KErrNone && cb.Length() == sizeof(TCallBack) && 
       
   267                 cb().iFunction && cb().iPtr == &User::Heap())
       
   268             {
       
   269             // Callback is only invoked if the heap for the singleton was the 
       
   270             // WServ heap because the WServ memory leak tests only check this
       
   271             // heap.
       
   272             cb().CallBack();
       
   273             }
       
   274         // Errors are ignored because the purpose of this function is to free
       
   275         // singletons in order top make memory leak checks pass.
       
   276         prop.Close();
       
   277         t.Close();
       
   278         }
       
   279     }
       
   280 
       
   281 void CWsTop::DeleteStaticsL()
       
   282 	{
       
   283 	iShuttingDown=ETrue;
       
   284 	CClick::DeleteStatics();
       
   285 	TWsPointer::Stop();
       
   286 	CWsClient::DeleteStatics();
       
   287 //
       
   288 	delete iShellStarter;
       
   289 	iServer->DestroySessionsForShutdown();
       
   290 
       
   291 	CWsBackedUpWindow::StaticDestroy();
       
   292 	delete iShell;
       
   293 	DisableLogging();
       
   294 
       
   295 	CEventQueue::DeleteStaticsL();
       
   296 		
       
   297 	CWsSpriteBase::DeleteStatics();
       
   298 	CWsGc::DeleteStatics();
       
   299 	CPlaybackGc::DeleteStatics();
       
   300 	CWsAnimDll::DeleteStatics();
       
   301 	CWsFontCache::DestroyInstance();
       
   302 
       
   303 	iScreens->ResetAndDestroy();
       
   304 	delete iScreens;
       
   305 
       
   306 	delete iServer;
       
   307 	TWindowServerEvent::DeleteStatics();
       
   308 	
       
   309 	// Free singletons on WServ heap created by libraries. Must be called
       
   310 	// BEFORE iPluginManager is deleted otherwise the library code could have
       
   311 	// been unloaded.
       
   312 	DeleteSingleton(KOpenWfcImplCleanupKey);
       
   313 	DeleteSingleton(KOpenWfcInteropCleanupKey);
       
   314 	eglReleaseThread();
       
   315 
       
   316 	if (!iDoHeapCheckAndRestart)
       
   317 		{
       
   318 		RFbsSession::GetSession()->SendCommand(RFbsSession_SendCommand_ShutDownMessage);		//This line is just being tidy, never really does anything useful.
       
   319 		}
       
   320 
       
   321 	RFbsSession::Disconnect();
       
   322 	iDebugLib.Close();
       
   323 	iTimer.Close();
       
   324 	TWsPointer::DeleteStatics();
       
   325 	delete TheActiveScheduler;
       
   326 	
       
   327 	// iPluginManager is not created in InitStaticsL because plugins need to be loaded 
       
   328 	// before E32Main's loop for EcomSession allocations issues
       
   329 	delete iPluginManager;
       
   330 	}
       
   331 
       
   332 RWsTextCursor *CWsTop::CurrentTextCursor()
       
   333 	{
       
   334 	if(iCurrentFocusScreen && FocusWindowGroup())
       
   335 		{
       
   336 		return FocusWindowGroup()->TextCursor();
       
   337 		}
       
   338 	else
       
   339 		{
       
   340 		return NULL;
       
   341 		}
       
   342 	}
       
   343 
       
   344 CWsClient *CWsTop::FocusWindowGroupOwner()
       
   345 	{
       
   346 	return(FocusWindowGroup() ? FocusWindowGroup()->WsOwner():NULL);
       
   347 	}
       
   348 
       
   349 void CWsTop::ClientDestroyed(const CWsClient *aClient)
       
   350 	{
       
   351 	if (aClient==iShellClient)
       
   352 		iShellClient=NULL;
       
   353 	}
       
   354 
       
   355 void CWsTop::NewSession(const CWsClient *aClient)
       
   356 	{	
       
   357 	if (iShellClient==NULL && iShell)
       
   358 		{
       
   359 #if defined(__WINS__)
       
   360 		RThread proc;
       
   361 		proc=aClient->Client();
       
   362 #else
       
   363 		RProcess proc;
       
   364 		aClient->Client().Process(proc);
       
   365 #endif
       
   366 		TFullName procName = proc.FullName();
       
   367 		// Before comparing the proc name with iShell name , truncate the proc name up to the actual name
       
   368 		// referring to the process, by removing the part which starts with ':', if exists.
       
   369 		TInt colonLocation = procName.Locate(':');
       
   370 		if( KErrNotFound != colonLocation)
       
   371 			{
       
   372 			procName = procName.Left(colonLocation);
       
   373 			}
       
   374 		if (procName ==iShell->FullName())
       
   375 			{
       
   376 			iShellClient=aClient;
       
   377 			if (!iPreviousShellClient)
       
   378 				{
       
   379 				iPreviousShellClient=ETrue;
       
   380 				aClient->Screen()->RootWindow()->SetColorIfClear();
       
   381 				}
       
   382 			}
       
   383 #if !defined(__WINS__)
       
   384 		proc.Close();
       
   385 #endif
       
   386 		}	
       
   387 	}
       
   388 
       
   389 void CWsTop::SessionExited(CWsClient *aClient)
       
   390 	{
       
   391 	if (iShuttingDown)
       
   392 		{
       
   393 		RProcess proc;
       
   394 		TInt err=aClient->Client().Process(proc);
       
   395 		if (err==KErrNone && proc.Id()!=RProcess().Id())
       
   396 			proc.Kill(0);
       
   397 		else
       
   398 			const_cast<RThread&>(aClient->Client()).Kill(0);
       
   399 		if (err==KErrNone)
       
   400 			proc.Close();
       
   401 		}
       
   402 	else if (iHeapCheckMode!=EWsCheckHeapOnDisconnectModeNone && aClient==iTriggerHeapCheckOnClientExit)
       
   403 		{
       
   404 		if (iHeapCheckMode==EWsCheckHeapOnDisconnectModeOnce)
       
   405 			{
       
   406 			iHeapCheckMode=EWsCheckHeapOnDisconnectModeNone;
       
   407 			}
       
   408 		iTriggerHeapCheckOnClientExit=NULL;
       
   409 		iDoHeapCheckAndRestart=ETrue;
       
   410 		Exit();
       
   411 		}
       
   412 	if (iServer->SessionCount()==1 && iShellBootMode==EShellBootModeNoReboot && iShell==NULL)
       
   413 		StartShell();
       
   414 	}
       
   415 
       
   416 
       
   417 void CWsTop::RunServerL()
       
   418 	{
       
   419 	InitStaticsL();
       
   420 	CWsMemoryManager* memMgr = CWsMemoryManager::NewLC();
       
   421 	CActiveScheduler::Start();
       
   422 	CleanupStack::PopAndDestroy(memMgr);
       
   423 	DeleteStaticsL();
       
   424 	}
       
   425 
       
   426 void CWsTop::InitStaticsL()
       
   427 	{
       
   428 	iShuttingDown=EFalse;
       
   429 	// By default shell should be started.
       
   430 	TBool startShell = ETrue;
       
   431 	
       
   432 	iCurrentFocusScreen = 0;
       
   433 
       
   434 	// The windows server has been invoked.
       
   435 	// This may have been from the system starter (via a
       
   436 	// start up rss file)  
       
   437 	// This block looks for a "-NoShell" argument in the invocation.
       
   438 	// The existence of the argument means that shell does not need to be 
       
   439 	// invoked from here because the new system starter
       
   440 	// is in charge, and it will do it if required.
       
   441 	
       
   442 	_LIT(KNoShell,"-NOSHELL");
       
   443 	
       
   444 	TInt argLen = User::CommandLineLength();
       
   445 	if(argLen)
       
   446 		{
       
   447 		HBufC* arg = HBufC::NewLC(argLen);
       
   448 		TPtr argPtr = arg->Des();
       
   449 		User::CommandLine(argPtr);
       
   450 		argPtr.UpperCase();
       
   451 
       
   452 		if(KErrNotFound != argPtr.Find(KNoShell))
       
   453 			{
       
   454 			// Don't start the shell. It will be started if required by 
       
   455 			// the system starter.
       
   456 			startShell = EFalse;
       
   457 			}
       
   458 		CleanupStack::PopAndDestroy(arg);
       
   459 		}
       
   460 		
       
   461 	TheActiveScheduler=new(ELeave) CWsActiveScheduler;
       
   462 	CActiveScheduler::Install(TheActiveScheduler);
       
   463 	// WsIniFile is already created (before E32Main's Loop)
       
   464 	_LIT(KWSERVIniFileVarLogEnable,"LOGENABLE");
       
   465 	TInt loggingLevel;
       
   466 	if (WsIniFile->FindVar(KWSERVIniFileVarLogEnable,loggingLevel))
       
   467 		{
       
   468 		EnableLogging(EDoNotReloadWsIni);
       
   469 		if (wsDebugLog)
       
   470 			{
       
   471 			wsDebugLog->SetLoggingLevel(loggingLevel);
       
   472 			}
       
   473 		}
       
   474 		
       
   475 	_LIT(KWSERVIniFileVarFadeEnable,"FADEDISABLE");
       
   476 	iFadeEnabled = !WsIniFile->FindVar(KWSERVIniFileVarFadeEnable);
       
   477 
       
   478 	_LIT(KWSERVIniFileVarFinishEveryFlush,"FINISHEVERYFLUSH");
       
   479 	iFinishEveryFlush = WsIniFile->FindVar(KWSERVIniFileVarFinishEveryFlush);
       
   480 	
       
   481 	_LIT(KWSERVIniFileVarSwitchOffEvent,"IGNORESWITCHOFFEVENT");
       
   482 	iIgnoreSwitchOffEvent = WsIniFile->FindVar(KWSERVIniFileVarSwitchOffEvent);	
       
   483 
       
   484 	iPluginManager = CWsPluginManager::NewL(); // need to be constructed before iServer!
       
   485 	iServer=CWindowServer::NewL();
       
   486 	CClick::InitStaticsL();
       
   487 	
       
   488 	RProcess wservProc;
       
   489 	if (!wservProc.DefaultDataPaged())
       
   490 	{
       
   491 		iServer->SetPinClientDescriptors(ETrue);
       
   492 	}
       
   493 	User::LeaveIfError(FbsStartup());
       
   494 	User::LeaveIfError(RFbsSession::Connect());
       
   495 	User::LeaveIfError(iTimer.CreateLocal());
       
   496 
       
   497 	TWindowServerEvent::InitStaticsL();
       
   498 	CWsClient::InitStaticsL();
       
   499 	//-------------------------------------------
       
   500 	User::LeaveIfError(  HAL::Get( HAL::EDisplayNumberOfScreens, iNumberOfScreens ) ) ; 
       
   501 	// Check that the INI file matches the HAL
       
   502 	WS_ASSERT_ALWAYS(WsIniFile->NumberOfScreens()<=iNumberOfScreens, EWsPanicScreenInformationError);
       
   503 
       
   504 	iScreens = new (ELeave) CArrayPtrFlat<CScreen>( iNumberOfScreens ) ;  //
       
   505 	// now construct screens for as long as there is information
       
   506 	
       
   507 	TInt ii ;
       
   508 	for ( ii = 0 ; ii < iNumberOfScreens ; ++ii )
       
   509 		{
       
   510 		InitScreenL( ii ) ;
       
   511 		}
       
   512 	//---------------------------------------------
       
   513 	iCurrentFocusScreen = (*iScreens)[0] ;
       
   514 	iServer->StartL();
       
   515 
       
   516 	CWsFontCache::CreateInstanceL();
       
   517 	CWsGc::InitStaticsL();
       
   518 	CPlaybackGc::InitStaticsL();
       
   519 	CWsSpriteBase::InitStaticsL();
       
   520 	CEventQueue::InitStaticsL();
       
   521 
       
   522 //
       
   523 	CWsAnimDll::InitStaticsL();
       
   524 //
       
   525 	TInt bootMode=0;
       
   526 	_LIT(KWSERVIniFileVarReboot,"REBOOT");
       
   527 	WsIniFile->FindVar(KWSERVIniFileVarReboot,bootMode);
       
   528 	if (bootMode>=0 && bootMode<=2)
       
   529 		iShellBootMode=bootMode;
       
   530 //
       
   531 	CWsBackedUpWindow::StaticInitL();
       
   532 	CWsRedrawMsgWindow::StaticInitL();
       
   533 //
       
   534 	TWsPointer::InitStaticsL();
       
   535 	iShellStarter=new (ELeave) CShellStarter;
       
   536 	iShellStarter->ConstructL();
       
   537 	_LIT(KPreProcess,"REMOVEFADINGONFOCUSGAIN");
       
   538 	CWsWindowGroup::SetFocusGainPreprocessing(WsIniFile->FindVar(KPreProcess));
       
   539 	_LIT(KAbsFade,"ABSOLUTEFADING");
       
   540 	CWsClientWindow::SetAbsoluteFading(WsIniFile->FindVar(KAbsFade));
       
   541 
       
   542 //Set the focus policy
       
   543 	_LIT(KFocusPolicy,"MULTIFOCUSPOLICY");
       
   544 	if(WsIniFile->FindVar(KFocusPolicy))
       
   545 		{
       
   546 		iMultiFocusPolicy = ETrue;	
       
   547 		}
       
   548 	RProcess::Rendezvous(KErrNone);
       
   549 	// Start the shell from here unless the 'NoShell' option has been 
       
   550 	// received indicating that the system starter will start the shell directly.
       
   551 	if(startShell)
       
   552 		{
       
   553 		StartShell();
       
   554 		}
       
   555 	UserSvr::WsRegisterSwitchOnScreenHandling(ETrue);
       
   556 	}
       
   557 
       
   558 
       
   559 void CWsTop::InitScreenL( TInt aScreenNumber)  // static
       
   560 	{
       
   561 	// create a new screen,  read ini file for aScreenNumber (this happens in CScreen - just need to pass a screen number from here
       
   562 	CScreen* screen = new (ELeave) CScreen() ;
       
   563 	CleanupStack::PushL( screen ) ;
       
   564 	TRect digitiserArea;
       
   565 	if (aScreenNumber==0)
       
   566 		{
       
   567 		TMachineInfoV1Buf machineBuf;
       
   568 		UserHal::MachineInfo(machineBuf);
       
   569 		TMachineInfoV1& machineInfo=*(TMachineInfoV1*)machineBuf.Ptr();
       
   570 		digitiserArea = TRect(-machineInfo.iOffsetToDisplayInPixels,machineInfo.iXYInputSizeInPixels);
       
   571 		}
       
   572 	screen->ConstructL(digitiserArea, aScreenNumber);
       
   573 	iScreens->AppendL( screen ) ; 
       
   574 	CleanupStack::Pop( screen ) ;
       
   575 	}
       
   576 
       
   577 void CWsTop::ClearAllRedrawStores()
       
   578 	{
       
   579 	TInt ii;
       
   580 	if (iScreens && iScreens->Count()>=iNumberOfScreens)
       
   581 		{	//All screens are initialized
       
   582 		for (ii=0; ii<iNumberOfScreens; ++ii)
       
   583 			{
       
   584 			CScreen *screen=(*iScreens)[ii];
       
   585 			CWsWindowGroup* group=screen->RootWindow()->Child();
       
   586 			while (group!=NULL)
       
   587 				{
       
   588 				CWsWindowBase* win=group->Child();
       
   589 				if (win)
       
   590 					{
       
   591 					while (win!=group)
       
   592 						{
       
   593 						static_cast<CWsWindow*>(win)->Redraw()->ClearRedrawStore(ETrue);
       
   594 						//On orientation switch, window is no longer present on screen
       
   595 						static_cast<CWsWindow*>(win)->SetDrawnToScreen(EFalse);
       
   596 						if (win->BaseChild())
       
   597 							win=win->BaseChild();
       
   598 						else
       
   599 							{
       
   600 							do	
       
   601 								{
       
   602 								if (win->NextSibling())
       
   603 									{
       
   604 									win=win->NextSibling();
       
   605 									break;
       
   606 									}
       
   607 								win=win->BaseParent();
       
   608 								}
       
   609 							while (win!=group);
       
   610 							}
       
   611 						}
       
   612 					}
       
   613 				group=group->NextSibling();
       
   614 				}
       
   615 			TriggerRedraws(screen->RootWindow());
       
   616 			}
       
   617 		}
       
   618 	}
       
   619 
       
   620 void CWsTop::Exit()
       
   621 	{
       
   622 	CActiveScheduler::Stop();
       
   623 	}
       
   624 
       
   625 void CWsTop::TriggerRedraws(CWsRootWindow* aRootWindow)
       
   626 	{
       
   627 	for(CWsWindowGroup *group=aRootWindow->Child();group!=NULL;group=group->NextSibling())
       
   628 		group->WsOwner()->TriggerRedraw();
       
   629 	}
       
   630 
       
   631 void CWsTop::StartShell()
       
   632 	{
       
   633 	TRAPD(err,iShell=new(ELeave) CWsShellLogon());
       
   634 	if (err==KErrNone)
       
   635 		{
       
   636 		RFs fs;
       
   637 		if ((err=fs.Connect())==KErrNone)
       
   638 			{
       
   639 			fs.SetNotifyUser(EFalse);
       
   640 			TRAP(err,iShell->ConstructL(fs));
       
   641 			fs.Close();
       
   642 			}
       
   643 		}
       
   644 	if (err!=KErrNone)
       
   645 		{
       
   646 #ifdef _DEBUG
       
   647 		RDebug::Print(_L("Failed to start shell: err=%d\n"),err);
       
   648 #endif
       
   649 		delete iShell;
       
   650 		iShell=NULL;
       
   651 		iShellStarter->After(TTimeIntervalMicroSeconds32(1000000));
       
   652 		}
       
   653 	}
       
   654 
       
   655 void CWsTop::ShellExited()
       
   656 	{
       
   657 	delete iShell;
       
   658 	iShell=NULL;
       
   659 	switch(iShellBootMode)
       
   660 		{
       
   661 		case EShellBootModeReboot:
       
   662 			StartShell();
       
   663 			break;
       
   664 		case EShellBootModeNoReboot:
       
   665 			if (iServer->SessionCount()==0)
       
   666 				StartShell();
       
   667 			break;
       
   668 		case EShellBootModeExit:
       
   669 			Exit();
       
   670 			break;
       
   671 		}
       
   672 	}
       
   673 
       
   674 TInt CWsTop::SetSendOffEventsToShell(CWsClient *aClient,const TWsClCmdOffEventsToShell &aData)
       
   675 	{
       
   676 	CWsWindowBase *window=NULL;
       
   677 	if (aData.window==0)
       
   678 		{
       
   679 		if (aData.on)
       
   680 			aClient->PPanic(EWservPanicNoWindowSpecifed);
       
   681 		}
       
   682 	else
       
   683 		aClient->HandleToWindow(aData.window,&window);
       
   684 	if (aData.on)
       
   685 		{
       
   686 		if (iWindowToSendOffEventsTo!=NULL && aClient!=iShellClient)		//Allow the shell to pinch it
       
   687 			return KErrAlreadyExists;
       
   688 		iWindowToSendOffEventsTo=window;
       
   689 		}
       
   690 	else
       
   691 		{
       
   692 		if (iWindowToSendOffEventsTo==window || (!window && aClient==iWindowToSendOffEventsTo->WsOwner()))
       
   693 			iWindowToSendOffEventsTo=NULL;
       
   694 		}
       
   695 	return KErrNone;
       
   696 	}
       
   697 
       
   698 void CWsTop::StopWindowGettingOffEvents(CWsWindowBase* aWindow)
       
   699 	{
       
   700 	if (aWindow==iWindowToSendOffEventsTo)
       
   701 		iWindowToSendOffEventsTo=NULL;
       
   702 	}
       
   703 
       
   704 /** Routes "Off" events to the shutdown manager if one is registered. Othwerwise calls Power API's directly to
       
   705 set the power mode of the device accordingly.
       
   706 @internalTechnology
       
   707 @released
       
   708 @param aEvent Type of event that Wserv passes to client as OFF events. 
       
   709 It can be EEventSwitchOff, EEventCaseClosed, EEventKeySwitchOff or EEventRestartSystem.
       
   710 @param aDoSwitchOff ETrue if the switch-off should be performed when no shutdown manager is registered
       
   711 and IGNORESWITCHOFFEVENT is not defined in wsini.ini
       
   712 */
       
   713 void CWsTop::HandleSwitchOff(TInt aEvent,TBool aDoSwitchOff)
       
   714 	{
       
   715 	// If any shutdown manager is registered, forward the event to it
       
   716 	if (iWindowToSendOffEventsTo && iWindowToSendOffEventsTo->QueueEvent(aEvent))
       
   717 		return;
       
   718 	// Otherwise, do the shutdown here
       
   719 	if(!iIgnoreSwitchOffEvent && aDoSwitchOff)
       
   720 		{
       
   721 #ifdef SYMBIAN_PROCESS_MONITORING_AND_STARTUP		
       
   722 		// if LaF is not registered, restart or shutdown using Power API 
       
   723 		if (aEvent == EEventRestartSystem) // restart
       
   724 			{
       
   725 			if (Power::EnableWakeupEvents(EPwRestart) == KErrNone)
       
   726 				{
       
   727 				// Should reboot/power-cycle the system, so no need to RequestWakeupEventNotification
       
   728 				Power::PowerDown();
       
   729 				}
       
   730 			}
       
   731 		else // everything else maps to standby for now
       
   732 			{
       
   733 			if (Power::EnableWakeupEvents(EPwStandby) == KErrNone)
       
   734 				{
       
   735 				// Prepare to wake up from standby
       
   736 				TRequestStatus s;
       
   737 				Power::RequestWakeupEventNotification(s);
       
   738 				Power::PowerDown();
       
   739 				User::WaitForRequest(s);
       
   740 				}
       
   741 			}
       
   742 #else
       
   743 		UserHal::SwitchOff();
       
   744 #endif			
       
   745 		}
       
   746 	}
       
   747 
       
   748 void CWsTop::RedrawScreens()
       
   749 	{
       
   750 	// apply to all screens
       
   751 	TInt screenNo;
       
   752 	for(screenNo=0; screenNo<iNumberOfScreens; ++screenNo)
       
   753 		{
       
   754 		CScreen* screen = Screen(screenNo);
       
   755 		TRegionFix<1> screenArea(TRect(screen->DrawableArea()));
       
   756 		}
       
   757 	}
       
   758 
       
   759 void CWsTop::EnableLogging(TReloadWsIni aSetting)
       
   760 	{
       
   761 	TInt errorLoc=0;
       
   762 	if (wsDebugLog)
       
   763 		{
       
   764 		if (wsDebugLogLevel==CDebugLogBase::ELogEverything)
       
   765 			{
       
   766 			wsDebugLogLevel=CDebugLogBase::ELogImportant;
       
   767 			wsDebugLog->SetLoggingLevel(wsDebugLogLevel);
       
   768 			return;
       
   769 			}
       
   770 		DisableLogging();
       
   771 		}
       
   772 
       
   773 	if(aSetting == EDoReloadWsIni)
       
   774 	    {
       
   775 	    CIniFile* temp = NULL;
       
   776 	    TRAPD(err, temp = CIniFile::NewL());
       
   777 	    if(err == KErrNone)
       
   778 	        {
       
   779 	        //loading successful, replace the previous one
       
   780 	        delete WsIniFile;
       
   781 	        WsIniFile = temp;
       
   782 	        }
       
   783 	    }
       
   784 	
       
   785 	TPtrC dlog;
       
   786 	_LIT(KWSERVDebugLogFileName,"DLOG");
       
   787 	TBuf<KMaxFileName> fname(KWSERVDebugLogFileName);
       
   788 	_LIT(KWSERVIniFileVarLog,"LOG");
       
   789 	if (WsIniFile->FindVar(KWSERVIniFileVarLog,dlog) && dlog.Length()==2)
       
   790 		{
       
   791 		fname.Append(dlog);
       
   792 		TInt err=iDebugLib.Load(fname);
       
   793 		if (err==KErrNone)
       
   794 			{
       
   795 			TUidType uid=iDebugLib.Type();
       
   796 			if (uid[1]!=KWservLoggingDllUid)
       
   797 				{
       
   798 				err=KErrNotSupported;
       
   799 				errorLoc=2;
       
   800 				}
       
   801 			else
       
   802 				{
       
   803 				TPtrC params;
       
   804 				_LIT(KWSERVIniFileVarLogP,"LOGP");
       
   805 				if (!WsIniFile->FindVar(KWSERVIniFileVarLogP,params))
       
   806 					params.Set(NULL,0);
       
   807 				CreateDebugLog func=(CreateDebugLog)iDebugLib.Lookup(1);
       
   808 				if (func!=NULL)
       
   809 					{
       
   810 					TRAP(err,wsDebugLog=(*func)(iIsFirstLog, params));
       
   811 					if (err==KErrNone)
       
   812 						{
       
   813 						iIsFirstLog=EFalse;
       
   814 						wsDebugLogLevel=CDebugLogBase::ELogEverything;
       
   815 						}
       
   816 					else
       
   817 						errorLoc=4;
       
   818 					}
       
   819 				else
       
   820 					errorLoc=3;
       
   821 				}
       
   822 			}
       
   823 		else
       
   824 			errorLoc=1;
       
   825 		if (iCurrentFocusScreen)
       
   826 			{
       
   827 			TWindowServerEvent::ProcessErrorMessages(TWsErrorMessage::ELogging,(errorLoc<<8)-err);
       
   828 			}
       
   829 		}
       
   830 	}
       
   831 
       
   832 void CWsTop::DisableLogging()
       
   833 	{
       
   834 	delete wsDebugLog;
       
   835 	wsDebugLog=NULL;
       
   836 	iDebugLib.Close();
       
   837 	}
       
   838 
       
   839 void CWsTop::LogCommand(RWsSession::TLoggingCommand aCommand)
       
   840 	{
       
   841 	switch(aCommand)
       
   842 		{
       
   843 	case RWsSession::ELoggingEnable:
       
   844 		EnableLogging();
       
   845 		break;
       
   846 	case RWsSession::ELoggingDisable:
       
   847 		DisableLogging();
       
   848 		break;
       
   849 	case RWsSession::ELoggingStatusDump:
       
   850 		StateDump();
       
   851 		break;
       
   852 	case RWsSession::ELoggingHeapDump:
       
   853 		HeapDump();
       
   854 		break;
       
   855 		}
       
   856 	}
       
   857 
       
   858 void CWsTop::StateDump()
       
   859 	{
       
   860 	TInt screenNo;
       
   861 	for (screenNo=0; screenNo<iNumberOfScreens; ++screenNo)
       
   862 		::StateDump( (*iScreens)[screenNo]->RootWindow());
       
   863 	}
       
   864 	
       
   865 void CWsTop::SetCurrentFocusScreen(CScreen* aScreen)	
       
   866 	{
       
   867 	iCurrentFocusScreen = aScreen;
       
   868 	}
       
   869 
       
   870 TInt CWsTop::SetCurrentFocusScreen(TInt aScreenNo)
       
   871 	{
       
   872 	CScreen* newFocusScreen=CWsTop::Screen(aScreenNo);
       
   873 	if (newFocusScreen==iCurrentFocusScreen)
       
   874 		return KErrNone;
       
   875 
       
   876 	CWsWindowGroup* newFocusGroup=newFocusScreen->FocusWindowGroup();
       
   877 	if (!newFocusGroup)
       
   878 		return KErrNotReady;
       
   879 
       
   880 	CWsWindowGroup* oldFocusGroup=iCurrentFocusScreen->FocusWindowGroup();
       
   881 	if (oldFocusGroup)
       
   882 		oldFocusGroup->LostFocus();
       
   883 	iCurrentFocusScreen=newFocusScreen;
       
   884 	newFocusGroup->ReceivedFocus();
       
   885 	TWsPointer::UpdatePointerCursor();
       
   886 	TWindowServerEvent::SendFocusChangedEvents();
       
   887 	return KErrNone;
       
   888 	}
       
   889 
       
   890 void CWsTop::SetCheckHeapOnDisconnectClient(const CWsClient* aClient)
       
   891 	{
       
   892 	iTriggerHeapCheckOnClientExit=aClient;
       
   893 	}
       
   894 
       
   895 void CWsTop::SetCheckHeapOnDisconnectMode(TWsCheckHeapOnDisconnectMode aCheckHeapOnDisconnectMode)
       
   896 	{
       
   897 	iHeapCheckMode=aCheckHeapOnDisconnectMode;
       
   898 	}
       
   899 
       
   900 static void ReportAllCurrentLevelLeaks()
       
   901     {
       
   902     class RHeapWalk: public RHeap
       
   903         {
       
   904     public:
       
   905          static void WalkCheckCell(TAny* aPtr, TCellType aType, TAny* aCell, TInt aLen)
       
   906              {
       
   907              RHeapWalk* heap=(RHeapWalk*)aPtr;
       
   908              (void)aCell;
       
   909              switch(aType)
       
   910                  {
       
   911                  case EGoodAllocatedCell:
       
   912                      if ( ((SDebugCell*)aCell)->nestingLevel == heap->iNestingLevel )
       
   913                          {
       
   914                          RDebug::Printf("Leaked heap cell: level %i, serial %i @ %08x : len=%d", 
       
   915                                             heap->iNestingLevel, ((SDebugCell*)aCell)->allocCount, aCell, aLen);
       
   916                          }
       
   917                     break;
       
   918                  }
       
   919              }
       
   920         };
       
   921     
       
   922     User::Heap().DebugFunction(RHeap::EWalk, (TAny*)RHeapWalk::WalkCheckCell, &User::Heap());
       
   923     }
       
   924 
       
   925 TBool CWsTop::NeedsHeapCheckAndRestart(TInt aStartHeapCount)
       
   926 	{
       
   927 	if (!iDoHeapCheckAndRestart)
       
   928 		return(EFalse);
       
   929 	iDoHeapCheckAndRestart=EFalse;
       
   930 	iCheckHeapResult=User::Heap().Count()-aStartHeapCount;
       
   931 	if(iCheckHeapResult > 0)
       
   932 	    {
       
   933 	    const TUint32 orphanedCell = User::Heap().__DbgMarkEnd(aStartHeapCount);
       
   934 	    RDebug::Printf("Memory leak detected in wserv. First orphaned cell: 0x%8x", orphanedCell);
       
   935 	    ReportAllCurrentLevelLeaks();
       
   936 	    }
       
   937 	return(ETrue);
       
   938 	}
       
   939 
       
   940 TInt CWsTop::FetchCheckHeapResult()
       
   941 	{
       
   942 	TInt ret=iCheckHeapResult;
       
   943 	iCheckHeapResult=KErrNotReady;
       
   944 	return(ret);
       
   945 	}
       
   946 
       
   947 /**
       
   948 This function looks for memory which isn't essential to the correct running of the window server
       
   949 and frees some of it.
       
   950 Returns true if some memory was freed, and false if it was unable to free anything.
       
   951 Called from the memory manager in low memory conditions.
       
   952 */
       
   953 TBool CWsTop::ReleaseMemory()
       
   954 	{
       
   955 	return iServer->ReleaseMemory();
       
   956 	}
       
   957 	
       
   958 TBool CWsTop::MultiFocusPolicy()
       
   959 	{
       
   960 	return	iMultiFocusPolicy;
       
   961 	}
       
   962 
       
   963 void CWsTop::ClearSurfaceMap(CWsClient *aClient)
       
   964 	{
       
   965 	TInt tempScreens = CWsTop::NumberOfScreens();
       
   966 	for (TInt ii = 0; ii < tempScreens; ii++)
       
   967 		{
       
   968 		__DEBUG_ONLY(TInt err=)
       
   969 		CWsTop::Screen(ii)->SurfaceMap()->RemoveAll(*aClient);
       
   970 		WS_ASSERT_DEBUG((err==KErrNone||err==KErrNotFound||err==KErrInUse), EWsPanicSurfaceMapError);
       
   971 		}
       
   972 	}
       
   973 
       
   974 TBool CWsTop::SearchDuplicateSurfaceId(const TSurfaceId& aSurfaceId)
       
   975 	{
       
   976 	TInt tempScreens = CWsTop::NumberOfScreens();
       
   977 	for (TInt ii = 0; ii < tempScreens; ii++)
       
   978 		{
       
   979 		if (CWsTop::Screen(ii)->WindowElements().SearchDuplicateSurfaceId(aSurfaceId))
       
   980 			{
       
   981 			return ETrue;
       
   982 			}
       
   983 		}
       
   984 	return EFalse;
       
   985 	}
       
   986 
       
   987 typedef TInt (*ShellEntryPoint)(TAny *);
       
   988 
       
   989 #if defined(__WINS__)
       
   990 LOCAL_D const TUint KHeapSize=0x10000;
       
   991 LOCAL_D const TUint KMaxHeapSize=0x400000;
       
   992 #endif
       
   993 
       
   994 CWsShellLogon::CWsShellLogon() : CActive(EWsShellLogonPriority)
       
   995 	{
       
   996 #if defined (__WINS__)
       
   997 	// Clear handles to NULL so we can later detect which one gets used
       
   998 	iShellThread.SetHandle(NULL);
       
   999 	iShellProcess.SetHandle(NULL);
       
  1000 #endif
       
  1001 	}
       
  1002 
       
  1003 CWsShellLogon::~CWsShellLogon()
       
  1004 	{
       
  1005 	Cancel();
       
  1006 #if defined (__WINS__)
       
  1007 	iShellThread.Close();
       
  1008 	iShellProcess.Close();
       
  1009 #else
       
  1010 	iShell.Close();
       
  1011 #endif
       
  1012 #if defined(__WINS__)
       
  1013 	iLib.Close();
       
  1014 #endif
       
  1015 	}
       
  1016 
       
  1017 void CWsShellLogon::ConstructL(RFs &)
       
  1018 	{
       
  1019 	CActiveScheduler::Add(this);
       
  1020 	TPtrC shellCmd;
       
  1021 
       
  1022 	_LIT(KWSERVIniFileVarShellCmd,"SHELLCMD");
       
  1023 	WsIniFile->FindVar(KWSERVIniFileVarShellCmd,shellCmd);
       
  1024 	_LIT(KWSERVShellName,"SHELL");
       
  1025 	TPtrC startUp(KWSERVShellName);
       
  1026 	_LIT(KWSERVIniFileVarStartUp,"STARTUP");
       
  1027 	WsIniFile->FindVar(KWSERVIniFileVarStartUp,startUp);
       
  1028 
       
  1029 
       
  1030 	TParse fileName;
       
  1031 	_LIT(KWSERVArmShellLocationPattern,"Z:\\sys\\bin\\.EXE");
       
  1032 	User::LeaveIfError(fileName.SetNoWild(startUp,&KWSERVArmShellLocationPattern,NULL));
       
  1033 #if defined(__WINS__)
       
  1034 	TInt err=iShellProcess.Create(fileName.FullName(),shellCmd);
       
  1035 	if (err == KErrNone)
       
  1036 		{
       
  1037 		Request();
       
  1038 		iShellProcess.Resume();
       
  1039 		}
       
  1040 	else
       
  1041 		{
       
  1042 		// Try loading the matching DLL name instead?
       
  1043 		_LIT(KWSERVShellExtension,"Z:.DLL");
       
  1044 		User::LeaveIfError(fileName.Set(KWSERVShellExtension,&startUp,NULL));
       
  1045 		User::LeaveIfError(iLib.Load(fileName.FullName()));
       
  1046 		ShellEntryPoint libFunc=(ShellEntryPoint)iLib.Lookup(1);
       
  1047 		if (!libFunc)
       
  1048 			User::Leave(KErrGeneral);
       
  1049 		TBuf<256> name;
       
  1050 		TInt num=0;
       
  1051 		TInt ret=KErrNone;
       
  1052 		do
       
  1053 			{
       
  1054 			_LIT(KWSERVWinsShellInstanceName,"Shell%d");
       
  1055 			name.Format(KWSERVWinsShellInstanceName,num++);
       
  1056 			ret=iShellThread.Create(name,libFunc,KDefaultStackSize,&shellCmd,&iLib,NULL,KHeapSize,KMaxHeapSize,EOwnerProcess);
       
  1057 			} while(ret==KErrAlreadyExists);
       
  1058 		User::LeaveIfError(ret);
       
  1059 		Request();
       
  1060 		iShellThread.Resume();
       
  1061 		}
       
  1062 #else // not __WINS__
       
  1063 	User::LeaveIfError(iShell.Create(fileName.FullName(),shellCmd));
       
  1064 	Request();
       
  1065 	iShell.Resume();
       
  1066 #endif	
       
  1067 	return;
       
  1068 
       
  1069 	}
       
  1070 
       
  1071 void CWsShellLogon::DoCancel()
       
  1072 	{
       
  1073 #if defined (__WINS__)
       
  1074 	if(iShellThread.Handle())
       
  1075 		iShellThread.LogonCancel(iStatus);
       
  1076 	else
       
  1077 		iShellProcess.LogonCancel(iStatus);
       
  1078 #else
       
  1079 	iShell.LogonCancel(iStatus);
       
  1080 #endif
       
  1081 	}
       
  1082 
       
  1083 void CWsShellLogon::RunL()
       
  1084 	{
       
  1085 	if (iStatus.Int()!=KErrCancel)
       
  1086 		CWsTop::ShellExited();
       
  1087 	}
       
  1088 
       
  1089 void CWsShellLogon::Request()
       
  1090 	{
       
  1091 #if defined (__WINS__)
       
  1092 	if(iShellThread.Handle())
       
  1093 		iShellThread.Logon(iStatus);
       
  1094 	else
       
  1095 		iShellProcess.Logon(iStatus);
       
  1096 #else
       
  1097 	iShell.Logon(iStatus);
       
  1098 #endif
       
  1099 	SetActive();
       
  1100 	}
       
  1101 
       
  1102 #if defined(__WINS__) 
       
  1103 TFullName CWsShellLogon::FullName()
       
  1104 	{
       
  1105 	if(iShellThread.Handle())
       
  1106 		return(iShellThread.FullName());
       
  1107 	else
       
  1108 		return(iShellProcess.FullName());
       
  1109 	}
       
  1110 #else
       
  1111 TFullName CWsShellLogon::FullName()
       
  1112 	{return(iShell.FullName());}
       
  1113 #endif	
       
  1114 
       
  1115 TInt E32Main()
       
  1116 	{
       
  1117 	__UHEAP_MARK;
       
  1118 
       
  1119 	UserSvr::WsRegisterThread();
       
  1120 
       
  1121 	RThread thread;
       
  1122 	// Set wserv's main thread to system permanent
       
  1123 	TInt err;
       
  1124 	err = User::SetCritical(User::ESystemPermanent);
       
  1125 	if (err!=KErrNone)
       
  1126 		{
       
  1127 		WS_PANIC_ALWAYS(EWsPanicFailedToSetThread);
       
  1128 		}
       
  1129 // If in the future wserv becomes multi-threaded,
       
  1130 // we can uncomment the following lines to set any new threads to be system permanent as well.
       
  1131 //	err = User::SetProcessCritical(User::ESystemPermanent); 
       
  1132 //	if (err!=KErrNone)
       
  1133 //		{
       
  1134 //		WS_PANIC_ALWAYS(EWsPanicFailedToSetProcess);
       
  1135 //		}
       
  1136 
       
  1137 	thread.SetPriority(EPriorityMore);
       
  1138 	err = User::RenameThread(KWSERVThreadName);
       
  1139 	if (err==KErrNone)
       
  1140 		{
       
  1141 		thread.Close();
       
  1142 		}
       
  1143 	else
       
  1144 		{
       
  1145 		return err;
       
  1146 		}
       
  1147 
       
  1148 	CTrapCleanup* CleanUpStack=CTrapCleanup::New();	
       
  1149 	TRAP(err, WsIniFile = CIniFile::NewL());
       
  1150 	if (err!=KErrNone)
       
  1151 		{
       
  1152 		WS_PANIC_ALWAYS(EWsPanicFailedToInitialise);
       
  1153 		}	
       
  1154 		
       
  1155 	_LIT(KMemLeakCheck, "MEMLEAKCHECK");
       
  1156 	if (WsIniFile->FindVar(KMemLeakCheck))
       
  1157 		{
       
  1158 		RDebug::Printf("The Memory Leak Check is Enabled => ECOM plugins are preload");
       
  1159 		CWsPluginManager* pm = NULL;
       
  1160 		TRAP(err,pm = CWsPluginManager::NewL());
       
  1161 		delete pm;
       
  1162 		if (err!=KErrNone)
       
  1163 			{
       
  1164 			WS_PANIC_ALWAYS(EWsPanicFailedToInitialise);
       
  1165 			}
       
  1166 		}
       
  1167 
       
  1168 	// Define properties for singleton callbacks. This must only be done ONCE
       
  1169 	// to ensure the properties can't be hijacked.
       
  1170 	gReleaseSingletonsOnExit = ETrue;
       
  1171 	DefineSingletonKey(KOpenWfcInteropCleanupKey);
       
  1172 	DefineSingletonKey(KOpenWfcImplCleanupKey);
       
  1173 	
       
  1174 	TInt startCount;
       
  1175 	do
       
  1176 		{		
       
  1177 		User::Heap().__DbgMarkStart();
       
  1178 		startCount=User::Heap().Count();
       
  1179 		TRAP(err,CWsTop::RunServerL());
       
  1180 		if (err!=KErrNone)
       
  1181 			{
       
  1182 			WS_PANIC_ALWAYS(EWsPanicFailedToInitialise);
       
  1183 			}
       
  1184 		UserSvr::ReleaseEventHook();						
       
  1185 		} while	(CWsTop::NeedsHeapCheckAndRestart(startCount));
       
  1186 		
       
  1187 	REComSession::FinalClose(); // Now we can unload the plugins' dlls
       
  1188 	delete WsIniFile;
       
  1189 	delete CleanUpStack;		
       
  1190 	
       
  1191 	__UHEAP_MARKEND;
       
  1192 	return(err);
       
  1193 	}
       
  1194 
       
  1195