diff -r 675a964f4eb5 -r 35751d3474b7 cryptoservices/filebasedcertificateandkeystores/source/certapps/server/CFSCertAppsServer.cpp --- a/cryptoservices/filebasedcertificateandkeystores/source/certapps/server/CFSCertAppsServer.cpp Tue Jul 21 01:04:32 2009 +0100 +++ b/cryptoservices/filebasedcertificateandkeystores/source/certapps/server/CFSCertAppsServer.cpp Thu Sep 10 14:01:51 2009 +0300 @@ -1,469 +1,470 @@ -/* -* Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies). -* All rights reserved. -* This component and the accompanying materials are made available -* under the terms of the License "Eclipse Public License v1.0" -* which accompanies this distribution, and is available -* at the URL "http://www.eclipse.org/legal/epl-v10.html". -* -* Initial Contributors: -* Nokia Corporation - initial contribution. -* -* Contributors: -* -* Description: -* -*/ - - -#include "CFSCertAppsServer.h" -#include "CCertAppsSession.h" -#include "CCertAppsConduit.h" -#include "fstokencliserv.h" -#include "fstokenutil.h" -#include "certstorepatchdata.h" -#include -#include - -// Filename where all data is stored -_LIT(KCertAppsFilename,"certclients.dat"); -_LIT(KCertAppsFile,"certclients*.dat"); - -CFSCertAppsServer* CFSCertAppsServer::NewL() - { - CFSCertAppsServer* self = new (ELeave) CFSCertAppsServer(); - CleanupStack::PushL(self); - self->ConstructL(); - CleanupStack::Pop(self); - return self; - } - -CFSCertAppsServer::CFSCertAppsServer() - { - } - -void CFSCertAppsServer::ConstructL() - { - iConduit = CCertAppsConduit::NewL(*this); - - // Connect to the filesystem - User::LeaveIfError(iFs.Connect()); - - iPatchableConst = KAggregateCertStore; - - #ifdef __WINS__ - // For the emulator allow the constant to be patched via epoc.ini - UserSvr::HalFunction(EHalGroupEmulator, EEmulatorHalIntProperty, - (TAny*)"KAggregateCertStore", &iPatchableConst); // read emulator property (if present) - #endif - - // Retrieves the store - OpenStoreL(); - } - -CFSCertAppsServer::~CFSCertAppsServer() - { - delete iStore; - iFs.Close(); - iClients.Close(); - delete iConduit; - } - -CCertAppsSession* CFSCertAppsServer::CreateSessionL() - { - return CCertAppsSession::NewL(*iConduit); - } - -void CFSCertAppsServer::AddL(const TCertificateAppInfo& aClient) - { - // see if application already exists. If so, then leave - - if (FindApplication(aClient.Id())) - { - User::Leave(KErrAlreadyExists); - } - User::LeaveIfError(iClients.Append(aClient)); - TRAPD(err, ReplaceAndCommitL(-1)); - if (err != KErrNone) - { - // We must remove the client from iClients if we didn't manage - // to add it to the store - iClients.Remove(iClients.Count() - 1); - User::Leave(err); - } - } - -void CFSCertAppsServer::RemoveL(const TUid& aUid) - { - // Make sure the application for that uid exists - TInt i; - if (!FindApplication(aUid, &i)) - { - User::Leave(KErrNotFound); - } - - ReplaceAndCommitL(i); - - // We managed to remove it from the store, so we remove it from the - // iClients array - iClients.Remove(i); - } - -TInt CFSCertAppsServer::ApplicationCountL() const - { - return iClients.Count(); - } - -void CFSCertAppsServer::ApplicationsL(RArray& aAppArray) const - { - // Make a copy of the array - TInt count = iClients.Count(); - - for (TInt i = 0; i < count; ++i) - { - aAppArray.Append(iClients[i]); - } - } - -void CFSCertAppsServer::ApplicationL(const TUid& aUid, TCertificateAppInfo& aInfo) const - { - const TCertificateAppInfo* app = FindApplication(aUid); - - // leave if not found - if (!app) - { - User::Leave(KErrNotFound); - } - - // make a copy and return to client - aInfo = *app; - } - -const TCertificateAppInfo* CFSCertAppsServer::FindApplication(const TUid& aUid, TInt* aIndex) const - { - // This helper function tries to find an application with the given - // Uid. It returns NULL if not found. aIndex returns the index into - // the array successful - const TCertificateAppInfo* retVal = NULL; - TInt end = iClients.Count(); - for (TInt i = 0; i < end; ++i) - { - if (iClients[i].Id() == aUid) - { - // check if an index is required to be returned - if (aIndex) - { - *aIndex = i; - } - retVal = &iClients[i]; - break; - } - } - - return retVal; - } - -void CFSCertAppsServer::AggregateStoreFileL(const TDesC& aFile) - { - ASSERT(iPatchableConst); - - // if patchable constant is enabled - // 1. open read-only permanent file store on each file. - // 2. open certificate client entry list of each store. - // 3. aggregate the entries. - RFile file; - User::LeaveIfError(file.Open(iFs, aFile, EFileRead)); - CleanupClosePushL(file); - CPermanentFileStore* store = CPermanentFileStore::FromL(file); - // now owned by store - CleanupStack::Pop(&file); - CleanupStack::PushL(store); - - // Read id of cert list stream - TStreamId streamId; - RStoreReadStream stream; - stream.OpenLC(*store, store->Root()); - stream >> streamId; - CleanupStack::PopAndDestroy(&stream); - - // Read the certificate's clients entry list - stream.OpenLC(*store, streamId); - TInt count = stream.ReadInt32L(); - RArray entryList; - for (TInt i = 0 ; i < count ; i++) - { - TCertificateAppInfo clientInfo; - stream >> clientInfo; - entryList.AppendL(clientInfo); - } - CleanupStack::PopAndDestroy(&stream); - CleanupClosePushL(entryList); - - MergeCertificateEntryListL(entryList); - // cleanup entryList and store instances. - CleanupStack::PopAndDestroy(2,store); - } - -TBool CFSCertAppsServer::FindUid(const TUid& aUid) - { - TInt end = iClients.Count(); - for (TInt i = 0; i < end; ++i) - { - if (iClients[i].Id() == aUid) - { - return ETrue; - } - } - return EFalse; - } - -void CFSCertAppsServer::MergeCertificateEntryListL(const RArray& aSourceList) - { - ASSERT(iPatchableConst); - - // if patchable constant is enabled - TInt sourceCount = aSourceList.Count(); - for(TInt i = 0; i < sourceCount; i++) - { - // compare if the uid pre-exists in the composite list. - if (!FindUid(aSourceList[i].Id())) - { - // Aggregation: append this entry to the composite list. - iClients.AppendL(aSourceList[i]); - } - // Eclipsing: Higher order store cert client entries with same UIDs take precedence over lower order - // store cert client entries therefore the later are not included in the composite cert client entry list. - // Higher order store client entries are ones which are aggregated prior to other client entries. - } - } - -void CFSCertAppsServer::OpenCompositeStoreL(const TDesC& aFilename) - { - ASSERT(iPatchableConst); - - // 1. create a new empty certstore file under system drive with the name 'certclients.dat'. - // 2. this will be the composite store and the instances 'iEntryList' and 'iStore' will be initialized with this. - // 3. make private rom drive path where certstore files are located. - // 4. collect the certstore file names in a list. - // 5. make private rom drive path on each file. - // 6. populate the composite store with certificate client entries present in rom drive certstores. - - // create a new empty certstore file 'certclients.dat' under system drive. - CreateStoreL(aFilename); - // restore permanent store on it - // this will be the composite store after complete aggregation. - ReadStoreContentsL(aFilename); - - RBuf romFilename; - romFilename.CreateL(KMaxFilenameLength); - CleanupClosePushL(romFilename); - FileUtils::MakePrivateROMFilenameL(iFs, KCertAppsFile, romFilename); - CDir* filenameList = NULL; - User::LeaveIfError(iFs.GetDir(romFilename, KEntryAttNormal, ESortByName|EDescending, filenameList)); - CleanupStack::PopAndDestroy(&romFilename); - CleanupStack::PushL(filenameList); - TInt count = filenameList->Count(); - - // aggregate ROM stores iteratively - for(TInt index = 0; index < count; index++) - { - RBuf fileName; - fileName.CreateL(KMaxFileName); - CleanupClosePushL(fileName); - FileUtils::MakePrivateROMFilenameL(iFs, ((*filenameList)[index]).iName, fileName); - // if there is any corrupt certstore present then we will simply ignore its - // aggregation and proceed with aggregating remaining stores. - TRAP_IGNORE(AggregateStoreFileL(fileName)); - CleanupStack::PopAndDestroy(&fileName); - } - // write the 'iClients' to the composite store. - ReplaceAndCommitL(-1); - CleanupStack::PopAndDestroy(filenameList); - } - -// this logic should be handled by a superclass or mixin -void CFSCertAppsServer::OpenStoreL() - { - RBuf filename; - filename.CreateL(KMaxFilenameLength); - CleanupClosePushL(filename); - FileUtils::MakePrivateFilenameL(iFs, KCertAppsFilename, filename); - - // Attempt to open the store - // need to test opening corrupt store - TRAPD(err, ReadStoreContentsL(filename)); - - if (err == KErrNoMemory || err == KErrInUse) - { - User::Leave(err); - } - - if (err != KErrNone) - { - // Couldn't open RAM based store, copy from ROM - FileUtils::EnsurePathL(iFs, filename); - - if(iPatchableConst) - { - OpenCompositeStoreL(filename); - } - else - { - RBuf romFilename; - romFilename.CreateL(KMaxFilenameLength); - CleanupClosePushL(romFilename); - FileUtils::MakePrivateROMFilenameL(iFs, KCertAppsFilename, romFilename); - - if (FileUtils::ExistsL(iFs, romFilename)) - { - FileUtils::CopyL(iFs, romFilename, filename); - } - else - { - CreateStoreL(filename); - } - CleanupStack::PopAndDestroy(&romFilename); - //Retry open, and leave on failure - ReadStoreContentsL(filename); - } - } - CleanupStack::PopAndDestroy(&filename); - ASSERT(iStore); - } - -void CFSCertAppsServer::ReadStoreContentsL(const TDesC& aFilename) - { - // Make sure the store is not read-only - User::LeaveIfError(iFs.SetAtt(aFilename, KEntryAttNormal, KEntryAttReadOnly)); - - RFile file; - User::LeaveIfError(file.Open(iFs, aFilename, EFileRead | EFileWrite)); - CleanupClosePushL(file); - CPermanentFileStore* store = CPermanentFileStore::FromL(file); - CleanupStack::Pop(&file); - CleanupStack::PushL(store); - - // now read the root stream to get the id of our main stream - RStoreReadStream readStream; - readStream.OpenLC(*store, store->Root()); - readStream >> iId; // This can leave - CleanupStack::PopAndDestroy(&readStream); - - // finally, restore the stream which contains the client arrays. - // First long is the number of entries, then each entry - readStream.OpenLC(*store, iId); - TInt count = readStream.ReadInt32L(); - for (TInt i = 0; i < count; ++i) - { - TCertificateAppInfo clientInfo; - readStream >> clientInfo; - User::LeaveIfError(iClients.Append(clientInfo)); - } - CleanupStack::PopAndDestroy(&readStream); - - ASSERT(!iStore); - iStore = store; - CleanupStack::Pop(store); - } - -void CFSCertAppsServer::CreateStoreL(const TDesC& aFilename) - { - // If for some reason we can't complete the creation of the store, we want - // to be sure that we don't leave a half-constructed store on the device - // as we will then be in trouble when we try to open the store - TCleanupItem deleteStoreFile(DeleteStoreFile, this); - CleanupStack::PushL(deleteStoreFile); - - iFs.Delete(aFilename); // ignore errors - - RFile file; - User::LeaveIfError(file.Create(iFs, aFilename, EFileWrite)); - CleanupClosePushL(file); - - CPermanentFileStore* store = CPermanentFileStore::NewL(file); - CleanupStack::Pop(&file); // now owned by store - CleanupStack::PushL(store); - store->SetTypeL(KPermanentFileStoreLayoutUid); - - RStoreWriteStream clientsStream; - TStreamId id = clientsStream.CreateLC(*store); - WriteClientArrayL(clientsStream); - CleanupStack::PopAndDestroy(&clientsStream); - - RStoreWriteStream rootStream; - TStreamId rootId = rootStream.CreateLC(*store); - rootStream << id; - rootStream.CommitL(); - CleanupStack::PopAndDestroy(&rootStream); - - store->SetRootL(rootId); - store->CommitL(); - - CleanupStack::PopAndDestroy(store); - CleanupStack::Pop(); // deleteStoreFile - } - -void CFSCertAppsServer::RevertStore(TAny* aStore) - { - // this is a CleanupItem - __ASSERT_DEBUG(aStore, PanicServer(EPanicNotInitialised)); - - CPermanentFileStore* store = reinterpret_cast(aStore); - store->Revert(); - } - -void CFSCertAppsServer::DeleteStoreFile(TAny *aThis) - { - __ASSERT_DEBUG(aThis, PanicServer(EPanicNotInitialised)); - - // should call non-static member - - CFSCertAppsServer* self = reinterpret_cast(aThis); - - // Something strange has occurred if we can't get the ramStorePath. - // Since we can't leave we have to ignore the error - TFileName ramStorePath; - TRAPD(err, FileUtils::MakePrivateFilenameL(self->iFs, KCertAppsFilename, ramStorePath)); - if (!err) - { - self->iFs.Delete(ramStorePath); - } - } - -void CFSCertAppsServer::ReplaceAndCommitL(TInt aExcludedIndex) - { - TCleanupItem cleanupStore(RevertStore, iStore); - CleanupStack::PushL(cleanupStore); - - // compact the store - iStore->ReclaimL(); // do we need to reclaim - iStore->CompactL(); - - RStoreWriteStream outputStream; - outputStream.ReplaceLC(*iStore, iId); - - WriteClientArrayL(outputStream, aExcludedIndex); - - CleanupStack::PopAndDestroy(&outputStream); - iStore->CommitL(); - CleanupStack::Pop(); // cleanupStore - } - -void CFSCertAppsServer::WriteClientArrayL(RWriteStream& stream, TInt aExcludedIndex) const - { - // the count of elements to be written is the arraycount - 1 if we exclude - // something, otherwise the arraycount - TInt arrayEnd = iClients.Count(); - TInt count = (aExcludedIndex < 0) ? (arrayEnd) : (arrayEnd - 1); - - stream.WriteInt32L(count); - - for (TInt i = 0; i < arrayEnd; ++i) - { - if (i != aExcludedIndex) - { - stream << iClients[i]; // This can leave - } - } - stream.CommitL(); - } +/* +* Copyright (c) 2002-2009 Nokia Corporation and/or its subsidiary(-ies). +* All rights reserved. +* This component and the accompanying materials are made available +* under the terms of the License "Eclipse Public License v1.0" +* which accompanies this distribution, and is available +* at the URL "http://www.eclipse.org/legal/epl-v10.html". +* +* Initial Contributors: +* Nokia Corporation - initial contribution. +* +* Contributors: +* +* Description: +* +*/ + + +#include "CFSCertAppsServer.h" +#include "CCertAppsSession.h" +#include "CCertAppsConduit.h" +#include "fstokencliserv.h" +#include "fstokenutil.h" + +#include +#include +#include + +// Filename where all data is stored +_LIT(KCertAppsFilename,"certclients.dat"); +_LIT(KCertAppsFile,"certclients*.dat"); + +CFSCertAppsServer* CFSCertAppsServer::NewL() + { + CFSCertAppsServer* self = new (ELeave) CFSCertAppsServer(); + CleanupStack::PushL(self); + self->ConstructL(); + CleanupStack::Pop(self); + return self; + } + +CFSCertAppsServer::CFSCertAppsServer() + { + } + +void CFSCertAppsServer::ConstructL() + { + iConduit = CCertAppsConduit::NewL(*this); + + // Connect to the filesystem + User::LeaveIfError(iFs.Connect()); + + iPatchableConst = KAggregateCertStore; + + #ifdef __WINS__ + // For the emulator allow the constant to be patched via epoc.ini + UserSvr::HalFunction(EHalGroupEmulator, EEmulatorHalIntProperty, + (TAny*)"KAggregateCertStore", &iPatchableConst); // read emulator property (if present) + #endif + + // Retrieves the store + OpenStoreL(); + } + +CFSCertAppsServer::~CFSCertAppsServer() + { + delete iStore; + iFs.Close(); + iClients.Close(); + delete iConduit; + } + +CCertAppsSession* CFSCertAppsServer::CreateSessionL() + { + return CCertAppsSession::NewL(*iConduit); + } + +void CFSCertAppsServer::AddL(const TCertificateAppInfo& aClient) + { + // see if application already exists. If so, then leave + + if (FindApplication(aClient.Id())) + { + User::Leave(KErrAlreadyExists); + } + User::LeaveIfError(iClients.Append(aClient)); + TRAPD(err, ReplaceAndCommitL(-1)); + if (err != KErrNone) + { + // We must remove the client from iClients if we didn't manage + // to add it to the store + iClients.Remove(iClients.Count() - 1); + User::Leave(err); + } + } + +void CFSCertAppsServer::RemoveL(const TUid& aUid) + { + // Make sure the application for that uid exists + TInt i; + if (!FindApplication(aUid, &i)) + { + User::Leave(KErrNotFound); + } + + ReplaceAndCommitL(i); + + // We managed to remove it from the store, so we remove it from the + // iClients array + iClients.Remove(i); + } + +TInt CFSCertAppsServer::ApplicationCountL() const + { + return iClients.Count(); + } + +void CFSCertAppsServer::ApplicationsL(RArray& aAppArray) const + { + // Make a copy of the array + TInt count = iClients.Count(); + + for (TInt i = 0; i < count; ++i) + { + aAppArray.Append(iClients[i]); + } + } + +void CFSCertAppsServer::ApplicationL(const TUid& aUid, TCertificateAppInfo& aInfo) const + { + const TCertificateAppInfo* app = FindApplication(aUid); + + // leave if not found + if (!app) + { + User::Leave(KErrNotFound); + } + + // make a copy and return to client + aInfo = *app; + } + +const TCertificateAppInfo* CFSCertAppsServer::FindApplication(const TUid& aUid, TInt* aIndex) const + { + // This helper function tries to find an application with the given + // Uid. It returns NULL if not found. aIndex returns the index into + // the array successful + const TCertificateAppInfo* retVal = NULL; + TInt end = iClients.Count(); + for (TInt i = 0; i < end; ++i) + { + if (iClients[i].Id() == aUid) + { + // check if an index is required to be returned + if (aIndex) + { + *aIndex = i; + } + retVal = &iClients[i]; + break; + } + } + + return retVal; + } + +void CFSCertAppsServer::AggregateStoreFileL(const TDesC& aFile) + { + ASSERT(iPatchableConst); + + // if patchable constant is enabled + // 1. open read-only permanent file store on each file. + // 2. open certificate client entry list of each store. + // 3. aggregate the entries. + RFile file; + User::LeaveIfError(file.Open(iFs, aFile, EFileRead)); + CleanupClosePushL(file); + CPermanentFileStore* store = CPermanentFileStore::FromL(file); + // now owned by store + CleanupStack::Pop(&file); + CleanupStack::PushL(store); + + // Read id of cert list stream + TStreamId streamId; + RStoreReadStream stream; + stream.OpenLC(*store, store->Root()); + stream >> streamId; + CleanupStack::PopAndDestroy(&stream); + + // Read the certificate's clients entry list + stream.OpenLC(*store, streamId); + TInt count = stream.ReadInt32L(); + RArray entryList; + for (TInt i = 0 ; i < count ; i++) + { + TCertificateAppInfo clientInfo; + stream >> clientInfo; + entryList.AppendL(clientInfo); + } + CleanupStack::PopAndDestroy(&stream); + CleanupClosePushL(entryList); + + MergeCertificateEntryListL(entryList); + // cleanup entryList and store instances. + CleanupStack::PopAndDestroy(2,store); + } + +TBool CFSCertAppsServer::FindUid(const TUid& aUid) + { + TInt end = iClients.Count(); + for (TInt i = 0; i < end; ++i) + { + if (iClients[i].Id() == aUid) + { + return ETrue; + } + } + return EFalse; + } + +void CFSCertAppsServer::MergeCertificateEntryListL(const RArray& aSourceList) + { + ASSERT(iPatchableConst); + + // if patchable constant is enabled + TInt sourceCount = aSourceList.Count(); + for(TInt i = 0; i < sourceCount; i++) + { + // compare if the uid pre-exists in the composite list. + if (!FindUid(aSourceList[i].Id())) + { + // Aggregation: append this entry to the composite list. + iClients.AppendL(aSourceList[i]); + } + // Eclipsing: Higher order store cert client entries with same UIDs take precedence over lower order + // store cert client entries therefore the later are not included in the composite cert client entry list. + // Higher order store client entries are ones which are aggregated prior to other client entries. + } + } + +void CFSCertAppsServer::OpenCompositeStoreL(const TDesC& aFilename) + { + ASSERT(iPatchableConst); + + // 1. create a new empty certstore file under system drive with the name 'certclients.dat'. + // 2. this will be the composite store and the instances 'iEntryList' and 'iStore' will be initialized with this. + // 3. make private rom drive path where certstore files are located. + // 4. collect the certstore file names in a list. + // 5. make private rom drive path on each file. + // 6. populate the composite store with certificate client entries present in rom drive certstores. + + // create a new empty certstore file 'certclients.dat' under system drive. + CreateStoreL(aFilename); + // restore permanent store on it + // this will be the composite store after complete aggregation. + ReadStoreContentsL(aFilename); + + RBuf romFilename; + romFilename.CreateL(KMaxFilenameLength); + CleanupClosePushL(romFilename); + FileUtils::MakePrivateROMFilenameL(iFs, KCertAppsFile, romFilename); + CDir* filenameList = NULL; + User::LeaveIfError(iFs.GetDir(romFilename, KEntryAttNormal, ESortByName|EDescending, filenameList)); + CleanupStack::PopAndDestroy(&romFilename); + CleanupStack::PushL(filenameList); + TInt count = filenameList->Count(); + + // aggregate ROM stores iteratively + for(TInt index = 0; index < count; index++) + { + RBuf fileName; + fileName.CreateL(KMaxFileName); + CleanupClosePushL(fileName); + FileUtils::MakePrivateROMFilenameL(iFs, ((*filenameList)[index]).iName, fileName); + // if there is any corrupt certstore present then we will simply ignore its + // aggregation and proceed with aggregating remaining stores. + TRAP_IGNORE(AggregateStoreFileL(fileName)); + CleanupStack::PopAndDestroy(&fileName); + } + // write the 'iClients' to the composite store. + ReplaceAndCommitL(-1); + CleanupStack::PopAndDestroy(filenameList); + } + +// this logic should be handled by a superclass or mixin +void CFSCertAppsServer::OpenStoreL() + { + RBuf filename; + filename.CreateL(KMaxFilenameLength); + CleanupClosePushL(filename); + FileUtils::MakePrivateFilenameL(iFs, KCertAppsFilename, filename); + + // Attempt to open the store + // need to test opening corrupt store + TRAPD(err, ReadStoreContentsL(filename)); + + if (err == KErrNoMemory || err == KErrInUse) + { + User::Leave(err); + } + + if (err != KErrNone) + { + // Couldn't open RAM based store, copy from ROM + FileUtils::EnsurePathL(iFs, filename); + + if(iPatchableConst) + { + OpenCompositeStoreL(filename); + } + else + { + RBuf romFilename; + romFilename.CreateL(KMaxFilenameLength); + CleanupClosePushL(romFilename); + FileUtils::MakePrivateROMFilenameL(iFs, KCertAppsFilename, romFilename); + + if (FileUtils::ExistsL(iFs, romFilename)) + { + FileUtils::CopyL(iFs, romFilename, filename); + } + else + { + CreateStoreL(filename); + } + CleanupStack::PopAndDestroy(&romFilename); + //Retry open, and leave on failure + ReadStoreContentsL(filename); + } + } + CleanupStack::PopAndDestroy(&filename); + ASSERT(iStore); + } + +void CFSCertAppsServer::ReadStoreContentsL(const TDesC& aFilename) + { + // Make sure the store is not read-only + User::LeaveIfError(iFs.SetAtt(aFilename, KEntryAttNormal, KEntryAttReadOnly)); + + RFile file; + User::LeaveIfError(file.Open(iFs, aFilename, EFileRead | EFileWrite)); + CleanupClosePushL(file); + CPermanentFileStore* store = CPermanentFileStore::FromL(file); + CleanupStack::Pop(&file); + CleanupStack::PushL(store); + + // now read the root stream to get the id of our main stream + RStoreReadStream readStream; + readStream.OpenLC(*store, store->Root()); + readStream >> iId; // This can leave + CleanupStack::PopAndDestroy(&readStream); + + // finally, restore the stream which contains the client arrays. + // First long is the number of entries, then each entry + readStream.OpenLC(*store, iId); + TInt count = readStream.ReadInt32L(); + for (TInt i = 0; i < count; ++i) + { + TCertificateAppInfo clientInfo; + readStream >> clientInfo; + User::LeaveIfError(iClients.Append(clientInfo)); + } + CleanupStack::PopAndDestroy(&readStream); + + ASSERT(!iStore); + iStore = store; + CleanupStack::Pop(store); + } + +void CFSCertAppsServer::CreateStoreL(const TDesC& aFilename) + { + // If for some reason we can't complete the creation of the store, we want + // to be sure that we don't leave a half-constructed store on the device + // as we will then be in trouble when we try to open the store + TCleanupItem deleteStoreFile(DeleteStoreFile, this); + CleanupStack::PushL(deleteStoreFile); + + iFs.Delete(aFilename); // ignore errors + + RFile file; + User::LeaveIfError(file.Create(iFs, aFilename, EFileWrite)); + CleanupClosePushL(file); + + CPermanentFileStore* store = CPermanentFileStore::NewL(file); + CleanupStack::Pop(&file); // now owned by store + CleanupStack::PushL(store); + store->SetTypeL(KPermanentFileStoreLayoutUid); + + RStoreWriteStream clientsStream; + TStreamId id = clientsStream.CreateLC(*store); + WriteClientArrayL(clientsStream); + CleanupStack::PopAndDestroy(&clientsStream); + + RStoreWriteStream rootStream; + TStreamId rootId = rootStream.CreateLC(*store); + rootStream << id; + rootStream.CommitL(); + CleanupStack::PopAndDestroy(&rootStream); + + store->SetRootL(rootId); + store->CommitL(); + + CleanupStack::PopAndDestroy(store); + CleanupStack::Pop(); // deleteStoreFile + } + +void CFSCertAppsServer::RevertStore(TAny* aStore) + { + // this is a CleanupItem + __ASSERT_DEBUG(aStore, PanicServer(EPanicNotInitialised)); + + CPermanentFileStore* store = reinterpret_cast(aStore); + store->Revert(); + } + +void CFSCertAppsServer::DeleteStoreFile(TAny *aThis) + { + __ASSERT_DEBUG(aThis, PanicServer(EPanicNotInitialised)); + + // should call non-static member + + CFSCertAppsServer* self = reinterpret_cast(aThis); + + // Something strange has occurred if we can't get the ramStorePath. + // Since we can't leave we have to ignore the error + TFileName ramStorePath; + TRAPD(err, FileUtils::MakePrivateFilenameL(self->iFs, KCertAppsFilename, ramStorePath)); + if (!err) + { + self->iFs.Delete(ramStorePath); + } + } + +void CFSCertAppsServer::ReplaceAndCommitL(TInt aExcludedIndex) + { + TCleanupItem cleanupStore(RevertStore, iStore); + CleanupStack::PushL(cleanupStore); + + // compact the store + iStore->ReclaimL(); // do we need to reclaim + iStore->CompactL(); + + RStoreWriteStream outputStream; + outputStream.ReplaceLC(*iStore, iId); + + WriteClientArrayL(outputStream, aExcludedIndex); + + CleanupStack::PopAndDestroy(&outputStream); + iStore->CommitL(); + CleanupStack::Pop(); // cleanupStore + } + +void CFSCertAppsServer::WriteClientArrayL(RWriteStream& stream, TInt aExcludedIndex) const + { + // the count of elements to be written is the arraycount - 1 if we exclude + // something, otherwise the arraycount + TInt arrayEnd = iClients.Count(); + TInt count = (aExcludedIndex < 0) ? (arrayEnd) : (arrayEnd - 1); + + stream.WriteInt32L(count); + + for (TInt i = 0; i < arrayEnd; ++i) + { + if (i != aExcludedIndex) + { + stream << iClients[i]; // This can leave + } + } + stream.CommitL(); + }