sl@0: // Copyright (c) 2004-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // sl@0: sl@0: #include "panic.h" sl@0: #include "shrepos.h" sl@0: #include "srvrepos_noc.h" sl@0: #include "srvres.h" sl@0: #include "cachemgr.h" sl@0: #include "sessnotf.h" sl@0: #include "srvPerf.h" sl@0: #include "srvreqs.h" sl@0: #include "rstrepos.h" sl@0: #ifdef SYMBIAN_BAFL_SYSUTIL sl@0: #include sl@0: #endif sl@0: #include sl@0: sl@0: sl@0: void CServerRepository::OpenL(TUid aUid, MObserver& aObserver, TBool aFailIfNotFound) sl@0: { sl@0: iNotifier = &aObserver; sl@0: sl@0: TServerResources::iObserver->iObservers.ReserveL(1); sl@0: sl@0: TServerResources::iObserver->AddSharedRepositoryInfoL(aUid); sl@0: sl@0: TRAPD( err, iRepository = TServerResources::iObserver->AccessL(aUid, aFailIfNotFound) ); sl@0: sl@0: //store uid sl@0: iUid = aUid; sl@0: sl@0: if (err == KErrNone) sl@0: { sl@0: TRAP( err, TServerResources::iObserver->AddObserverL(aUid, this) ); sl@0: } sl@0: sl@0: if (err != KErrNone) sl@0: { sl@0: TServerResources::iObserver->RemoveSharedRepositoryInfo(aUid); sl@0: User::Leave(err); sl@0: } sl@0: } sl@0: sl@0: void CServerRepository::Close() sl@0: { sl@0: iRepository = NULL; sl@0: sl@0: TInt index = TServerResources::iObserver->FindOpenRepository(iUid); sl@0: sl@0: if (index>=0) sl@0: { sl@0: iRepository = TServerResources::iObserver->GetOpenRepository(index); sl@0: } sl@0: // cancel to ensure any read/write locks are released and transaction settings cleaned up sl@0: sl@0: CancelTransaction(); sl@0: sl@0: sl@0: TServerResources::iObserver->RemoveObserver(iUid, this, index); sl@0: sl@0: iNotifier = NULL; sl@0: } sl@0: sl@0: /** sl@0: Notify about all changed keys stored in the specified reference to the sl@0: CRestoredRepository. sl@0: sl@0: @param aRstRepos The reference to CRestoredRepository which holds the list sl@0: of the changed keys. sl@0: */ sl@0: void CServerRepository::RestoreNotify(const CRestoredRepository& aRstRepos) sl@0: { sl@0: const RArray& keys = aRstRepos.ChangedKeys(); sl@0: TInt count=keys.Count(); sl@0: for(TInt i = 0; i < count; i++) sl@0: { sl@0: iRepository->Notify(keys[i]); sl@0: } sl@0: } sl@0: sl@0: /** sl@0: Attempt to reset a single key to it's value in the file in the given location. Routine sl@0: attempts to find a .cre file first. If ( and only if ) a cre file doesn't exist the sl@0: routine attempts to find a txt file. In the presence of multi rofs, it needs to perform sl@0: merging of all the rom keyspaces first before doing a reset, hence we are not able to perform sl@0: the reading line by line for efficiency purpose. sl@0: */ sl@0: #ifdef SYMBIAN_CENTREP_SUPPORT_MULTIROFS sl@0: void CServerRepository::ResetFromIniFileL(TUint32 aId, sl@0: CIniFileIn::TIniFileOpenMode aIniFileOpenMode, sl@0: TBool& aKeyFound) sl@0: { sl@0: aKeyFound=EFalse; sl@0: sl@0: CSharedRepository* rep=NULL; sl@0: // Attempt to reset key to the aLocation if exist sl@0: //dont fail if repository not found sl@0: TServerResources::iObserver->LoadRepositoryLC(iRepository->Uid(),EFalse,rep,aIniFileOpenMode); sl@0: sl@0: if (rep) sl@0: { sl@0: TServerSetting* s = rep->GetSettings().Find(aId); sl@0: if(s) sl@0: { sl@0: aKeyFound=ETrue; sl@0: // Mark the setting as default again sl@0: s->SetClean(); sl@0: iRepository->ResetAndPersistL(*s); sl@0: s->SetAccessPolicy(GetFallbackAccessPolicy(aId)); sl@0: } sl@0: } sl@0: CleanupStack::PopAndDestroy(rep); sl@0: } sl@0: #else sl@0: /** sl@0: Attempt to reset a single key to it's value in the file in the given location. Routine sl@0: attempts to find a .cre file first. If ( and only if ) a cre file doesn't exist the sl@0: routine attempts to find a txt file. sl@0: Note that it would be possible to use LoadRepositoryLC here but for the txt file sl@0: that would take longer. This is because in LoadRepositoryLC the txt file is sl@0: completely processed. The Reset specific txt file opening code below is quicker because sl@0: it is just attempting to find the reset key. sl@0: */ sl@0: void CServerRepository::ResetFromIniFileL(TUint32 aId, sl@0: TCentRepLocation aLocation, sl@0: TBool& aKeyFound) sl@0: { sl@0: aKeyFound=EFalse; sl@0: sl@0: // Attempt to reset key to value in cre file if it exists sl@0: sl@0: // Attempt to create a temporary repository from the cre file in aLocation sl@0: CSharedRepository* rep = CSharedRepository::NewL(iRepository->Uid()); sl@0: CleanupStack::PushL(rep); sl@0: TInt err = rep->CreateRepositoryFromCreFileL(aLocation); sl@0: sl@0: // Search for aId in the temporary repository sl@0: if (err!=KErrNotFound) sl@0: { sl@0: // Note that for all errors except KErrNotFound code leaves and doesn't sl@0: // attempt to look for txt file. This is intentional. Code does not sl@0: // attempt to support coexisting cre and txt files. sl@0: User::LeaveIfError(err); sl@0: sl@0: // Search for aId in the temporary repository sl@0: TServerSetting* s = rep->GetSettings().Find(aId); sl@0: if(s) sl@0: { sl@0: aKeyFound=ETrue; sl@0: // Mark the setting as default again sl@0: s->SetClean(); sl@0: iRepository->ResetAndPersistL(*s); sl@0: s->SetAccessPolicy(GetFallbackAccessPolicy(aId)); sl@0: } sl@0: sl@0: CleanupStack::PopAndDestroy(rep); sl@0: return; sl@0: } sl@0: else sl@0: { sl@0: CleanupStack::PopAndDestroy(rep); sl@0: } sl@0: sl@0: HBufC* fileName(NULL); sl@0: TServerResources::CreateRepositoryFileNameLC(fileName,iRepository->Uid(),aLocation,EIni); sl@0: sl@0: CIniFileIn* inputFile = 0; sl@0: TInt r = CIniFileIn::NewLC(TServerResources::iFs,inputFile,*fileName); sl@0: if(r==KErrNone) sl@0: { sl@0: //we don't want to read this stuff again... just skip over to get to settings! sl@0: inputFile->SkipOwnerSectionL() ; sl@0: inputFile->SkipTimeStampSectionL() ; sl@0: inputFile->SkipDefaultMetaSectionL() ; sl@0: inputFile->SkipPlatSecSectionL(); sl@0: sl@0: // Find start of Main section sl@0: inputFile->FindMainSectionL(); sl@0: sl@0: TServerSetting s; sl@0: TBool singleMetaFound=EFalse; sl@0: TBool singleReadPolicyFound=EFalse; sl@0: TBool singleWritePolicyFound=EFalse; sl@0: TSecurityPolicy singleReadPolicy; sl@0: TSecurityPolicy singleWritePolicy; sl@0: sl@0: // Note that calling CIniFile::ReadSettingL causes the single policy ( if it exists ) to be read from the sl@0: // file being reset to, but doesn't update the single policy array, which is not required in the reset case. sl@0: while((r=inputFile->ReadSettingL(s,singleReadPolicy, singleWritePolicy, singleReadPolicyFound, singleWritePolicyFound, singleMetaFound)) == KErrNone) sl@0: { sl@0: iRepository->SetMetaDataOnRead( s, singleMetaFound); sl@0: if(s.Key()==aId) sl@0: { sl@0: // Mark the setting as default again sl@0: s.SetClean(); sl@0: iRepository->ResetAndPersistL(s); sl@0: s.SetAccessPolicy(GetFallbackAccessPolicy(aId)); sl@0: aKeyFound = ETrue; sl@0: break; sl@0: } sl@0: s.Reset(); sl@0: } sl@0: sl@0: sl@0: } sl@0: CleanupStack::PopAndDestroy(inputFile); // inputFile sl@0: CleanupStack::PopAndDestroy(fileName); // filename sl@0: } sl@0: sl@0: #endif sl@0: sl@0: TInt CServerRepository::ResetL(TUint32 aId) sl@0: { sl@0: // not yet supported in transactions sl@0: ASSERT(!IsInTransaction()); sl@0: sl@0: // if setting has not changed, there nothing to do sl@0: TServerSetting *targetSetting = GetSetting(aId) ; sl@0: sl@0: if (targetSetting) sl@0: { sl@0: if ((targetSetting->Meta() & KMetaDefaultValue)) sl@0: { sl@0: return KErrNone; sl@0: } sl@0: } sl@0: sl@0: TInt error = KErrNone; sl@0: TBool keyReset = EFalse; sl@0: sl@0: // Check for default value in any installed file first sl@0: #ifdef SYMBIAN_CENTREP_SUPPORT_MULTIROFS sl@0: ResetFromIniFileL(aId, CIniFileIn::EInstallOnly, keyReset); sl@0: #else sl@0: ResetFromIniFileL(aId, EInstall, keyReset); sl@0: #endif sl@0: if (keyReset) sl@0: return KErrNone; sl@0: sl@0: // Either we couldn't find a matching key or sl@0: // there wasn't an installed file - try for a ROM sl@0: // file sl@0: #ifdef SYMBIAN_CENTREP_SUPPORT_MULTIROFS sl@0: ResetFromIniFileL(aId, CIniFileIn::ERomOnly, keyReset); sl@0: #else sl@0: ResetFromIniFileL(aId, ERom, keyReset); sl@0: #endif sl@0: if (keyReset) sl@0: return KErrNone; sl@0: sl@0: // No default value found in install or ROM file sl@0: // delete the key! sl@0: error = iRepository->DeleteAndPersist(aId); sl@0: sl@0: return error ; sl@0: } sl@0: sl@0: sl@0: void CServerRepository::CacheRomVersionL(const TDesC& aFilename,TDesC8& aVersion) sl@0: { sl@0: sl@0: RFile file; sl@0: TInt err = KErrNone; sl@0: _LIT(KTmpPersistedRomVersionFile, "_:\\private\\10202be9\\romversion\\romversion_info.tmp"); sl@0: TBuf tmpPersistedRomVersionFileName; sl@0: sl@0: tmpPersistedRomVersionFileName.Copy(KTmpPersistedRomVersionFile); sl@0: tmpPersistedRomVersionFileName[0] = RFs::GetSystemDriveChar(); sl@0: sl@0: //Create a new empty tmp file. sl@0: err = file.Replace( TServerResources::iFs, tmpPersistedRomVersionFileName, sl@0: EFileWrite | EFileStreamText ); sl@0: if (err != KErrNone) sl@0: { sl@0: file.Close(); sl@0: User::Leave(err); sl@0: } sl@0: sl@0: err = file.Write(aVersion); sl@0: if (err != KErrNone) sl@0: { sl@0: file.Close(); sl@0: User::Leave(err); sl@0: } sl@0: sl@0: file.Close(); sl@0: sl@0: User::LeaveIfError(TServerResources::iFs.Replace(tmpPersistedRomVersionFileName,aFilename)); sl@0: sl@0: } sl@0: sl@0: #ifdef SYMBIAN_BAFL_SYSUTIL sl@0: void CServerRepository::CheckROMReflashL() sl@0: { sl@0: TInt err=KErrNone; sl@0: sl@0: TBuf16 version; sl@0: TBuf8 persistedCopyOfRomVersion; sl@0: _LIT(KPersistedRomVersionFile, "_:\\private\\10202be9\\romversion\\romversion_info.txt"); sl@0: TBuf persistedRomVersionFileName; sl@0: persistedRomVersionFileName.Copy(KPersistedRomVersionFile); sl@0: persistedRomVersionFileName[0] = RFs::GetSystemDriveChar(); sl@0: sl@0: TBuf8 eightBitVersion; sl@0: sl@0: sl@0: if ((err = SysUtil::GetSWVersion(version)) == KErrNone ) sl@0: { sl@0: eightBitVersion.Copy(version);//Converts to 8bit sl@0: err = TServerResources::GetTextFromFile(persistedRomVersionFileName,persistedCopyOfRomVersion); sl@0: if(err == KErrNone) sl@0: { sl@0: if(eightBitVersion == persistedCopyOfRomVersion)//No rom update has occurred do nothing sl@0: { sl@0: return; sl@0: } sl@0: else //rom update detected process persists files. sl@0: { sl@0: //Call function with flag set to true causing Reflash merging activity. sl@0: ProcessPersistsRepositoriesL(ECenRepReflash); sl@0: } sl@0: } sl@0: sl@0: //create the persisted rom version file sl@0: //if the persists files are successfully processed sl@0: //if the persists file doesnt exist sl@0: //if the persists file is corrupt sl@0: //if the persists file is corrupt in such a way that its contents are too large. sl@0: if (err == KErrNone || err == KErrNotFound || err == KErrPathNotFound || err == KErrCorrupt || err == KErrTooBig) sl@0: { sl@0: CServerRepository::CacheRomVersionL(persistedRomVersionFileName,eightBitVersion); sl@0: } sl@0: else sl@0: { sl@0: User::Leave(err); sl@0: } sl@0: } sl@0: else sl@0: { sl@0: User::Leave(err); sl@0: } sl@0: } sl@0: #endif sl@0: sl@0: void CServerRepository::RFSAllRepositoriesL() sl@0: { sl@0: ProcessPersistsRepositoriesL(ECenRepReset); sl@0: } sl@0: sl@0: void CServerRepository::ProcessPersistsRepositoriesL(TPersistedRepActions aRomFlashOrReset) sl@0: { sl@0: // Read contents of persist directory to get a list of repositories sl@0: TPtr dataDirectory = TServerResources::iDataDirectory->Des(); sl@0: RDir persistDir; sl@0: CleanupClosePushL(persistDir); sl@0: sl@0: User::LeaveIfError(persistDir.Open(TServerResources::iFs, dataDirectory, KEntryAttNormal)); sl@0: sl@0: TEntryArray dirEntries; sl@0: TInt readError = KErrNone; sl@0: sl@0: while (readError != KErrEof) sl@0: { sl@0: readError = persistDir.Read(dirEntries); sl@0: sl@0: if(readError != KErrNone && readError != KErrEof) sl@0: { sl@0: User::Leave(readError); sl@0: } sl@0: else sl@0: { sl@0: const TInt dirCount = dirEntries.Count(); sl@0: for (TInt i=0; i(dirEntries[i]), uid)) sl@0: { sl@0: CSessionNotifier notifier; sl@0: sl@0: // Create shared repository sl@0: CServerRepository *repository = new(ELeave) CServerRepository; sl@0: CleanupStack::PushL(repository); sl@0: sl@0: repository->OpenL(uid, notifier); sl@0: sl@0: //Handle ROM re-flash sl@0: TInt err = KErrNone; sl@0: if(aRomFlashOrReset==ECenRepReflash) sl@0: { sl@0: TRAP(err, repository->HandleReflashofRepositoryL()); sl@0: } sl@0: else if(aRomFlashOrReset==ECenRepReset) sl@0: { sl@0: // Restore settings sl@0: TRAP(err,repository->RFSRepositoryL()); sl@0: } sl@0: if(err != KErrNone) sl@0: { sl@0: if(err == KErrNoMemory) sl@0: { sl@0: repository->Close(); sl@0: User::LeaveNoMemory(); sl@0: } sl@0: else sl@0: {//Dont stop processing the rest of the persisted repositories becos one has a problem. sl@0: __CENTREP_TRACE1("CENTREP: CServerRepository::ProcessPersistsRepositoriesL - Error = %d", err); sl@0: } sl@0: } sl@0: sl@0: // delete repository. sl@0: repository->Close(); sl@0: CleanupStack::PopAndDestroy(repository); sl@0: } sl@0: } sl@0: } sl@0: } sl@0: sl@0: CleanupStack::PopAndDestroy(&persistDir); sl@0: } sl@0: sl@0: TInt CServerRepository::RFSRepositoryL() sl@0: { sl@0: // for each key in combined ROM/Install restore sl@0: TUid uid = iRepository->Uid(); sl@0: sl@0: CSharedRepository* defaultRepository = 0; sl@0: TInt err=KErrNone; sl@0: sl@0: //Determine if ROM and Install files exist sl@0: TBool romExists=TServerResources::RomFileExistsL(uid); sl@0: TBool installExists=TServerResources::InstallFileExistsL(uid); sl@0: sl@0: if(romExists) sl@0: { sl@0: // Create a rep using the ROM file sl@0: TServerResources::iObserver->LoadRepositoryLC(uid, ETrue, defaultRepository, CIniFileIn::ERomOnly); sl@0: sl@0: if(installExists) sl@0: { sl@0: CSharedRepository *installRep = 0; sl@0: // Create install rep for merging sl@0: TServerResources::iObserver->LoadRepositoryLC(uid, ETrue, installRep, CIniFileIn::EInstallOnly); sl@0: sl@0: // If install and ROM exist create a merged rep to Reset against sl@0: defaultRepository->MergeL(*installRep, ESWIUpgradeMerge); sl@0: sl@0: //pop and destroy install repository as this has now been sl@0: //merged with repository sl@0: CleanupStack::PopAndDestroy(installRep); sl@0: } sl@0: } sl@0: sl@0: else if(installExists) sl@0: { sl@0: // Reset against install repository if only the install file exists sl@0: TServerResources::iObserver->LoadRepositoryLC(uid, ETrue, defaultRepository, CIniFileIn::EInstallOnly); sl@0: } sl@0: else sl@0: { sl@0: // The repository must exist in the ROM or install directory (or both). sl@0: ASSERT(romExists || installExists); sl@0: // Reset against empty repository if neither ROM or install file are found sl@0: defaultRepository = CSharedRepository::NewL(uid); sl@0: CleanupStack::PushL(defaultRepository); sl@0: } sl@0: sl@0: for(TInt i = 0; i < iRepository->GetSettings().Count(); i++) sl@0: { sl@0: // setting in persists sl@0: TServerSetting* persistedSetting = &iRepository->GetSettings()[i]; sl@0: sl@0: // If the clean is set on setting in the persist, nothing to do sl@0: if (persistedSetting->Meta() & KMetaDefaultValue) sl@0: { sl@0: continue; sl@0: } sl@0: sl@0: TUint32 key = persistedSetting->Key(); sl@0: // setting in ROM/install sl@0: TServerSetting* defaultSetting = defaultRepository->GetSettings().Find(key); sl@0: sl@0: if (defaultSetting) sl@0: { sl@0: if ((defaultSetting->Meta() & KMetaRfsValue)) sl@0: { sl@0: iRepository->ResetNoPersistL(*defaultSetting); sl@0: } sl@0: //remove from Reset repository sl@0: defaultRepository->GetSettings().Remove(key); sl@0: } sl@0: else sl@0: { sl@0: // if setting has no default value (i.e. doesn't exist in any default file but RFS meta is sl@0: // set (using pre-set default range meta), delete the setting sl@0: if ((persistedSetting->Meta() & KMetaRfsValue)) sl@0: { sl@0: iRepository->DeleteNoPersist(key); sl@0: } sl@0: } sl@0: } sl@0: // search for remaining items in default file, because previous loop has already removed all items sl@0: // from the persists file sl@0: for(TInt i = 0; i < defaultRepository->GetSettings().Count(); i++) sl@0: { sl@0: TServerSetting* defaultSetting = &defaultRepository->GetSettings()[i]; sl@0: sl@0: if ((defaultSetting->Meta() & KMetaRfsValue) != KMetaRfsValue) sl@0: { sl@0: continue; sl@0: } sl@0: iRepository->ResetNoPersistL(*defaultSetting); sl@0: } sl@0: sl@0: // Persist settings sl@0: iRepository->CommitChangesL(); sl@0: sl@0: CleanupStack::PopAndDestroy(defaultRepository); sl@0: sl@0: return err; sl@0: } sl@0: sl@0: sl@0: TInt CServerRepository::HandleReflashofRepositoryL() sl@0: { sl@0: // for each key in persists repository sl@0: TUid uid = iRepository->Uid(); sl@0: sl@0: CSharedRepository* defaultRepository = 0; sl@0: sl@0: //Determine if ROM and Install files exist sl@0: TBool romExists=TServerResources::RomFileExistsL(uid); sl@0: TBool installExists=TServerResources::InstallFileExistsL(uid); sl@0: sl@0: if(romExists) sl@0: { sl@0: // Create a rep using the ROM file sl@0: TServerResources::iObserver->LoadRepositoryLC(uid, ETrue, defaultRepository, CIniFileIn::ERomOnly); sl@0: sl@0: if(installExists)//Then create a merged repository of rom and install settings sl@0: { sl@0: CSharedRepository *installRep = 0; sl@0: // Create install rep for merging sl@0: TServerResources::iObserver->LoadRepositoryLC(uid, ETrue, installRep, CIniFileIn::EInstallOnly); sl@0: sl@0: // If install and ROM exist create a merged rep to Reset against sl@0: defaultRepository->MergeL(*installRep, ESWIUpgradeMerge); sl@0: sl@0: //pop and destroy install repository as this has now been sl@0: //merged with the rom repository sl@0: CleanupStack::PopAndDestroy(installRep); sl@0: } sl@0: } sl@0: else if(installExists)//There was no ROM repository just an install repository sl@0: { sl@0: // Reset against install repository if only the install file exists sl@0: TServerResources::iObserver->LoadRepositoryLC(uid, ETrue, defaultRepository, CIniFileIn::EInstallOnly); sl@0: } sl@0: else //If rom file and install files have been removed for this repository sl@0: {//then remove the persists file. sl@0: TServerResources::DeleteCentrepFileL(uid, EPersists, ECre); sl@0: TServerResources::DeleteCentrepFileL(uid, EPersists, EIni); sl@0: return KErrNone; sl@0: } sl@0: sl@0: // Merge rom and/or install with persists repository sl@0: iRepository->MergeL(*defaultRepository, ERomFlash); sl@0: sl@0: // Persist settings sl@0: iRepository->CommitChangesL(); sl@0: sl@0: CleanupStack::PopAndDestroy(defaultRepository); sl@0: sl@0: return KErrNone; sl@0: } sl@0: sl@0: sl@0: TInt CServerRepository::ResetAllL() sl@0: { sl@0: // not yet supported in transactions sl@0: ASSERT(!IsInTransaction()); sl@0: // fail all sessions' transactions first sl@0: iRepository->FailAllTransactions(/*aExcludeTransactor*/NULL); sl@0: sl@0: TUid uid = iRepository->Uid(); sl@0: sl@0: // Reset sl@0: sl@0: // Create a rep using the ROM file sl@0: CSharedRepository* rep = 0; sl@0: TBool romExists=TServerResources::RomFileExistsL(uid); sl@0: if(romExists) sl@0: { sl@0: TServerResources::iObserver->LoadRepositoryLC(uid, ETrue, rep, CIniFileIn::ERomOnly); sl@0: } sl@0: sl@0: // Create install rep for merging sl@0: CSharedRepository *installRep = 0; sl@0: TBool installExists=TServerResources::InstallFileExistsL(uid); sl@0: if(installExists) sl@0: { sl@0: TServerResources::iObserver->LoadRepositoryLC(uid, ETrue, installRep, CIniFileIn::EInstallOnly); sl@0: } sl@0: sl@0: TInt err=KErrNone; sl@0: if( romExists && installExists) sl@0: { sl@0: // If install and ROM exist create a merged rep to Reset against sl@0: rep->MergeL(*installRep, ESWIUpgradeMerge); sl@0: err=iRepository->ResetAllNoPersistL(*rep); sl@0: CleanupStack::PopAndDestroy(installRep); sl@0: CleanupStack::PopAndDestroy(rep); sl@0: } sl@0: else if(romExists) sl@0: { sl@0: // Reset against ROM sl@0: err=iRepository->ResetAllNoPersistL(*rep); sl@0: CleanupStack::PopAndDestroy(rep); sl@0: } sl@0: else if(installExists) sl@0: { sl@0: // Reset against install sl@0: err=iRepository->ResetAllNoPersistL(*installRep); sl@0: CleanupStack::PopAndDestroy(installRep); sl@0: } sl@0: else sl@0: { sl@0: // Reset against empty repository sl@0: rep = CSharedRepository::NewL(uid); sl@0: CleanupStack::PushL(rep); sl@0: err=iRepository->ResetAllNoPersistL(*rep); sl@0: CleanupStack::PopAndDestroy(rep); sl@0: } sl@0: sl@0: return err; sl@0: } sl@0: sl@0: // Handle install directory file update. sl@0: void CServerRepository::HandleSWIUpdateL(TUid aUid, TTime aModified, CSessionNotifier &aNotifier) sl@0: { sl@0: // A file create or update has just occurred in the SWI directory. sl@0: // Need to check if this is a new install. sl@0: sl@0: if(TServerResources::PersistsFileExistsL(aUid) || sl@0: TServerResources::RomFileExistsL(aUid)) sl@0: { sl@0: // Create a rep using the ROM or persists file sl@0: OpenL(aUid, aNotifier); sl@0: if(iRepository->IsTransactionActive()) sl@0: { sl@0: // Fail transactions on any currently open session sl@0: iRepository->FailAllTransactions(NULL); sl@0: } sl@0: sl@0: // Create install rep for merging sl@0: CSharedRepository *installRep = 0; sl@0: TRAPD( err, TServerResources::iObserver->LoadRepositoryLC(aUid, ETrue, installRep, CIniFileIn::EInstallOnly); CleanupStack::Pop(installRep) ); sl@0: sl@0: if (err == KErrNone) sl@0: { sl@0: // Perform merge sl@0: TRAP( err, iRepository->HandleUpdateMergeL(aModified, *installRep) ); sl@0: } sl@0: if (installRep!=NULL) sl@0: { sl@0: delete installRep; sl@0: } sl@0: Close(); sl@0: User::LeaveIfError(err); sl@0: } sl@0: else // No ROM or persists sl@0: { sl@0: // Create install rep for persisting sl@0: OpenL(aUid, aNotifier); sl@0: TRAPD(err, iRepository->CommitChangesL()); sl@0: Close(); sl@0: User::LeaveIfError(err); sl@0: } sl@0: } sl@0: sl@0: sl@0: // Handle install directory file delete sl@0: void CServerRepository::HandleSWIDeleteL(TUid aUid, CSessionNotifier &aNotifier) sl@0: { sl@0: // A file delete has just occurred in the SWI directory. If there is no ROM file sl@0: // this is a complete uninstall, so delete persists file.Otherwise, do downgrade sl@0: // merge. sl@0: sl@0: if(TServerResources::RomFileExistsL(aUid)) // ROM file, this is a downgrade uninstall sl@0: { sl@0: if(!TServerResources::PersistsFileExistsL(aUid)) sl@0: { sl@0: // If we are downgrading the ROM, there should be a persists file because the sl@0: // original upgrade should have created one. sl@0: // However if there isn't a persists file, there's nothing to do, so just return sl@0: return; sl@0: } sl@0: sl@0: // Create a rep using the persists file sl@0: OpenL(aUid, aNotifier); sl@0: if(iRepository->IsTransactionActive()) sl@0: { sl@0: // Fail transactions on any currently open session sl@0: iRepository->FailAllTransactions(NULL); sl@0: } sl@0: sl@0: // Create ROM rep for merging sl@0: CSharedRepository *romRep = 0; sl@0: TRAPD( err, TServerResources::iObserver->LoadRepositoryLC(aUid, ETrue, romRep, CIniFileIn::ERomOnly); CleanupStack::Pop(romRep) ); sl@0: sl@0: if (err == KErrNone) sl@0: { sl@0: // Perform merge sl@0: TRAP( err, iRepository->HandleDeleteMergeL(*romRep) ); sl@0: } sl@0: if (romRep!=NULL) sl@0: { sl@0: delete romRep; sl@0: } sl@0: Close(); sl@0: User::LeaveIfError(err); sl@0: } sl@0: else // No ROM file, this is a complete uninstall sl@0: { sl@0: if(TServerResources::PersistsFileExistsL(aUid)) sl@0: { sl@0: TServerResources::DeleteCentrepFileL(aUid, EPersists, ECre); sl@0: sl@0: // Check if the repository was open sl@0: TInt i = TServerResources::iObserver->FindOpenRepository(aUid); sl@0: sl@0: // If repository is open, fail all transactions sl@0: if(i>KErrNotFound) sl@0: { sl@0: OpenL(aUid, aNotifier); sl@0: if(iRepository->IsTransactionActive()) sl@0: { sl@0: // Fail transactions on any currently open session sl@0: iRepository->FailAllTransactions(NULL); sl@0: } sl@0: iRepository->ResetContent(); sl@0: Close(); sl@0: } sl@0: } sl@0: } sl@0: } sl@0: sl@0: void CServerRepository::StoreRepositoryContentsL(CStreamStore& aStore, TStreamId & aSettingStreamId, TStreamId & aDeletedSettingsStreamId) const sl@0: { sl@0: StoreRepositorySettingValuesL(aStore, aSettingStreamId); // Stores current repository setting values sl@0: sl@0: RStoreWriteStream outStream; sl@0: aDeletedSettingsStreamId = outStream.CreateLC(aStore); // Creates the write for settings stream sl@0: iRepository->WriteDeletedSettingsStream(outStream) ; sl@0: outStream.CommitL(); // Commits the stream sl@0: CleanupStack::PopAndDestroy(&outStream); // Performs cleanup on the write stream object sl@0: } sl@0: sl@0: void CServerRepository::StoreRepositorySettingValuesL(CStreamStore& aStore, TStreamId & aSettingStreamId) const sl@0: { sl@0: RStoreWriteStream outStream; sl@0: aSettingStreamId = outStream.CreateLC(aStore); // Creates the write stream sl@0: iRepository->WriteBackupStream(outStream); // Only care about repository contents. sl@0: outStream.CommitL(); // Commits the stream sl@0: CleanupStack::PopAndDestroy(&outStream); // Performs cleanup on the write stream object sl@0: } sl@0: sl@0: void CServerRepository::RestoreRepositoryContentsL(CStreamStore& aStore, TStreamId aSettingStreamId, TStreamId aDeletedSettingsStreamId, CRestoredRepository& aRstRepos) sl@0: { sl@0: RestoreRepositorySettingValuesL(aStore, aSettingStreamId, aRstRepos); sl@0: sl@0: RStoreReadStream inStream; sl@0: // If the backup contains a list of deleted settings read them in and apply them. sl@0: if (aDeletedSettingsStreamId != KNullStreamId) sl@0: { sl@0: inStream.OpenLC(aStore, aDeletedSettingsStreamId); // Creates read stream for deleted settings (if available) sl@0: sl@0: TCardinality numDeletedSettings ; sl@0: inStream >> numDeletedSettings ; sl@0: sl@0: for (TInt i = 0; i < numDeletedSettings; i++) sl@0: { sl@0: TUint32 settingToDelete ; sl@0: inStream >> settingToDelete ; sl@0: TInt err = iRepository->DeleteNoPersist(settingToDelete) ; sl@0: // Add the deleted key to the restored repository if it has existed before being deleted. sl@0: // If it has not existed before being deleted, we do not add it to the list because nothing sl@0: // has changed. sl@0: if(err == KErrNone) sl@0: { sl@0: aRstRepos.AddKeyL(settingToDelete); sl@0: } sl@0: } sl@0: CleanupStack::PopAndDestroy(&inStream); // Perform cleanup on the read stream object sl@0: } sl@0: return; sl@0: } sl@0: sl@0: void CServerRepository::RestoreRepositorySettingValuesL(CStreamStore& aStore, TStreamId aSettingStreamId, CRestoredRepository& aRstRepos) sl@0: { sl@0: RStoreReadStream inStream; sl@0: inStream.OpenLC(aStore, aSettingStreamId); // Creates the write stream sl@0: iRepository->InternalizeL(inStream, aRstRepos); // Only care about repository contents. sl@0: CleanupStack::PopAndDestroy(&inStream); // Perform cleanup on the read stream object sl@0: } sl@0: sl@0: static void CancelTransactionCleanupOperation(TAny* aRepository) sl@0: { sl@0: static_cast(aRepository)->CancelTransaction(); sl@0: } sl@0: sl@0: // So CancelTransaction is called in case of Leave. Must pop with CleanupStack::Pop() or similar sl@0: void CServerRepository::CleanupCancelTransactionPushL() sl@0: { sl@0: CleanupStack::PushL(TCleanupItem(CancelTransactionCleanupOperation, this)); sl@0: } sl@0: sl@0: /** sl@0: @internalTechnology sl@0: Check the range of security policies against RMessage sl@0: @return sl@0: KErrNone if read access policies of all settings in array pass, sl@0: KErrPermissionDenied if any single policy fails. sl@0: */ sl@0: TInt CServerRepository::CheckPermissions(RSettingPointerArray& aSettings, const TClientRequest& aMessage, const char* aDiagnostic, TBool aReadPolicy,TUint32& aErrId) sl@0: { sl@0: TInt error = KErrNone; sl@0: TInt numSettings = aSettings.Count(); sl@0: for (TInt i = 0; i < numSettings; i++) sl@0: { sl@0: ASSERT(aSettings[i]); sl@0: const TServerSetting& setting = *aSettings[i]; sl@0: if (aReadPolicy) sl@0: { sl@0: if (!aMessage.CheckPolicy(GetReadAccessPolicy(setting),aDiagnostic)) sl@0: { sl@0: aErrId=setting.Key(); sl@0: error = KErrPermissionDenied; sl@0: break; sl@0: } sl@0: } sl@0: else sl@0: { sl@0: if (!aMessage.CheckPolicy(GetWriteAccessPolicy(setting),aDiagnostic)) sl@0: { sl@0: aErrId=setting.Key(); sl@0: error = KErrPermissionDenied; sl@0: break; sl@0: } sl@0: } sl@0: } sl@0: return error; sl@0: } sl@0: sl@0: TInt CServerRepository::TransactionDeleteRangeL(const TClientRequest& aMessage, TUint32& aErrorKey) sl@0: { sl@0: // all write operations now done in a transaction sl@0: ASSERT(IsInActiveReadWriteTransaction()); sl@0: TInt error = KErrNone; sl@0: aErrorKey = KUnspecifiedKey; sl@0: sl@0: TUint32 partialKey = aMessage.Int0(); sl@0: TUint32 keyMask = aMessage.Int1(); sl@0: sl@0: RSettingPointerArray settingsToDelete; sl@0: CleanupClosePushL(settingsToDelete); sl@0: error = FindSettings(partialKey, keyMask, settingsToDelete); sl@0: if (error==KErrNoMemory) sl@0: User::LeaveNoMemory(); sl@0: sl@0: //perform write security check first sl@0: error=CheckPermissions(settingsToDelete,aMessage,__PLATSEC_DIAGNOSTIC_STRING("CenRep: CServerRepository::DeleteRangeL - Attempt made to delete a setting"),EFalse,aErrorKey); sl@0: sl@0: if (error==KErrNone) sl@0: { sl@0: TRAP(error,DeleteSettingsRangeL(settingsToDelete,partialKey,aErrorKey)); sl@0: if (error==KErrNoMemory) sl@0: User::LeaveNoMemory(); sl@0: } sl@0: CleanupStack::PopAndDestroy(&settingsToDelete); sl@0: sl@0: if ((error != KErrNone) && (error != KErrNotFound)) sl@0: { sl@0: FailTransaction(error, aErrorKey); sl@0: } sl@0: return error; sl@0: } sl@0: sl@0: TInt CServerRepository::TransactionMoveL(const TClientRequest& aMessage, TUint32& aErrorKey) sl@0: { sl@0: // all write operations now done in a transaction sl@0: ASSERT(IsInActiveReadWriteTransaction()); sl@0: //read the source and target partial key sl@0: TKeyFilter sourceKeyIdentifier; sl@0: TPckg pSource(sourceKeyIdentifier); sl@0: aMessage.Read(0, pSource); sl@0: sl@0: TKeyFilter targetKeyIdentifier; sl@0: TPckg pTarget(targetKeyIdentifier); sl@0: aMessage.Read(1, pTarget); sl@0: sl@0: TUint32 sourceToTarget = (sourceKeyIdentifier.iPartialId & sourceKeyIdentifier.iIdMask) ^ (targetKeyIdentifier.iPartialId & targetKeyIdentifier.iIdMask); sl@0: if (sourceToTarget==0) sl@0: { sl@0: return KErrNone; sl@0: } sl@0: sl@0: //Need to get the list of source settings to perform some security policy check sl@0: RSettingPointerArray sourceSettings; sl@0: CleanupClosePushL(sourceSettings); sl@0: TInt error=FindSettings(sourceKeyIdentifier.iPartialId & sourceKeyIdentifier.iIdMask, sourceKeyIdentifier.iIdMask, sourceSettings); sl@0: sl@0: //dont fail transaction if source settings is empty sl@0: if ((error == KErrNone) && (sourceSettings.Count() == 0)) sl@0: { sl@0: error = KErrNotFound; sl@0: aErrorKey = sourceKeyIdentifier.iPartialId; sl@0: CleanupStack::PopAndDestroy(&sourceSettings); sl@0: TPckg p(aErrorKey); sl@0: aMessage.WriteL(2, p); sl@0: return error; sl@0: sl@0: } sl@0: if (error!=KErrNone) sl@0: { sl@0: aErrorKey = sourceKeyIdentifier.iPartialId; sl@0: CleanupStack::PopAndDestroy(&sourceSettings); sl@0: return error; sl@0: } sl@0: sl@0: //Now validate against the security policy before doing the settings move sl@0: error=CheckMovePermissions(sourceSettings,aMessage,sourceToTarget,aErrorKey); sl@0: if (error!=KErrNone) sl@0: { sl@0: CleanupStack::PopAndDestroy(&sourceSettings); sl@0: return error; sl@0: } sl@0: sl@0: error =MoveL(sourceKeyIdentifier.iPartialId,targetKeyIdentifier.iPartialId,sourceKeyIdentifier.iIdMask,aErrorKey, sourceSettings); sl@0: CleanupStack::PopAndDestroy(&sourceSettings); sl@0: return error; sl@0: } sl@0: sl@0: void CServerRepository::LoadIniRepL(CIniFileIn::TIniFileOpenMode aMode) sl@0: { sl@0: if (iIniRep == NULL) sl@0: { sl@0: CSharedRepository *rep = NULL; sl@0: TServerResources::iObserver->LoadRepositoryLC(iUid, ETrue, rep, aMode); sl@0: CleanupStack::Pop(); sl@0: iIniRep = rep; sl@0: } sl@0: } sl@0: sl@0: TBool CServerRepository::GetMetaFromIni(TUint32 aKey, TUint32& aMeta) sl@0: { sl@0: // Note: cannot use iRepository even if sl@0: // iRepository->iSettings.IsDefault() is true. sl@0: // The flag is not updated on TransactionCommit. sl@0: if (iIniRep == NULL) sl@0: { sl@0: TInt err; sl@0: TRAP(err, LoadIniRepL(CIniFileIn::EInstallOnly)); sl@0: if (err != KErrNone) sl@0: { sl@0: TRAP(err,LoadIniRepL(CIniFileIn::ERomOnly)); sl@0: } sl@0: if (err != KErrNone) sl@0: { sl@0: return EFalse; sl@0: } sl@0: } sl@0: sl@0: ASSERT(iIniRep); sl@0: TServerSetting* s = iIniRep->GetSettings().Find(aKey); sl@0: if (s) sl@0: { sl@0: aMeta = s->Meta(); sl@0: return ETrue; sl@0: } sl@0: sl@0: return EFalse; sl@0: } sl@0: sl@0: void CServerRepository::RestoreInstallRepositoryL(TUid aUid, CStreamStore& aStore, TStreamId& aSettingStreamId, CRestoredRepository& aRstRepos) sl@0: { sl@0: iRepository = CSharedRepository::NewL(aUid); sl@0: CleanupStack::PushL(iRepository); sl@0: iUid = aUid; sl@0: RestoreRepositorySettingValuesL(aStore, aSettingStreamId, aRstRepos); sl@0: CommitChangesL(EInstall); sl@0: CleanupStack::PopAndDestroy(iRepository); sl@0: iRepository = NULL; sl@0: } sl@0: sl@0: void CServerRepository::BackupInstallRepositoryL(TUid aUid, CStreamStore& aStore, TStreamId& aSettingStreamId) sl@0: { sl@0: TServerResources::iObserver->LoadRepositoryLC(aUid, EFalse, iRepository, CIniFileIn::EInstallOnly); sl@0: iUid = aUid; sl@0: StoreRepositorySettingValuesL(aStore, aSettingStreamId); sl@0: CleanupStack::PopAndDestroy(iRepository); sl@0: iRepository = NULL; sl@0: } sl@0: sl@0: TInt CServerRepository::CheckAccessPolicyBeforeMoving(const TClientRequest& aMessage, const TServerSetting* aSourceSetting, sl@0: TUint32 aSourceKey, const TServerSetting* aTargetSetting, TUint32 aTargetKey, TUint32& aErrorKey) sl@0: { sl@0: TInt error = KErrNone; sl@0: sl@0: if (aTargetSetting && !aTargetSetting->IsDeleted()) sl@0: { sl@0: error=KErrAlreadyExists; sl@0: aErrorKey=aTargetKey; sl@0: } sl@0: sl@0: if (!aMessage.CheckPolicy(GetReadAccessPolicy(*aSourceSetting), sl@0: __PLATSEC_DIAGNOSTIC_STRING("CenRep: CServerRepository::MoveL - Attempt made to read a setting"))) sl@0: { sl@0: error = KErrPermissionDenied; sl@0: aErrorKey = aSourceKey; sl@0: } sl@0: else if (!aMessage.CheckPolicy(GetWriteAccessPolicy(*aSourceSetting), sl@0: __PLATSEC_DIAGNOSTIC_STRING("CenRep: CServerRepository::MoveL - Attempt made to delete a setting"))) sl@0: { sl@0: error = KErrPermissionDenied; sl@0: aErrorKey = aSourceKey; sl@0: } sl@0: else if (error == KErrAlreadyExists) sl@0: { sl@0: // set error to KErrPermissionDenied in preference to KErrAlreadyExists sl@0: if (!aMessage.CheckPolicy(GetWriteAccessPolicy(*aTargetSetting), sl@0: __PLATSEC_DIAGNOSTIC_STRING("CenRep: CServerRepository::MoveL - Attempt made to create a setting"))) sl@0: { sl@0: error = KErrPermissionDenied; sl@0: aErrorKey = aTargetKey; sl@0: } sl@0: } sl@0: else if (!aMessage.CheckPolicy(GetFallbackWriteAccessPolicy(aTargetKey), sl@0: __PLATSEC_DIAGNOSTIC_STRING("CenRep: CServerRepository::MoveL - Attempt made to create a setting"))) sl@0: { sl@0: error = KErrPermissionDenied; sl@0: aErrorKey = aTargetKey; sl@0: } sl@0: return error; sl@0: }