emailservices/emailstore/message_store/server/src/MessageStoreServer.cpp
changeset 0 8466d47a6819
child 8 e1b6206813b4
equal deleted inserted replaced
-1:000000000000 0:8466d47a6819
       
     1 /*
       
     2 * Copyright (c) 2006 Nokia Corporation and/or its subsidiary(-ies). 
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description:  Message store server implementation.
       
    15 *
       
    16 */
       
    17 
       
    18 
       
    19 
       
    20 // ========
       
    21 // INCLUDES
       
    22 // ========
       
    23 
       
    24 #include <e32svr.h>
       
    25 #include <bautils.h>
       
    26 #include <driveinfo.h>
       
    27 #include <s32file.h>
       
    28 
       
    29 #include "MsgStoreTypes.h"
       
    30 #include "MsgStorePropertyKeys.h"
       
    31 #include "EmailStoreUids.hrh"
       
    32 #include "MessageStoreServer.h"
       
    33 #include "MessageStoreSession.h"
       
    34 #include "ContainerStore.h"
       
    35 #include "PropertiesSerializer.h"
       
    36 #include "ShutdownServer.h"
       
    37 //<cmail>
       
    38 #include "ImsPointsecMonitor.h"
       
    39 #include "ImsPointsecObserver.h"
       
    40 #include "emailstorepskeys.h" // Support for on-the-fly upgrade
       
    41 //</cmail>
       
    42 
       
    43 // =========
       
    44 // CONSTANTS
       
    45 // =========
       
    46 
       
    47 _LIT8( KNullDescriptor8, "" );
       
    48 
       
    49 // To support biggest free drive, we have to get rid of hard-coded C: drive
       
    50 //const TDriveNumber KDbDriveNumber = EDriveC;
       
    51 
       
    52 _LIT( KDbFilename, "message_store.db" );
       
    53 
       
    54 const TMsgStoreCounts KInitialCounts = {0, 0};
       
    55 
       
    56 // This should be more than sufficient.
       
    57 const TUint KQuickPropertiesMaxLength = 1024;
       
    58 
       
    59 const TUint KCommandLineSize = 30;
       
    60 
       
    61 _LIT( KUninstallParameter, "IMS_UNINSTALL" );
       
    62 _LIT( KImsUninstaller, "IMS Uninstaller" );
       
    63 _LIT( KUpgradeDetectionFile, "c:\\System\\EsIms\\canary.txt" );
       
    64 _LIT16( KDriveToUseFile, "db_drive.cfg" );
       
    65 //_LIT( KMsgStorePrivateDir, "c:\\Private\\200029e1\\" );
       
    66 
       
    67 //const TChar KColon(':');
       
    68 
       
    69 // SID list
       
    70 // This is the list of secure Ids that are allowed to use the message store.  This list must be terminated
       
    71 // with zero.
       
    72 
       
    73 /*
       
    74 const TUint32 KAllowedSecureIds[] =
       
    75         {
       
    76         0x200029E4,  // bridge process
       
    77         0x10274F51,  // IMS process
       
    78         0x1000EAEA,  // test automation executable
       
    79         0x20009C56,  // another automation test executable
       
    80         0x200029E6,  // message store exerciser
       
    81         0x20003C0A,
       
    82         0x20003C19,
       
    83         0x101FD64C,  // Idle server (for active idle plugin)
       
    84         0xA0002879,  // Native Composer Screen
       
    85         0x101F9A02,	 // DMHostServer1
       
    86 		0x101F9A03,	 // DMHostServer2
       
    87 		0x101F9A04,	 // DMHostServer3
       
    88 		0x101F9A05,	 // DMHostServer4
       
    89 
       
    90         // UNIT TESTERS
       
    91 #ifdef _DEBUG
       
    92         0x043ECF25,  // message store unit tester
       
    93         0x200029EC,
       
    94         0x200029EE,
       
    95         0x200029F0,
       
    96         0x200029F1,
       
    97         0x200029F2,
       
    98         0x200029F3,
       
    99         0x20004205,
       
   100 #endif
       
   101 
       
   102         0
       
   103         }; // end KAllowedSecureIds
       
   104 */
       
   105 
       
   106 // -----------------------------------------------------------------------------
       
   107 // DoUninstallL
       
   108 // Remove the files in private directory.
       
   109 // -----------------------------------------------------------------------------
       
   110 static void DoUninstallL()
       
   111     {
       
   112 	RFs fs;
       
   113     if( fs.Connect() == KErrNone )
       
   114         {
       
   115         if( ! BaflUtils::FileExists( fs, KUpgradeDetectionFile ) )
       
   116             {
       
   117         	// This is a full uninstallation because the upgrade detection file
       
   118         	// does not exist !!
       
   119             TFileName privatePath;
       
   120             fs.PrivatePath( privatePath );
       
   121             
       
   122             CFileMan* fm = CFileMan::NewL( fs );
       
   123             CleanupStack::PushL( fm );
       
   124             TInt err = fm->RmDir( privatePath );
       
   125             CleanupStack::PopAndDestroy( fm );
       
   126             } // end if
       
   127             
       
   128         fs.Close();
       
   129         } // end if
       
   130 }
       
   131 
       
   132 // ==========================================================================
       
   133 // Server startup code
       
   134 // ==========================================================================
       
   135 
       
   136 // Perform all server initialisation, in particular creation of the
       
   137 // scheduler and server and then run the scheduler
       
   138 //
       
   139 static void RunServerL( TBool aThreadRendezvous )
       
   140   {
       
   141   // naming the server thread after the server helps to debug panics
       
   142   User::LeaveIfError( User::RenameThread( KMsgStoreServerName ) );
       
   143 
       
   144   // create and install the active scheduler we need
       
   145   CActiveScheduler* scheduler = new (ELeave) CActiveScheduler();
       
   146   CleanupStack::PushL( scheduler );
       
   147   CActiveScheduler::Install( scheduler );
       
   148   
       
   149   // Examine the command line parameters, to determine whether to
       
   150   // run the server as normal, or to perform the uninstall operation
       
   151   // and exit.
       
   152   
       
   153   TBuf<KCommandLineSize> commandLine;
       
   154   if( User::CommandLineLength() > 0 && User::CommandLineLength() < KCommandLineSize )
       
   155       {        
       
   156       User::CommandLine( commandLine );
       
   157       }
       
   158   
       
   159   // If the executable was launched with the "IMS_UNINSTALL" parameter then do not
       
   160   // launch the server, but just performs necessary uninstallation tasks.
       
   161   if( commandLine.Length() > 0 && commandLine.Compare( KUninstallParameter ) == 0 )
       
   162       {
       
   163 	  // naming the server thread after the server helps to debug panics
       
   164       User::RenameThread( KImsUninstaller );
       
   165 
       
   166       // This is an uninstall.  Do not run the server.
       
   167       DoUninstallL();
       
   168       }
       
   169   else
       
   170   {
       
   171 	  // Create the upgrade detection file, if necessary.
       
   172       RFs fs;
       
   173       if( (fs.Connect() == KErrNone) && !BaflUtils::FileExists( fs, KUpgradeDetectionFile ) )
       
   174       {            
       
   175     	  TRAP_IGNORE( /*result,*/ BaflUtils::EnsurePathExistsL( fs, KUpgradeDetectionFile ) );
       
   176 	        
       
   177     	  RFile file;
       
   178     	  /*result =*/ file.Create( fs, KUpgradeDetectionFile, EFileWrite );
       
   179     	  file.Close();
       
   180 
       
   181     	  fs.Close();
       
   182       } // end if
       
   183 
       
   184 	  // create the server (leave it on the cleanup stack)
       
   185 	  CMessageStoreServer* server = CMessageStoreServer::NewLC();
       
   186 	
       
   187 	  // Initialisation complete, now signal the client
       
   188 	  if( aThreadRendezvous )
       
   189 	    {    
       
   190 	    RThread::Rendezvous( KErrNone );
       
   191 	    }
       
   192 	  else
       
   193 	    {
       
   194 	    RProcess::Rendezvous( KErrNone );    
       
   195 	    }
       
   196 	  
       
   197 	  // Ready to run
       
   198 	  // Start wait loop, will return when server is shutdown
       
   199 	  CActiveScheduler::Start();
       
   200 	  
       
   201 	  // Cleanup the server
       
   202 	  CleanupStack::PopAndDestroy( server );
       
   203   }
       
   204 
       
   205   // Cleanup scheduler after shutdown
       
   206   CleanupStack::PopAndDestroy( scheduler );
       
   207 
       
   208   __LOG_LEAKED_OBJECTS
       
   209   
       
   210   } // end RunServerL
       
   211 
       
   212 // ==========================================================================
       
   213 // Server thread main function
       
   214 // ==========================================================================
       
   215 EXPORT_C TInt MessageStoreServerThreadFunction( TAny* aParams )
       
   216   {
       
   217   __UHEAP_MARK;
       
   218   CTrapCleanup* cleanup = CTrapCleanup::New();
       
   219 
       
   220   TInt ret = KErrNoMemory;
       
   221   if( cleanup )
       
   222     {
       
   223 	// At one time, Message Store runs as a dll with Bridge process, but it is
       
   224 	// decided that MsgStore running as a seperate process in case Bridge process
       
   225 	// crashes makes more sense
       
   226 	// (aParams == NULL) is basically to differentiate dll or exe
       
   227     TRAP( ret, RunServerL( (aParams == NULL) ) );
       
   228     delete cleanup;
       
   229     }
       
   230   __UHEAP_MARKEND;
       
   231 
       
   232   return ret;
       
   233   } // end MessageStoreServerThreadFunction
       
   234 
       
   235 // ==========================================================================
       
   236 // RMessagePtr2::Panic() also completes the message. This is:
       
   237 // (a) important for efficient cleanup within the kernel
       
   238 // (b) a problem if the message is completed a second time
       
   239 // ==========================================================================
       
   240 void PanicClient(const RMessagePtr2& aMessage, TMessageStorePanic aPanic)
       
   241   {
       
   242   _LIT( KPanic, "MessageStoreServer" );
       
   243   aMessage.Panic( KPanic, aPanic);
       
   244   } // end PanicClient
       
   245 
       
   246 // ======================
       
   247 // METHOD IMPLEMENTATIONS
       
   248 // ======================
       
   249 
       
   250 // ==========================================================================
       
   251 // FUNCTION: NewLC
       
   252 // ==========================================================================
       
   253 CMessageStoreServer* CMessageStoreServer::NewLC()
       
   254   {
       
   255   CMessageStoreServer* self = new (ELeave) CMessageStoreServer();
       
   256   CleanupStack::PushL( self );
       
   257   self->ConstructL();
       
   258   return self;
       
   259   } // end NewLC
       
   260 
       
   261 // ==========================================================================
       
   262 // FUNCTION: Constructor
       
   263 // ==========================================================================
       
   264 CMessageStoreServer::CMessageStoreServer()
       
   265   :CPolicyServer( 0, KMessageStorePolicy, ESharableSessions )
       
   266   {
       
   267   __LOG_CONSTRUCT( "msg", "CMessageStoreServer" )
       
   268   
       
   269   iLockedByBackupRestore = EFalse;
       
   270   iLockedByPointSec = EFalse;
       
   271   iLockedByDriveMonitor = EFalse;
       
   272   
       
   273   } // end constructor
       
   274 
       
   275 // ==========================================================================
       
   276 // FUNCTION: ConstructL
       
   277 // 2nd phase construction - ensure the timer and server objects are running
       
   278 // ==========================================================================
       
   279 void CMessageStoreServer::ConstructL()
       
   280     {
       
   281     __LOG_ENTER( "ConstructL" )
       
   282 
       
   283 	// Log filename for this process.
       
   284 	RProcess thisProcess;
       
   285     __LOG_BLOCK( TFileName processName = thisProcess.FileName(); )
       
   286 	__LOG_WRITE_FORMAT1_INFO( "Filename: %S", &processName );
       
   287 	thisProcess.Close();
       
   288 	
       
   289     StartL( KMsgStoreServerName );
       
   290 
       
   291     iShutdown = CShutdownServer::NewL();
       
   292     //starts the PointsecMonitor
       
   293     iPointsecMonitor = CImsPointsecMonitor::NewL( *this );
       
   294     //must check if PointSec has locked the system or not,
       
   295     //only create the container store if PointSec is NOT locked.
       
   296     
       
   297     // This will be used to monitor the drive where message store db is located.
       
   298     iStoreDriveMonitor = CStoreDriveMonitor::NewL( *this );
       
   299     
       
   300     if ( iPointsecMonitor->IsServiceAllowed() )
       
   301         {
       
   302         //PointSec does NOT have the device locked, so we can start initialization
       
   303         // Construct an instance of the container store to be shared across all message server sessions.
       
   304         CreateContainerStoreL();
       
   305     
       
   306         // Create the inbox/outbox/draft/sent folders, if needed.
       
   307         CreatePredefinedFoldersIfNeededL();
       
   308         }
       
   309     else
       
   310         {
       
   311         __LOG_WRITE_INFO("PointSec has system locked! Database NOT initialized!")
       
   312         //PointSec has the device locked, DO NOT initialize the database
       
   313         iLockedByPointSec = ETrue;
       
   314         }
       
   315     // Register to receive backup/restore notifications.
       
   316     iBackupRestoreNotifier = CBackupRestoreNotifier::NewL( *this );
       
   317     
       
   318     // Ensure that the server still exits even if the 1st client fails to connect.
       
   319     // This time isn't started until after the code above, so that the shutdown timer isn't
       
   320     // running while the database is possibly being created or wiped.
       
   321 //    iShutdown->Start();
       
   322 
       
   323     // Support for on-the-fly upgrade
       
   324     // Watch for KProperty_EmailStore_Upgrade property. When set to our UID3/SECUREID,
       
   325     // then, this server should stop.
       
   326     RProcess process;
       
   327 	CleanupClosePushL( process ); //+process
       
   328     TSecurityPolicy readPolicy( ECapabilityReadDeviceData );
       
   329     TSecurityPolicy writePolicy( ECapabilityWriteDeviceData );
       
   330     iUpgradePropertyWatcher = CPSIntPropertyWatcher::NewL( this );
       
   331     iUpgradePropertyWatcher->StartL( KEmailStoreUpgradePSCategory,
       
   332                                      KProperty_EmailStore_Upgrade,
       
   333                                      process.SecureId(),
       
   334                                      /*ETrue*/EFalse,
       
   335                                      readPolicy,
       
   336                                      writePolicy ); 
       
   337     CleanupStack::PopAndDestroy(); //-process
       
   338         
       
   339     __LOG_EXIT
       
   340     } // end ConstructL
       
   341 
       
   342 // ==========================================================================
       
   343 // FUNCTION: Destructor
       
   344 // ==========================================================================
       
   345 CMessageStoreServer::~CMessageStoreServer()
       
   346   {
       
   347   delete iUpgradePropertyWatcher;
       
   348   delete iStoreDriveMonitor;
       
   349   delete iShutdown;
       
   350   delete iMessageStore;
       
   351   iMessageStore = NULL;
       
   352   delete iBackupRestoreNotifier;
       
   353   delete iPointsecMonitor;
       
   354   iSessions.ResetAndDestroy();
       
   355   __LOG_DESTRUCT
       
   356   } // end destructor
       
   357 
       
   358 // ==========================================================================
       
   359 // FUNCTION: NewSessionL
       
   360 // Create a new client session.
       
   361 // ==========================================================================
       
   362 CSession2* CMessageStoreServer::NewSessionL(const TVersion& aVersion, const RMessage2&) const
       
   363     {
       
   364     __LOG_ENTER( "NewSessionL" )
       
   365 
       
   366     if( aVersion.iMajor != KMsgStoreMajorVersion ||
       
   367         aVersion.iMinor != KMsgStoreMinorVersion ||
       
   368         aVersion.iBuild != KMsgStoreBuild )
       
   369         {
       
   370         __LOG_WRITE_ERROR( "Session version mismatch" )
       
   371         User::Leave( KErrNotSupported );
       
   372         } // end if
       
   373 
       
   374     // Construct a new session, passing it a pointer to the server object.  This function
       
   375     // is const, so the const-ness must be cast away from the this pointer.
       
   376     CSession2* returnValue = new (ELeave) CMessageStoreSession( *const_cast<CMessageStoreServer*>(this) );
       
   377 
       
   378     __LOG_EXIT
       
   379     return returnValue;
       
   380 
       
   381     } // end NewSessionL
       
   382 
       
   383 // ==========================================================================
       
   384 // FUNCTION: AddSession
       
   385 // A new session is being created
       
   386 // Cancel the shutdown timer if it was running
       
   387 // ==========================================================================
       
   388 void CMessageStoreServer::AddSession( CMessageStoreSession* aSession )
       
   389   {
       
   390   __LOG_ENTER( "AddSession" )
       
   391   iSessions.Append( aSession );
       
   392 
       
   393   // A sesssion was added, so the shutdown timer can be stopped.
       
   394 //  iShutdown->Stop();
       
   395   __LOG_EXIT
       
   396   } // end AddSession
       
   397 
       
   398 // ==========================================================================
       
   399 // FUNCTION: DropSession
       
   400 // A session is being destroyed
       
   401 // Start the shutdown timer if it is the last session.
       
   402 // ==========================================================================
       
   403 void CMessageStoreServer::DropSession( CMessageStoreSession* aSession )
       
   404     {
       
   405     __LOG_ENTER( "DropSession" )
       
   406 
       
   407     // Find the current session in the list of sessions.
       
   408     TInt index = iSessions.Find( aSession );
       
   409 
       
   410     if( index == KErrNotFound )
       
   411         {
       
   412         // This should never happen.
       
   413         __LOG_WRITE_ERROR( "ERROR! SESSION NOT FOUND!" );
       
   414         }
       
   415     else
       
   416         {
       
   417         // Remove the session from the list of sessions.
       
   418         iSessions.Remove( index );
       
   419         } // end if
       
   420 
       
   421     // If this was the last session to this server then start the shutdown timer with no delay.  This
       
   422     // will immediately shut down the server, unless the container store is currently performing
       
   423     // background operations.
       
   424 //    if( iSessions.Count() == 0 )
       
   425 //        {
       
   426 //        iShutdown->Start( 0 );
       
   427 //        } // end if
       
   428 
       
   429     __LOG_EXIT
       
   430     } // end DropSession
       
   431 
       
   432 
       
   433 
       
   434 // ==========================================================================
       
   435 // FUNCTION: CreateContainerStoreL
       
   436 // ==========================================================================
       
   437 void CMessageStoreServer::CreateContainerStoreL()
       
   438     {
       
   439     TDriveNumber drive( EDriveC );
       
   440     if ( GetDriveL( drive ) == KErrNotFound )
       
   441         {
       
   442         FindBiggestCapacityDriveL( drive );
       
   443         }
       
   444     //set again the drive to be monitored in case is different than previous
       
   445     iStoreDriveMonitor->SetDriveL( drive );
       
   446     
       
   447     if ( iStoreDriveMonitor->IsDrivePresent() )
       
   448         {
       
   449     iMessageStore = CContainerStore::NewL( KDbFilename,
       
   450                                            drive,
       
   451                                            *this,
       
   452                                            *iShutdown,
       
   453                                            Priority() - 1);  // lower than server
       
   454         }
       
   455     else
       
   456         {
       
   457         iLockedByDriveMonitor = ETrue;
       
   458         }
       
   459     
       
   460     // monitor the message store drive
       
   461     iStoreDriveMonitor->WaitForChange();
       
   462 
       
   463     } // end CreateContainerStoreL
       
   464 
       
   465 
       
   466 // ==========================================================================
       
   467 // FUNCTION: MessageStoreL
       
   468 // ==========================================================================
       
   469 CContainerStore& CMessageStoreServer::MessageStoreL()
       
   470   {
       
   471   if( !iMessageStore )
       
   472     {
       
   473     // A backup or restore is in progress.
       
   474     // Or PointSec has locked the device.
       
   475     User::Leave( KErrInUse );
       
   476     } // end if
       
   477 
       
   478   return *iMessageStore;
       
   479   } // end MessageStoreL
       
   480 
       
   481 // ==========================================================================
       
   482 // FUNCTION: CreatePredefinedFoldersIfNeededL
       
   483 // ==========================================================================
       
   484 void CMessageStoreServer::CreatePredefinedFoldersIfNeededL()
       
   485   {
       
   486   __LOG_ENTER( "CreatePredefinedFoldersIfNeededL" )
       
   487 
       
   488   // Create predefined folders.
       
   489   if ( iMessageStore )
       
   490       {
       
   491       iMessageStore->CreatePredefinedContainerIfNeededL(
       
   492               KMsgStoreRootMailBoxId, EMsgStoreMailBoxBits, KMsgStoreInvalidId,
       
   493               KNullDescriptor8 );
       
   494       }
       
   495 
       
   496   __LOG_EXIT
       
   497   } // end CreatePredefinedFoldersIfNeededL
       
   498 
       
   499 // ==========================================================================
       
   500 // FUNCTION: QuickPropertiesAndCountsL
       
   501 // This function traverses the properties, looking for the "quick" properties.
       
   502 // This is not part of the container store in order to keep the container
       
   503 // store more generic, without any message-specific logic.
       
   504 // ==========================================================================
       
   505 void CMessageStoreServer::QuickPropertiesAndCountsL( TContainerId  aType,
       
   506 													 const TDesC8& aProperties,
       
   507 													 RBuf8&        aQuickProperties,
       
   508 													 TDes8&        aCounts ) const
       
   509   {
       
   510   __LOG_ENTER( "QuickPropertiesAndCountsL" )
       
   511 
       
   512   TMsgStoreCounts counts;
       
   513 
       
   514   counts.iMessagesCount = 0;
       
   515   counts.iUnreadCount   = 0;
       
   516   
       
   517     // Quick properties and message counts are for message containers only.
       
   518   if( (aType & EMsgStoreContainerMask) == EMsgStoreMessageBits )
       
   519     {
       
   520     // This container should increment the iMessageCount field of the parent container's child counts.
       
   521     counts.iMessagesCount = 1;
       
   522 
       
   523     // Iterator through the properties, looking for the quick properties.
       
   524 
       
   525     TPropertiesDeserializer propertiesDeserializer( aProperties );
       
   526     TPropertiesSerializer   quickPropertiesSerializer( aQuickProperties );
       
   527 
       
   528     TBool moreProperties = propertiesDeserializer.First();
       
   529 
       
   530     TBool flagsFound       = EFalse;
       
   531     TBool completedAtFound = EFalse;
       
   532     TBool receivedAtFound  = EFalse;
       
   533     TBool replyByFound     = EFalse;
       
   534     TBool sizeFound        = EFalse;
       
   535 
       
   536     while( moreProperties && !(flagsFound && completedAtFound && receivedAtFound && replyByFound && sizeFound) )
       
   537         {
       
   538         TBool addProperty = EFalse;
       
   539 
       
   540         if( !flagsFound && (propertiesDeserializer.Name().Compare( KMsgStorePropertyFlags ) == 0) )
       
   541             {
       
   542             addProperty = ETrue;
       
   543             flagsFound  = ETrue;
       
   544 
       
   545             TPckgBuf<TUint32> flagsPckg;
       
   546             flagsPckg.Copy( propertiesDeserializer.Value() );
       
   547             
       
   548             // The message is considered read if either Read flag is set.
       
   549             if ((flagsPckg() & (EMsgStoreFlag_Read_Locally | EMsgStoreFlag_Read) ) == 0)
       
   550                 {
       
   551                 // This container should increment the iUnreadCount field of the parent
       
   552                 // container's child counts.
       
   553                 __LOG_WRITE_INFO( "is unread" );
       
   554                 counts.iUnreadCount = 1;
       
   555                 } // end if
       
   556             }
       
   557         else if( !completedAtFound && (propertiesDeserializer.Name().Compare( KMsgStorePropertyCompletedAt ) == 0) )
       
   558             {
       
   559             addProperty      = ETrue;
       
   560             completedAtFound = ETrue;
       
   561             }
       
   562         else if( !receivedAtFound && (propertiesDeserializer.Name().Compare( KMsgStorePropertyReceivedAt ) == 0) )
       
   563             {
       
   564             addProperty     = ETrue;
       
   565             receivedAtFound = ETrue;
       
   566             }
       
   567         else if( !replyByFound && (propertiesDeserializer.Name().Compare( KMsgStorePropertyReplyBy ) == 0) )
       
   568             {
       
   569             addProperty  = ETrue;
       
   570             replyByFound = ETrue;
       
   571             } // end if
       
   572         else if( !sizeFound && (propertiesDeserializer.Name().Compare( KMsgStorePropertyMessageSizeOnServer ) == 0) )
       
   573             {
       
   574             addProperty  = ETrue;
       
   575             sizeFound = ETrue;
       
   576             } // end if
       
   577 
       
   578         if( addProperty )
       
   579             {
       
   580             // This is a quick property!
       
   581 
       
   582             __LOG_WRITE8_FORMAT1_INFO( "found %S", &propertiesDeserializer.Name() );
       
   583 
       
   584             quickPropertiesSerializer.AddPropertyL( propertiesDeserializer.Name(),
       
   585                                                     propertiesDeserializer.Type(),
       
   586                                                     propertiesDeserializer.Value() );
       
   587 
       
   588             } // end if
       
   589 
       
   590         moreProperties = propertiesDeserializer.Next();
       
   591 
       
   592         } // end while
       
   593 
       
   594     } // end if
       
   595 
       
   596     __LOG_WRITE8_FORMAT2_INFO( "counts total=%i unread=%i", counts.iMessagesCount, counts.iUnreadCount )
       
   597     TPckg<TMsgStoreCounts> countsPckg(counts);
       
   598     aCounts.Copy( countsPckg );
       
   599 
       
   600     __LOG_EXIT
       
   601 
       
   602   } // end QuickPropertiesAndCountsL
       
   603 
       
   604 // ==========================================================================
       
   605 // FUNCTION: SortableFieldsL
       
   606 // This function retrieves some sortable fields from a serialized quick properties.
       
   607 // ==========================================================================
       
   608 void CMessageStoreServer::SortableFieldsL( const TDesC8&             aQuickProperties, 
       
   609                                            const TDesC8&             aProperties,
       
   610                                            RMsgStoreSortableFields&  aSortableFields ) const
       
   611     {
       
   612     __LOG_ENTER( "SortableFieldsL" )
       
   613     
       
   614     aSortableFields.iFlags = 0;
       
   615     aSortableFields.iReceivedDate = 0;
       
   616     aSortableFields.iSizeOnServer = 0;
       
   617     
       
   618     TPropertiesDeserializer qpDeserializer( aQuickProperties );
       
   619     
       
   620     TBool moreProperties = qpDeserializer.First();
       
   621 
       
   622     TBool flagsFound       = EFalse;
       
   623     TBool receivedAtFound  = EFalse;
       
   624     TBool sizeFound        = EFalse;
       
   625 
       
   626     while( moreProperties && !(flagsFound && receivedAtFound && sizeFound) )
       
   627         {
       
   628         if( !flagsFound && (qpDeserializer.Name().Compare( KMsgStorePropertyFlags ) == 0) )
       
   629             {
       
   630             flagsFound  = ETrue;
       
   631             
       
   632             TPckgBuf<TUint32> flagsPckg;
       
   633             flagsPckg.Copy( qpDeserializer.Value() );
       
   634             
       
   635             aSortableFields.iFlags = flagsPckg();
       
   636             }
       
   637         else if( !receivedAtFound && (qpDeserializer.Name().Compare( KMsgStorePropertyReceivedAt ) == 0) )
       
   638             {
       
   639             receivedAtFound = ETrue;
       
   640             
       
   641             TPckgBuf<TInt64> receivedDatePckg;
       
   642             receivedDatePckg.Copy( qpDeserializer.Value() );
       
   643             
       
   644             aSortableFields.iReceivedDate = receivedDatePckg();
       
   645             }
       
   646         else if( !sizeFound && (qpDeserializer.Name().Compare( KMsgStorePropertyMessageSizeOnServer ) == 0) )
       
   647             {
       
   648             sizeFound = ETrue;
       
   649             
       
   650             TPckgBuf<TUint32> sizePckg;
       
   651             sizePckg.Copy( qpDeserializer.Value() );
       
   652             
       
   653             aSortableFields.iSizeOnServer = sizePckg();
       
   654             } // end if
       
   655 
       
   656         moreProperties = qpDeserializer.Next();
       
   657         } // end while
       
   658     
       
   659     //get the "subject" and "from" the from fields
       
   660     TPropertiesDeserializer propDeserializer( aProperties );
       
   661     
       
   662     moreProperties = propDeserializer.First();
       
   663 
       
   664     TBool subjectFound     = EFalse;
       
   665     TBool fromFound        = EFalse;
       
   666     TBool toFound          = EFalse;
       
   667 
       
   668     while( moreProperties && !(subjectFound && fromFound && toFound) )
       
   669         {
       
   670         if( !subjectFound && (propDeserializer.Name().Compare( KMsgStorePropertySubject ) == 0) )
       
   671             {
       
   672             RBuf subject;
       
   673             CleanupClosePushL( subject );
       
   674             
       
   675             TPtrC8ToRBuf16L( propDeserializer.Value(), subject );
       
   676             
       
   677             //get rid of the "Alpha:" "AlphaAlpha:" "AlphaAlphaAlpha:"
       
   678             TPtr16 ptr = subject.MidTPtr(0);
       
   679             TBool prefixFound = ETrue;
       
   680             TChar KColon(':');
       
   681             const TUint KPos = 3;
       
   682             while ( prefixFound )
       
   683                 {
       
   684                 ptr.TrimLeft();
       
   685                 TInt pos = ptr.Locate( KColon );
       
   686        
       
   687                 if ( pos > 0 && pos <= KPos )
       
   688                     {
       
   689                     for ( TInt i = 0; i < pos; i++ )
       
   690                         {
       
   691                         TChar ch = ptr[i];
       
   692                         if ( !ch.IsAlpha() )
       
   693                             {
       
   694                             prefixFound = EFalse;
       
   695                             break;
       
   696                             }                    
       
   697                         }
       
   698                     if ( prefixFound )
       
   699                         {
       
   700                         ptr = ptr.Mid( pos + 1 );
       
   701                         __LOG_WRITE_INFO("Prefix ':' found.")
       
   702                         }
       
   703                     }
       
   704                 else
       
   705                     {
       
   706                     prefixFound = EFalse;
       
   707                     }
       
   708                 }
       
   709             
       
   710             aSortableFields.iSubject.Create( ptr );
       
   711             
       
   712             __LOG_WRITE_FORMAT1_INFO( "subject=%S", &aSortableFields.iSubject )
       
   713             
       
   714             CleanupStack::PopAndDestroy( &subject );
       
   715             subjectFound = ETrue;
       
   716             }
       
   717     
       
   718     //get the from
       
   719         else if( !fromFound && (propDeserializer.Name().Compare( KMsgStorePropertyFrom ) == 0) )
       
   720             {
       
   721             TPropertiesDeserializer addrDeserializer( propDeserializer.Value() );
       
   722             RBuf displayName;
       
   723             CleanupClosePushL( displayName );
       
   724             if ( addrDeserializer.Find( KMsgStorePropertyDisplayName ) )
       
   725                 {
       
   726                 TPtrC8ToRBuf16L( addrDeserializer.Value(), displayName );
       
   727                 }
       
   728             RBuf emailAddr;
       
   729             CleanupClosePushL( emailAddr );
       
   730             if ( addrDeserializer.Find( KMsgStorePropertyEmailAddress ) )
       
   731                 {
       
   732                 TPtrC8ToRBuf16L( addrDeserializer.Value(), emailAddr );
       
   733                 }
       
   734             
       
   735             aSortableFields.iFrom.Create( displayName.Length() + emailAddr.Length() );
       
   736             aSortableFields.iFrom.Copy( displayName );
       
   737             aSortableFields.iFrom.Append( emailAddr );
       
   738             
       
   739             CleanupStack::PopAndDestroy( &emailAddr );
       
   740             CleanupStack::PopAndDestroy( &displayName );
       
   741             fromFound = ETrue;
       
   742             }
       
   743         //get the to
       
   744         else if( !toFound && (propDeserializer.Name().Compare( KMsgStorePropertyTo ) == 0) )
       
   745             {
       
   746             TPropertiesDeserializer addrDeserializer( propDeserializer.Value() );
       
   747             RBuf displayName;
       
   748             CleanupClosePushL( displayName );
       
   749             if ( addrDeserializer.Find( KMsgStorePropertyDisplayName ) )
       
   750                 {
       
   751                 TPtrC8ToRBuf16L( addrDeserializer.Value(), displayName );
       
   752                 }
       
   753             RBuf emailAddr;
       
   754             CleanupClosePushL( emailAddr );
       
   755             if ( addrDeserializer.Find( KMsgStorePropertyEmailAddress ) )
       
   756                 {
       
   757                 TPtrC8ToRBuf16L( addrDeserializer.Value(), emailAddr );
       
   758                 }
       
   759             
       
   760             aSortableFields.iTo.Create( displayName.Length() + emailAddr.Length() );
       
   761             aSortableFields.iTo.Copy( displayName );
       
   762             aSortableFields.iTo.Append( emailAddr );
       
   763             
       
   764             CleanupStack::PopAndDestroy( &emailAddr );
       
   765             CleanupStack::PopAndDestroy( &displayName );
       
   766             toFound = ETrue;
       
   767             }
       
   768         moreProperties = propDeserializer.Next();
       
   769         }
       
   770 
       
   771     __LOG_EXIT
       
   772     
       
   773     }
       
   774 
       
   775 // ==========================================================================
       
   776 // FUNCTION: LengthsL
       
   777 // ==========================================================================
       
   778 void CMessageStoreServer::LengthsL( TUint& aCountsLength,
       
   779                                     TUint& aQuickPropertiesMaxLength ) const
       
   780     {
       
   781     aCountsLength = KMsgStoreCountsLength;
       
   782 
       
   783     aQuickPropertiesMaxLength = KQuickPropertiesMaxLength;
       
   784 
       
   785     } // end LengthsL
       
   786 
       
   787 // ==========================================================================
       
   788 // FUNCTION: IncrementParentCounts
       
   789 // ==========================================================================
       
   790 void CMessageStoreServer::IncrementParentCounts( TDes8& aParentCounts, const TDesC8& aChildCounts ) const
       
   791   {
       
   792   __LOG_ENTER_SUPPRESS( "IncrementParentCounts" )
       
   793   TMsgStoreCounts*       parentCounts = const_cast<TMsgStoreCounts*>( reinterpret_cast<const TMsgStoreCounts*>( aParentCounts.Ptr() ) );
       
   794   const TMsgStoreCounts* childCounts  = reinterpret_cast<const TMsgStoreCounts*>( aChildCounts.Ptr() );
       
   795 
       
   796   __LOG_WRITE_FORMAT4_INFO("p.total=%d, p.unread=%d, c.total=%d, c.unread=%d", parentCounts->iMessagesCount, parentCounts->iUnreadCount, childCounts->iMessagesCount, childCounts->iUnreadCount )
       
   797   
       
   798   parentCounts->iMessagesCount += childCounts->iMessagesCount;
       
   799   parentCounts->iUnreadCount   += childCounts->iUnreadCount;
       
   800   } // end IncrementParentCounts
       
   801 
       
   802 // ==========================================================================
       
   803 // FUNCTION: DecrementParentCounts
       
   804 // ==========================================================================
       
   805 void CMessageStoreServer::DecrementParentCounts( TDes8& aParentCounts, const TDesC8& aChildCounts ) const
       
   806   {
       
   807   TMsgStoreCounts*       parentCounts = const_cast<TMsgStoreCounts*>( reinterpret_cast<const TMsgStoreCounts*>( aParentCounts.Ptr() ) );
       
   808   const TMsgStoreCounts* childCounts  = reinterpret_cast<const TMsgStoreCounts*>( aChildCounts.Ptr() );
       
   809 
       
   810   parentCounts->iMessagesCount -= childCounts->iMessagesCount;
       
   811   parentCounts->iUnreadCount   -= childCounts->iUnreadCount;
       
   812   } // end DecrementParentCounts
       
   813 
       
   814 // ==========================================================================
       
   815 // FUNCTION: InitializeCounts
       
   816 // ==========================================================================
       
   817 void CMessageStoreServer::InitializeCounts( TDes8& aCounts ) const
       
   818   {
       
   819   TPckg<TMsgStoreCounts> countsPckg( KInitialCounts );
       
   820   aCounts.Copy( countsPckg );
       
   821   } // end InitializeCounts
       
   822 
       
   823   
       
   824 void CMessageStoreServer::LogCounts( const TDesC& aDescription, const TDesC8& __LOG_BLOCK(aCounts) ) const
       
   825     {
       
   826     __LOG_ENTER_SUPPRESS( "LogCounts" )
       
   827     
       
   828     TInt length( aDescription.Length() );                   // noop usage to suppress compilation warning, "INFO" log level not enabled.
       
   829     
       
   830     __LOG_BLOCK( const TMsgStoreCounts* counts  = reinterpret_cast<const TMsgStoreCounts*>( aCounts.Ptr() ); )
       
   831     __LOG_WRITE_FORMAT3_INFO( "%S total=%d unread=%d", &aDescription, counts->iMessagesCount, counts->iUnreadCount )
       
   832     }
       
   833 
       
   834 
       
   835 // ==========================================================================
       
   836 // FUNCTION: WipeEverythingL
       
   837 // ==========================================================================
       
   838 void CMessageStoreServer::WipeEverythingL()
       
   839   {
       
   840   __LOG_ENTER( "WipeEverythingL" )
       
   841 
       
   842   for( TInt i = 0; i < iSessions.Count(); i++ )
       
   843     {
       
   844     iSessions[i]->ContainerStoreUnavailable();
       
   845     } // end if
       
   846 
       
   847     if( !iMessageStore )
       
   848         {
       
   849         // A backup/restore is in progress.  Wipe after it completes.
       
   850         iWipeAfterBackupRestore = ETrue;
       
   851         }
       
   852     else
       
   853         {
       
   854         delete iMessageStore;
       
   855         iMessageStore = NULL;
       
   856 
       
   857         // Wipe the message store files in the private area.  (Do not wipe the
       
   858         // entire private area since other threads may be storing files in
       
   859         // the area.)
       
   860 
       
   861         // Note: when the message store server was changed from a process to a
       
   862         //       thread, it would have been nice to move all of the message store
       
   863         //       files to a specific subdirectory in the private area, but that
       
   864         //       change would have been backwards incompatible.
       
   865         
       
   866         TDriveNumber drive( EDriveC );
       
   867         if ( GetDriveL( drive ) == KErrNotFound ) drive = EDriveC;
       
   868         TInt result = CContainerStore::WipeEverything( KDbFilename,
       
   869                                                        drive );
       
   870 
       
   871         TRAP( result, CreateContainerStoreL();
       
   872                       CreatePredefinedFoldersIfNeededL() );
       
   873 
       
   874         if( result != 0 )
       
   875             {
       
   876             __LOG_WRITE_ERROR( "failed to recreate message store after wipe" )
       
   877 
       
   878             // The server is in a very bad state.  Shut down the server immediately.
       
   879             iShutdown->ShutDownNow();
       
   880             } // end if
       
   881 
       
   882         // Notify observers of wipe event.
       
   883         TMsgStoreEvent event;
       
   884         event.iType        = EMsgStoreDatabaseWiped;
       
   885         event.iId          = KMsgStoreInvalidId;
       
   886         event.iParentId    = KMsgStoreInvalidId;
       
   887         event.iOtherId     = KMsgStoreInvalidId;
       
   888         event.iFlags       = KMsgStoreFlagsNotFound;
       
   889 
       
   890         for( TInt i = 0; i < iSessions.Count(); i++ )
       
   891             {
       
   892             iSessions[i]->ContainerStoreAvailable();
       
   893             iSessions[i]->SendEventToObserver( event );
       
   894             } // end if
       
   895 
       
   896         } // end if
       
   897 
       
   898   __LOG_EXIT
       
   899   } // end WipeEverythingL
       
   900 
       
   901 // ==========================================================================
       
   902 // FUNCTION: BackupOrRestoreInProgress
       
   903 // ==========================================================================
       
   904 void CMessageStoreServer::BackupOrRestoreInProgress( TBool /*aIsARestore*/ )
       
   905 {
       
   906     __LOG_ENTER( "BackupOrRestoreInProgress" );
       
   907     
       
   908     SendSystemLockMessage( EMsgStoreBackupOrRestoreInProgress );
       
   909     
       
   910     if (( !iLockedByPointSec ) && ( !iLockedByDriveMonitor ) )
       
   911         {
       
   912         LockSystem();
       
   913         }
       
   914 
       
   915     __LOG_EXIT
       
   916     } // end BackupOrRestoreInProgress
       
   917 
       
   918 // ==========================================================================
       
   919 // FUNCTION: BackupOrRestoreCompleted
       
   920 // ==========================================================================
       
   921 void CMessageStoreServer::BackupOrRestoreCompleted()
       
   922     {
       
   923     __LOG_ENTER( "BackupOrRestoreCompleted" );
       
   924   
       
   925     SendSystemLockMessage( EMsgStoreBackupOrRestoreCompleted );
       
   926       
       
   927     if (( !iLockedByPointSec ) && ( !iLockedByDriveMonitor ) )
       
   928         {
       
   929         TRAP_IGNORE( UnlockSystemL() );
       
   930         }
       
   931     
       
   932     __LOG_EXIT
       
   933 } // end BackupOrRestoreCompleted
       
   934 
       
   935 // ==========================================================================
       
   936 // FUNCTION: PointSecLockStarted
       
   937 // ==========================================================================
       
   938 void CMessageStoreServer::PointSecLockStarted()
       
   939     {
       
   940     __LOG_ENTER( "PointSecLockStarted" );
       
   941     if ( !iLockedByPointSec )
       
   942         {
       
   943         iLockedByPointSec = ETrue;
       
   944         SendSystemLockMessage( EMsgStorePointSecLockStarted );
       
   945         if (( !iLockedByBackupRestore ) && ( !iLockedByDriveMonitor ) )
       
   946             {
       
   947             LockSystem();
       
   948             }
       
   949         }
       
   950     __LOG_EXIT
       
   951     }
       
   952 
       
   953 // ==========================================================================
       
   954 // FUNCTION: PointSecLockEnded
       
   955 // ==========================================================================
       
   956 void CMessageStoreServer::PointSecLockEnded()
       
   957     {
       
   958     __LOG_ENTER( "PointSecLockEnded" );
       
   959     if ( iLockedByPointSec )
       
   960         {
       
   961         iLockedByPointSec = EFalse;
       
   962         SendSystemLockMessage( EMsgStorePointSecLockEnded );
       
   963         if ( ( !iLockedByBackupRestore ) && ( !iLockedByDriveMonitor ) )
       
   964             {
       
   965             TRAP_IGNORE( UnlockSystemL() );
       
   966             }
       
   967         }
       
   968     __LOG_EXIT
       
   969     }
       
   970 
       
   971 // ==========================================================================
       
   972 // FUNCTION: LockSystem
       
   973 // ==========================================================================
       
   974 void CMessageStoreServer::LockSystem()
       
   975     {
       
   976     __LOG_ENTER( "LockSystem" );
       
   977     
       
   978     for( TInt i = 0; i < iSessions.Count(); i++ )
       
   979         {
       
   980         iSessions[i]->ContainerStoreUnavailable();
       
   981         } // end if
       
   982 
       
   983     delete iMessageStore;
       
   984     iMessageStore = NULL;
       
   985     
       
   986     __LOG_EXIT
       
   987     }
       
   988 
       
   989 // ==========================================================================
       
   990 // FUNCTION: UnlockSystemL
       
   991 // ==========================================================================
       
   992 void CMessageStoreServer::UnlockSystemL()
       
   993     {
       
   994     __LOG_ENTER( "UnlockSystemL" );
       
   995     
       
   996     TRAPD( result,
       
   997             CreateContainerStoreL(); CreatePredefinedFoldersIfNeededL(); );
       
   998 
       
   999     if( result != 0 )
       
  1000         {
       
  1001         __LOG_WRITE_ERROR( "failed to recreate message store after system lock" )
       
  1002 
       
  1003         // The server is in a very bad state.  Shut down the server immediately.
       
  1004         iShutdown->ShutDownNow();
       
  1005         }
       
  1006    else if  ( ( !iLockedByBackupRestore ) 
       
  1007            && ( !iLockedByDriveMonitor ) 
       
  1008            && ( !iLockedByPointSec ) )
       
  1009         {
       
  1010 
       
  1011         for( TInt i = 0; i < iSessions.Count(); i++ )
       
  1012             {
       
  1013             iSessions[i]->ContainerStoreAvailable();
       
  1014             } // end if
       
  1015         
       
  1016         if( iWipeAfterBackupRestore )
       
  1017             {
       
  1018             iWipeAfterBackupRestore = EFalse;
       
  1019             WipeEverythingL();
       
  1020             } // end if
       
  1021 
       
  1022         } // end if
       
  1023     
       
  1024     __LOG_EXIT
       
  1025     }
       
  1026     
       
  1027 // ==========================================================================
       
  1028 // FUNCTION: FindBiggestCapacityDrive
       
  1029 //           To locate the internal drive with the biggest available space.
       
  1030 // ========================================================================== 
       
  1031 void CMessageStoreServer::FindBiggestCapacityDriveL( TDriveNumber& aDrive )
       
  1032     {
       
  1033     __LOG_ENTER( "FindBiggestCapacityDrive" );
       
  1034     
       
  1035     RFs fs;
       
  1036     TInt driveToUse( 2 );  // set default drive to C:
       
  1037     
       
  1038     if( fs.Connect() == KErrNone )
       
  1039         {
       
  1040         CleanupClosePushL( fs );               //+fs
       
  1041         TDriveList driveList;
       
  1042         fs.DriveList( driveList );
       
  1043         TInt64 highest( 0 );
       
  1044         for (TInt i=0; i<KMaxDrives; i++)
       
  1045             {
       
  1046             if ( driveList[i] != 0 )     // check if drive exits
       
  1047                 {
       
  1048                 TDriveInfo driveInfo;
       
  1049                 fs.Drive( driveInfo, i );
       
  1050                 TVolumeInfo driveVolume;
       
  1051                 fs.Volume( driveVolume, i );
       
  1052                                             
       
  1053                 TUint drvStatus( 0 );
       
  1054                 User::LeaveIfError( DriveInfo::GetDriveStatus( fs, i, drvStatus ) );
       
  1055                                             
       
  1056                 if ( (drvStatus & DriveInfo::EDriveUserVisible) &&
       
  1057                      (drvStatus & DriveInfo::EDriveInternal)  && 
       
  1058                      (drvStatus & DriveInfo::EDrivePresent) )
       
  1059                     {
       
  1060                     if (driveVolume.iFree > highest)
       
  1061                         {
       
  1062                         driveToUse = i;
       
  1063                         highest = driveVolume.iFree;
       
  1064                         }
       
  1065                     }
       
  1066                 }
       
  1067              }             
       
  1068                             
       
  1069         __LOG_WRITE_FORMAT2_INFO( "Drive #%d to use, free space=%u", driveToUse, highest );
       
  1070                                   
       
  1071         CleanupStack::PopAndDestroy( &fs );    //-fs
       
  1072         } // end if
       
  1073     
       
  1074     aDrive = static_cast<TDriveNumber>( driveToUse );
       
  1075     SetDriveL( aDrive );   // save it
       
  1076     
       
  1077     __LOG_EXIT
       
  1078     }
       
  1079 
       
  1080 // ==========================================================================
       
  1081 // FUNCTION: GetDrive
       
  1082 //           To find the previously-defined drive to use.   KErrNotFound will
       
  1083 //           be returned if not config file found
       
  1084 //
       
  1085 // Note    : the config file will be loacted in C: drive 
       
  1086 //           (C:\Private\2000c8d2\db_drive.cfg)
       
  1087 // ==========================================================================
       
  1088 TInt CMessageStoreServer::GetDriveL( TDriveNumber& aDrive )
       
  1089     {
       
  1090     __LOG_ENTER( "GetDrive" );
       
  1091     
       
  1092     TInt ret( KErrNotFound );
       
  1093         
       
  1094     RFs fs;
       
  1095     if( fs.Connect() == KErrNone )
       
  1096         {
       
  1097         CleanupClosePushL( fs );               //+fs
       
  1098         TFileName fileName;
       
  1099         fs.CreatePrivatePath( EDriveC );
       
  1100         User::LeaveIfError(fs.PrivatePath( fileName ));
       
  1101         fileName.Append( KDriveToUseFile );
       
  1102         _LIT( KCDrive, "C:" );
       
  1103         fileName.Insert( 0, KCDrive() );
       
  1104         __LOG_WRITE_FORMAT1_INFO( "DriveToUse file=%S", &fileName );
       
  1105                    
       
  1106         if( BaflUtils::FileExists( fs, fileName ) )
       
  1107             {
       
  1108             RFileReadStream reader;
       
  1109             if ( reader.Open( fs, fileName, EFileRead ) == KErrNone )
       
  1110           		{
       
  1111            		CleanupClosePushL( reader );             //+reader
       
  1112            		TUint drive = reader.ReadUint32L();
       
  1113            		__LOG_WRITE_FORMAT1_INFO( "previously-defined drive to use : %d", drive );
       
  1114                 CleanupStack::PopAndDestroy( &reader );  //-reader
       
  1115            		aDrive = static_cast<TDriveNumber>( drive );
       
  1116            		ret = KErrNone;
       
  1117            		}
       
  1118             }
       
  1119                    
       
  1120         CleanupStack::PopAndDestroy( &fs );    //-fs
       
  1121         } // end if
       
  1122     
       
  1123     __LOG_EXIT
       
  1124     return ret;
       
  1125     }
       
  1126 
       
  1127 // ==========================================================================
       
  1128 // FUNCTION: SetDrive
       
  1129 //           To write the chosen drive info to the config file.
       
  1130 //
       
  1131 // Note    : the config file will be loacted in C: drive 
       
  1132 //           (C:\Private\2000c8d2\db_drive.cfg)
       
  1133 // ==========================================================================
       
  1134 void CMessageStoreServer::SetDriveL( const TDriveNumber aDrive )
       
  1135     {
       
  1136     __LOG_ENTER( "SetDrive" );
       
  1137     
       
  1138     TUint drive = static_cast<TUint32>( aDrive );
       
  1139         
       
  1140     RFs fs;
       
  1141     if( fs.Connect() == KErrNone )
       
  1142         {
       
  1143         CleanupClosePushL( fs );               //+fs
       
  1144         TFileName fileName;
       
  1145         User::LeaveIfError(fs.PrivatePath( fileName ));
       
  1146         fileName.Append( KDriveToUseFile );
       
  1147         _LIT( KCDrive, "C:" );
       
  1148         fileName.Insert( 0, KCDrive() );
       
  1149         __LOG_WRITE_FORMAT1_INFO( "DriveToUse file=%S", &fileName )
       
  1150                    
       
  1151         RFileWriteStream writer;
       
  1152         if ( writer.Replace( fs, fileName, EFileRead ) == KErrNone )
       
  1153             {
       
  1154          	CleanupClosePushL( writer );             //+writer
       
  1155            	writer.WriteUint32L( drive );
       
  1156            	writer.CommitL();
       
  1157            	__LOG_WRITE_FORMAT1_INFO( "writing chosen drive #%d to file", drive );
       
  1158             CleanupStack::PopAndDestroy( &writer );  //-writer
       
  1159            	}
       
  1160                  
       
  1161         CleanupStack::PopAndDestroy( &fs );    //-fs
       
  1162         } // end if
       
  1163     
       
  1164     __LOG_EXIT
       
  1165     }
       
  1166 
       
  1167 // ==========================================================================
       
  1168 // FUNCTION: SendSystemLockMessage
       
  1169 // ==========================================================================
       
  1170 void CMessageStoreServer::SendSystemLockMessage( TInt aEvent )
       
  1171     {
       
  1172     TMsgStoreEvent event;
       
  1173     event.iType        = aEvent;
       
  1174     event.iId          = KMsgStoreInvalidId;
       
  1175     event.iParentId    = KMsgStoreInvalidId;
       
  1176     event.iOtherId     = KMsgStoreInvalidId;
       
  1177     event.iFlags       = KMsgStoreFlagsNotFound;
       
  1178 
       
  1179     for( TInt i = 0; i < iSessions.Count(); i++ )
       
  1180         {
       
  1181         iSessions[i]->SendEventToObserver( event );
       
  1182         } // end if
       
  1183     }
       
  1184 
       
  1185 // ==========================================================================
       
  1186 // FUNCTION: TPtrC8ToRBuf16L
       
  1187 // ==========================================================================
       
  1188 void CMessageStoreServer::TPtrC8ToRBuf16L( const TPtrC8& aPtr8, RBuf& aBuf ) const
       
  1189     {
       
  1190     RBuf8 val8;
       
  1191     CleanupClosePushL( val8 );
       
  1192     
       
  1193     val8.Create( aPtr8 );
       
  1194     
       
  1195     const TUint16* valuePtr16 = reinterpret_cast<const TUint16*>( val8.Ptr() );
       
  1196     TPtrC16 val16( valuePtr16, val8.Length() / 2 );
       
  1197     
       
  1198     aBuf.Create( val16 );
       
  1199     
       
  1200     CleanupStack::PopAndDestroy( &val8 );
       
  1201     }
       
  1202 
       
  1203 // FROM: MPSPropertyWatcherObserver
       
  1204 // ==========================================================================
       
  1205 // FUNCTION: OnPSValueChangedToRequired
       
  1206 // ==========================================================================
       
  1207 void CMessageStoreServer::OnPSValueChangedToRequired()
       
  1208     {
       
  1209     iShutdown->Start( 0 );
       
  1210     }
       
  1211 
       
  1212 // FUNCTIONS TO SUPPORT AUTOMATED UNIT TESTING
       
  1213 
       
  1214 #ifdef _DEBUG
       
  1215 // ==========================================================================
       
  1216 // FUNCTION: InjectBackupRestoreEventL
       
  1217 // ==========================================================================
       
  1218 void CMessageStoreServer::InjectBackupRestoreEventL( TUint aEvent )
       
  1219     {
       
  1220     iBackupRestoreNotifier->ProcessEvent( aEvent );
       
  1221     }
       
  1222 
       
  1223 // ==========================================================================
       
  1224 // FUNCTION: InjectPointSecEvern
       
  1225 // ==========================================================================
       
  1226 void CMessageStoreServer::InjectPointSecEvent( TBool aLock )
       
  1227     {
       
  1228     if ( aLock )
       
  1229         {
       
  1230         PointSecLockStarted();
       
  1231         }
       
  1232     else
       
  1233         {
       
  1234         PointSecLockEnded();
       
  1235         }
       
  1236     }
       
  1237 
       
  1238 void CMessageStoreServer::Shutdown()
       
  1239     {
       
  1240     iShutdown->Start( 0 );
       
  1241     }
       
  1242 
       
  1243 #endif
       
  1244 
       
  1245 //from MStoreDriveStateObserver
       
  1246 void CMessageStoreServer::DriveStateChangedL( TBool aState )
       
  1247     {
       
  1248     __LOG_ENTER( "DriveStateChangedL" );
       
  1249     if ( aState )
       
  1250         {
       
  1251         //drive mounted
       
  1252         if ( iLockedByDriveMonitor )
       
  1253              {
       
  1254              iLockedByDriveMonitor = EFalse;
       
  1255              if ( ( !iLockedByBackupRestore ) && ( !iLockedByPointSec ) )
       
  1256                  {
       
  1257                  UnlockSystemL();
       
  1258                  }
       
  1259              }
       
  1260         }
       
  1261     else
       
  1262         {
       
  1263         //drive unmounted
       
  1264         if ( !iLockedByDriveMonitor )
       
  1265             {
       
  1266             iLockedByDriveMonitor = ETrue;
       
  1267             if ( ( !iLockedByBackupRestore ) && ( !iLockedByPointSec ) )
       
  1268                 {
       
  1269                 LockSystem();
       
  1270                 }
       
  1271             }
       
  1272         }
       
  1273     __LOG_EXIT
       
  1274     }
       
  1275