remotemgmt_plat/syncml_ds_customization_api/tsrc/synchconfigvalidator/customdatasynchconfigvalidatorengine_p.cpp
branchRCL_3
changeset 25 b183ec05bd8c
equal deleted inserted replaced
24:13d7c31c74e0 25:b183ec05bd8c
       
     1 /*
       
     2 * Copyright (c) 2009 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: 
       
    15 *
       
    16 */
       
    17 
       
    18 // CLASS HEADER
       
    19 #include "customdatasynchconfigvalidatorengine_p.h"
       
    20 
       
    21 // INTERNAL INCLUDES
       
    22 #include "customdatasynchconfigvalidatorenginewrapper.h"
       
    23 #include "customdatasynchdeviceinfo.h"
       
    24 
       
    25 // EXTERNAL INCLUDES
       
    26 #include <etel3rdparty.h>
       
    27 #include <sysutil.h>
       
    28 #include <centralrepository.h>
       
    29 #include <ecom/ecom.h>
       
    30 #include <e32def.h>
       
    31 #include <utf.h>
       
    32 #include <nsmloperatordatacrkeys.h>
       
    33 #include <nsmloperatorerrorcrkeys.h>
       
    34 #include <syncmlclientds.h>
       
    35 
       
    36 #include <d32dbms.h>
       
    37 #include <f32file.h>
       
    38 
       
    39 const TUid KCRUidDatasyncKeys = { 0x2000CF7E };
       
    40 const TUint32 KDataSynchCustomProfileKey = 0x0;
       
    41 const QString SERVERID_DB_COLUMN_NAME = "ServerId";
       
    42 const QString PROFILEID_DB_COLUMN_NAME = "Id";
       
    43 
       
    44 // Utility clean up function
       
    45 void CleanupEComArray(TAny* aArray);
       
    46 
       
    47 // ----------------------------------------------------------------------------
       
    48 CustomDataSynchConfigValidatorEngine::CustomDataSynchConfigValidatorEngine(
       
    49     CustomDataSynchConfigValidatorEngineWrapper *parent) :
       
    50     q(parent)
       
    51 {
       
    52 }
       
    53 
       
    54 // ----------------------------------------------------------------------------
       
    55 CustomDataSynchConfigValidatorEngine::~CustomDataSynchConfigValidatorEngine()
       
    56 {
       
    57 }
       
    58 
       
    59 // ----------------------------------------------------------------------------
       
    60 bool CustomDataSynchConfigValidatorEngine::dataSynchCenrepExists()
       
    61 {
       
    62     int initError = KErrGeneral;
       
    63     TRAP(initError,
       
    64         CRepository* dataSynchCenrep = CRepository::NewL(KCRUidDatasyncKeys);
       
    65         delete dataSynchCenrep;
       
    66     )
       
    67     return (initError == KErrNone ? true : false);
       
    68 }
       
    69 
       
    70 // ----------------------------------------------------------------------------
       
    71 bool CustomDataSynchConfigValidatorEngine::operatordataSynchCenrepExists()
       
    72 {
       
    73     int initError = KErrGeneral;
       
    74     TRAP(initError,
       
    75         CRepository* operatordataSynchCenrep = CRepository::NewL(KCRUidOperatorDatasyncInternalKeys);
       
    76         delete operatordataSynchCenrep;
       
    77     )
       
    78     return (initError == KErrNone ? true : false);
       
    79 }
       
    80 
       
    81 // ----------------------------------------------------------------------------
       
    82 bool CustomDataSynchConfigValidatorEngine::operatordataSynchErrorCenrepExists()
       
    83 {
       
    84     int initError = KErrGeneral;
       
    85     TRAP(initError,
       
    86         CRepository* operatordataSynchErrorCenrep = CRepository::NewL(KCRUidOperatorDatasyncErrorKeys);
       
    87         delete operatordataSynchErrorCenrep;
       
    88     )
       
    89     return (initError == KErrNone ? true : false);
       
    90 }
       
    91 
       
    92 // ----------------------------------------------------------------------------
       
    93 bool CustomDataSynchConfigValidatorEngine::customSynchProfilesAllowed()
       
    94 {
       
    95     int initError = KErrGeneral;//CRepository::Get or CRepository::NewL
       
    96     int customProfileKeyValue = 0;//value 1 means allowed
       
    97     TRAP(initError,
       
    98         CRepository* dataSynchCenrep = CRepository::NewL(KCRUidDatasyncKeys);
       
    99         initError = dataSynchCenrep->Get(KDataSynchCustomProfileKey,customProfileKeyValue);
       
   100         delete dataSynchCenrep;
       
   101     )
       
   102     return (initError == KErrNone && customProfileKeyValue == 1 ? true : false);
       
   103 }
       
   104 
       
   105 // ----------------------------------------------------------------------------
       
   106 bool CustomDataSynchConfigValidatorEngine::configuredContactsAdapterExists(
       
   107     QString & errorMsg)
       
   108 {
       
   109     int initError = KErrGeneral;//CRepository::Get or CRepository::NewL
       
   110     int pluginloadError = KErrGeneral;
       
   111     
       
   112     TUid adapterUid = {0x101F6DDD};//platformcontactadapter Uid
       
   113     
       
   114     TRAP(initError,
       
   115         CRepository* operatordataSynchCenrep = CRepository::NewL(KCRUidOperatorDatasyncInternalKeys);
       
   116     int adapterUidInt = 0;
       
   117     int errorCode = operatordataSynchCenrep->Get(KNsmlOpDsOperatorAdapterUid,adapterUidInt);
       
   118     delete operatordataSynchCenrep;
       
   119     if( adapterUidInt > 0 )
       
   120     {//if greater than 0 custom contact adapter is 'likely' to be used
       
   121         adapterUid = TUid::Uid(adapterUidInt);
       
   122     }
       
   123     )
       
   124     TRAP(pluginloadError,
       
   125         TAny* any = REComSession::CreateImplementationL(adapterUid, _FOFF(CustomDataSynchConfigValidatorEngine, iEComDtorKey));
       
   126         REComSession::DestroyedImplementation(iEComDtorKey);
       
   127     )
       
   128     bool success = (initError == KErrNone && pluginloadError == KErrNone) ? true : false;
       
   129     if(!success)
       
   130     {
       
   131         errorMsg = "Problems loading adapter UID: 0x";
       
   132         errorMsg = errorMsg+QString::number(adapterUid.iUid,16).toUpper(); 
       
   133     }
       
   134     
       
   135     return success;
       
   136 }
       
   137 
       
   138 // ----------------------------------------------------------------------------
       
   139 bool CustomDataSynchConfigValidatorEngine::configuredCustomSynchProfileExists(QString & errorMsg)
       
   140 {
       
   141     int cenrepError = KErrGeneral;//CRepository::Get or CRepository::NewL
       
   142     bool serverIdmatchFound = false;
       
   143     bool dbOk = false;
       
   144     
       
   145     QString cenrepServerIdString;
       
   146     QString profileServerId;
       
   147     
       
   148     TRAP(cenrepError,      
       
   149         CRepository* operatordataSynchCenrep = CRepository::NewL(KCRUidOperatorDatasyncInternalKeys);
       
   150         TBuf8<50> cenrepServerIdBuf;
       
   151         cenrepError = operatordataSynchCenrep->Get(KNsmlOpDsOperatorSyncServerId,cenrepServerIdBuf);
       
   152         delete operatordataSynchCenrep;
       
   153         HBufC* cenrepServerIdHBufC;
       
   154         cenrepServerIdHBufC = CnvUtfConverter::ConvertToUnicodeFromUtf8L(cenrepServerIdBuf);
       
   155         cenrepServerIdString = QString::fromUtf16(cenrepServerIdHBufC->Ptr(), cenrepServerIdHBufC->Length());
       
   156         delete cenrepServerIdHBufC;
       
   157     )
       
   158     dbOk = getStringValueFromSyncProfileSettingsDb(profileServerId,SERVERID_DB_COLUMN_NAME);
       
   159     serverIdmatchFound = cenrepServerIdString.compare(profileServerId)==0 ? true : false;
       
   160 
       
   161     bool success = (cenrepError == KErrNone && dbOk) ? serverIdmatchFound : false;
       
   162     if(!success){
       
   163         errorMsg = "Problems with Cenrep defined ServerId:["+cenrepServerIdString+"]"; 
       
   164     }
       
   165     return success;
       
   166 }
       
   167 
       
   168 // ----------------------------------------------------------------------------
       
   169 bool CustomDataSynchConfigValidatorEngine::contactAdapterCenrepValueToProfileMatches(QString & errorMsg)
       
   170 {
       
   171     int cenrepError = KErrGeneral;//CRepository::Get or CRepository::NewL
       
   172     
       
   173     TUid cenrepAdapterUid = { 0x101F6DDD };//platformcontactadapter Uid
       
   174     int adapterUidInt = 0;
       
   175     TRAP(cenrepError, 
       
   176         CRepository* operatordataSynchCenrep = CRepository::NewL(KCRUidOperatorDatasyncInternalKeys);
       
   177         cenrepError = operatordataSynchCenrep->Get(KNsmlOpDsOperatorAdapterUid,adapterUidInt);
       
   178         delete operatordataSynchCenrep;
       
   179         )
       
   180     if( adapterUidInt > 0 )
       
   181     {//if greater than 0 custom contact adapter is 'likely' to be used
       
   182         cenrepAdapterUid = TUid::Uid(adapterUidInt);
       
   183     }
       
   184     return adapterCenrepValueToProfileMatches(errorMsg, cenrepAdapterUid);
       
   185 }
       
   186 
       
   187 // ----------------------------------------------------------------------------
       
   188 bool CustomDataSynchConfigValidatorEngine::myprofileAdapterCenrepValueToProfileMatches(QString & errorMsg)
       
   189 {
       
   190     int cenrepError = KErrGeneral;//CRepository::Get or CRepository::NewL  
       
   191     TUid cenrepAdapterUid = { 0x0 };
       
   192     int adapterUidInt = 0;
       
   193     TRAP(cenrepError,
       
   194         CRepository* operatordataSynchCenrep = CRepository::NewL(KCRUidOperatorDatasyncInternalKeys);
       
   195         cenrepError = operatordataSynchCenrep->Get(KNsmlOpDsProfileAdapterUid,adapterUidInt);
       
   196         delete operatordataSynchCenrep;
       
   197     )
       
   198     if( adapterUidInt > 0 )
       
   199     {//if greater than 0 custom contact adapter is 'likely' to be used
       
   200         cenrepAdapterUid = TUid::Uid(adapterUidInt);
       
   201     }    
       
   202     return adapterCenrepValueToProfileMatches(errorMsg, cenrepAdapterUid);
       
   203 }
       
   204 
       
   205 // ----------------------------------------------------------------------------
       
   206 bool CustomDataSynchConfigValidatorEngine::devInfoExtensionPluginAvailable()
       
   207 {
       
   208     TUid devInfoExtensionPluginUid = { 0x2002DC7C };
       
   209     int err = KErrGeneral;
       
   210     bool pluginExists = false;
       
   211     RImplInfoPtrArray implInfoArray;
       
   212     TCleanupItem cleanup( CleanupEComArray, &implInfoArray );
       
   213     TRAP(err,
       
   214         CleanupStack::PushL( cleanup );
       
   215         REComSession::ListImplementationsL(
       
   216             devInfoExtensionPluginUid, implInfoArray );
       
   217     if( err == KErrNone && implInfoArray.Count() > 0 )
       
   218     {
       
   219         pluginExists = true;
       
   220     }
       
   221 
       
   222     CleanupStack::PopAndDestroy(); // implInfoArray
       
   223     )
       
   224     return pluginExists;
       
   225 }
       
   226 
       
   227 //
       
   228 // Helper functions
       
   229 //
       
   230 //
       
   231 // ----------------------------------------------------------------------------
       
   232 bool CustomDataSynchConfigValidatorEngine::adapterCenrepValueToProfileMatches(QString & errorMsg, TUid adapterUid)
       
   233 {
       
   234     int profileOpenError = KErrGeneral;
       
   235     bool adapterMatchFound = false;
       
   236     
       
   237     int dbProfileId = operatorProfileIdFromProfilesDB();
       
   238     if(dbProfileId<0)
       
   239     {//No profile Id or cenrep server Id could not found
       
   240         errorMsg = "Test cannot proceed. No profile id was acquired or cenrepServerId was not configured.";
       
   241         return false;//RSyncMLDataSyncProfile.OpenL panics
       
   242     }
       
   243     //Get Contact Adapter UID from synch profile 
       
   244     TRAP(profileOpenError,
       
   245         RSyncMLSession syncMLSession;
       
   246         RArray<TSmlProfileId> profiles;
       
   247         syncMLSession.OpenL();
       
   248         CleanupClosePushL(syncMLSession);
       
   249         // Get the list of available profiles into an array
       
   250         syncMLSession.ListProfilesL(profiles, ESmlDataSync);
       
   251         QString dataProviderString = NULL;
       
   252         QString serverDataSourceName;
       
   253     
       
   254         for(int i=0; i < profiles.Count(); i++)
       
   255         {
       
   256             RSyncMLDataSyncProfile profile;
       
   257             profile.OpenL(syncMLSession,profiles[i],ESmlOpenRead);
       
   258             if (!profileOpenError) {//-42 PermissionDenied -> Capabilities problem
       
   259                 CleanupClosePushL(profile);
       
   260                 RArray<TSmlTaskId> profileTasks;
       
   261                 CleanupClosePushL(profileTasks);
       
   262                 profile.ListTasksL(profileTasks);
       
   263                 for (int j = 0; j < profileTasks.Count(); j++) {
       
   264                     RSyncMLTask task;
       
   265                     task.OpenL(profile, profileTasks[j]);
       
   266                     CleanupClosePushL(task);
       
   267                     if(task.Profile() == dbProfileId)
       
   268                     {
       
   269                         int taskProviderInt = task.DataProvider();
       
   270                         int cenrepProviderInt = adapterUid.iUid;
       
   271                         if(task.DataProvider()==adapterUid.iUid)
       
   272                         {
       
   273                             serverDataSourceName = QString((QChar*) task.ServerDataSource().Ptr(),
       
   274                                 task.ServerDataSource().Length());
       
   275                             adapterMatchFound = true;
       
   276                         }
       
   277                     }
       
   278                     CleanupStack::PopAndDestroy(&task);
       
   279                 }
       
   280                 CleanupStack::PopAndDestroy(&profileTasks);
       
   281                 CleanupStack::PopAndDestroy(&profile);
       
   282             }
       
   283         }
       
   284         if(profileOpenError==KErrNone)
       
   285         {
       
   286             profiles.Close();
       
   287         }
       
   288         CleanupStack::PopAndDestroy(&syncMLSession);
       
   289     )
       
   290     bool success = (profileOpenError == KErrNone) ? adapterMatchFound : false;
       
   291     if(!success)
       
   292     {
       
   293         errorMsg = "No match found.";
       
   294         errorMsg = errorMsg + "\n\n [dbProfileId]=("+QString::number(dbProfileId)+")";
       
   295         errorMsg = errorMsg + "\n [cenrepAdapterUid]=\n("+"0x"+QString::number(adapterUid.iUid,16).toUpper()+")";
       
   296         errorMsg = errorMsg + "\n\n [profileOpenError]=("+QString::number(profileOpenError)+")";
       
   297     }
       
   298     return success;
       
   299 }
       
   300 
       
   301 // ----------------------------------------------------------------------------
       
   302 bool CustomDataSynchConfigValidatorEngine::getStringValueFromSyncProfileSettingsDb(QString& value,QString columnName,QString whereTypeConditionForSql)
       
   303 {
       
   304     //profileDbOpenError can be caused by RFs,RDbs,RDbNamedDatabase,RDbTable or RDbView startup sequences
       
   305     int profileDbOpenError = KErrGeneral;
       
   306     bool resultsFromDbWithQuery = false;
       
   307     
       
   308     TPtrC columnNamePtr (static_cast<const TUint16*>(columnName.utf16()), columnName.length());
       
   309        
       
   310     QString syncSettingsDbName = "\\private\\100012a5\\DBS_101F99FB_nsmldssettings.db";
       
   311     QString syncSettingsDbTableProfiles = "Profiles";
       
   312     TPtrC syncSettingsDbNamePtr (static_cast<const TUint16*>(syncSettingsDbName.utf16()), syncSettingsDbName.length());
       
   313     TPtrC syncSettingsDbTableProfilesPtr (static_cast<const TUint16*>(syncSettingsDbTableProfiles.utf16()), syncSettingsDbTableProfiles.length());
       
   314     
       
   315     //Query & where condition handling
       
   316     QString sqlGetProfileQuery = "SELECT * FROM Profiles";
       
   317     if(whereTypeConditionForSql.length()>0)
       
   318     {
       
   319         sqlGetProfileQuery = sqlGetProfileQuery+" WHERE "+whereTypeConditionForSql;
       
   320     }
       
   321     TPtrC sqlQueryPtr (static_cast<const TUint16*>(sqlGetProfileQuery.utf16()), sqlGetProfileQuery.length());
       
   322     
       
   323     //DB INIT
       
   324     RDbNamedDatabase database;
       
   325     RFs fsSession;
       
   326     RDbs rdbSession;
       
   327     RDbTable dbTableProfiles;
       
   328     CDbColSet* dbColSet;
       
   329     RDbView dbView;   
       
   330     TRAP(profileDbOpenError,
       
   331         //DB CONNECT
       
   332         profileDbOpenError = fsSession.Connect();
       
   333         CleanupClosePushL(fsSession);
       
   334         profileDbOpenError = rdbSession.Connect();
       
   335         CleanupClosePushL(rdbSession);
       
   336         int i = 0;
       
   337         profileDbOpenError = KErrGeneral;//else DBMS 2 panic is rised in dbTableProfiles.Open
       
   338         while (i < 10 && profileDbOpenError != KErrNone)
       
   339         {//100ms synchronous waits max. 1sec
       
   340             profileDbOpenError = database.Open(fsSession,syncSettingsDbNamePtr);
       
   341             User::After(100000);
       
   342             i++;
       
   343         }
       
   344         CleanupClosePushL(database);
       
   345         profileDbOpenError = dbTableProfiles.Open( database, syncSettingsDbTableProfilesPtr );
       
   346         CleanupClosePushL(dbTableProfiles);
       
   347     
       
   348         //DB QUERY
       
   349         profileDbOpenError = dbView.Prepare( database, TDbQuery( sqlQueryPtr ), dbView.EReadOnly );
       
   350         CleanupClosePushL(dbView);
       
   351         dbColSet = dbTableProfiles.ColSetL();
       
   352         CleanupStack::PushL(dbColSet);
       
   353     
       
   354         while(profileDbOpenError!=KErrArgument&&dbView.NextL())
       
   355         {//if results and no db error
       
   356             resultsFromDbWithQuery = true;
       
   357             dbView.GetL();
       
   358             if(columnName.compare(PROFILEID_DB_COLUMN_NAME)==0)
       
   359             {//Uint 
       
   360                 TUint valueFromDb = dbView.ColUint( dbColSet->ColNo( columnNamePtr ));
       
   361                 value.setNum(valueFromDb);
       
   362             }
       
   363             else if(columnName.compare(SERVERID_DB_COLUMN_NAME)==0)
       
   364             {//String types
       
   365                 QString valueFromDb ((QChar*)dbView.ColDes( dbColSet->ColNo( columnNamePtr )).Ptr(),
       
   366                     dbView.ColDes(dbColSet->ColNo( columnNamePtr )).Length());
       
   367                 value=valueFromDb;
       
   368             }
       
   369         }
       
   370         //DB CLOSE
       
   371         CleanupStack::PopAndDestroy(dbColSet);
       
   372         CleanupStack::PopAndDestroy(5,&fsSession);
       
   373     )
       
   374     
       
   375     return profileDbOpenError == KErrNone ? resultsFromDbWithQuery : false;
       
   376 }
       
   377 
       
   378 // ----------------------------------------------------------------------------
       
   379 int CustomDataSynchConfigValidatorEngine::operatorProfileIdFromProfilesDB()
       
   380 {
       
   381     int profileId = -1;//Return this value if problems during fetch
       
   382     int cenrepError = KErrGeneral; //CRepository::Get or CRepository::NewL
       
   383     bool dbOk = false;
       
   384     
       
   385     //Find right Synch profile based on trusted cenrep configured Server Id
       
   386     QString profileIdString;
       
   387     QString cenrepServerIdString;
       
   388     
       
   389     TRAP(cenrepError,
       
   390         CRepository* operatordataSynchCenrep = CRepository::NewL(KCRUidOperatorDatasyncInternalKeys);
       
   391         TBuf8<50> cenrepServerIdBuf;
       
   392         cenrepError = operatordataSynchCenrep->Get(KNsmlOpDsOperatorSyncServerId,cenrepServerIdBuf);
       
   393         delete operatordataSynchCenrep;
       
   394         HBufC* cenrepServerIdHBufC;
       
   395         cenrepServerIdHBufC = CnvUtfConverter::ConvertToUnicodeFromUtf8L(cenrepServerIdBuf);
       
   396         cenrepServerIdString = QString::fromUtf16(cenrepServerIdHBufC->Ptr(), cenrepServerIdHBufC->Length());
       
   397         delete cenrepServerIdHBufC;
       
   398     )
       
   399     if(cenrepServerIdString.compare("")==0)
       
   400     {//protect against DBMS panic 2
       
   401         return profileId;//-1
       
   402     }
       
   403     QString whereCondition = SERVERID_DB_COLUMN_NAME+"='"+cenrepServerIdString+"'";
       
   404     dbOk = getStringValueFromSyncProfileSettingsDb(profileIdString,PROFILEID_DB_COLUMN_NAME,whereCondition);
       
   405     if(dbOk)
       
   406     {
       
   407         profileId = profileIdString.toInt();
       
   408     }
       
   409     return profileId;//error handling needs to be done in calling code
       
   410 }
       
   411 
       
   412 // ----------------------------------------------------------------------------
       
   413 QString CustomDataSynchConfigValidatorEngine::imei() const
       
   414 {
       
   415     QScopedPointer<CDeviceInfo> deviceInfo(CDeviceInfo::NewL());
       
   416     TBuf<CTelephony::KPhoneSerialNumberSize> imei(deviceInfo->imei());
       
   417     return QString::fromUtf16(imei.Ptr(), imei.Length());
       
   418 }
       
   419 
       
   420 // ----------------------------------------------------------------------------
       
   421 QString CustomDataSynchConfigValidatorEngine::model() const
       
   422 {
       
   423     QScopedPointer<CDeviceInfo> deviceInfo(CDeviceInfo::NewL());
       
   424     TBuf<CTelephony::KPhoneModelIdSize> model(deviceInfo->model());
       
   425     return QString::fromUtf16(model.Ptr(), model.Length());
       
   426 }
       
   427 
       
   428 // ----------------------------------------------------------------------------
       
   429 QString CustomDataSynchConfigValidatorEngine::manufacturer() const
       
   430 {
       
   431     QScopedPointer<CDeviceInfo> deviceInfo(CDeviceInfo::NewL());
       
   432     TBuf<CTelephony::KPhoneModelIdSize> manufacturer(deviceInfo->manufacturer());
       
   433     return QString::fromUtf16(manufacturer.Ptr(), manufacturer.Length());
       
   434 }
       
   435 
       
   436 // ----------------------------------------------------------------------------
       
   437 QString CustomDataSynchConfigValidatorEngine::imsi() const
       
   438 {
       
   439     QScopedPointer<CDeviceInfo> deviceInfo(CDeviceInfo::NewL());
       
   440     TBuf<CTelephony::KIMSISize> imsi(deviceInfo->imsi());
       
   441     return QString::fromUtf16(imsi.Ptr(), imsi.Length());
       
   442 }
       
   443 
       
   444 // ----------------------------------------------------------------------------
       
   445 QString CustomDataSynchConfigValidatorEngine::softwareVersion() const
       
   446 {
       
   447     QString version;
       
   448     TBuf<KSysUtilVersionTextLength> versionBuf;
       
   449     if (SysUtil::GetSWVersion(versionBuf) == KErrNone) {
       
   450         version = QString::fromUtf16(versionBuf.Ptr(), versionBuf.Length());
       
   451     }
       
   452     return version;
       
   453 }
       
   454 
       
   455 // ----------------------------------------------------------------------------
       
   456 // CleanupEComArray function is used for cleanup support of locally declared arrays
       
   457 void CleanupEComArray(TAny* aArray)
       
   458 {
       
   459     (static_cast<RImplInfoPtrArray*> (aArray))->ResetAndDestroy();
       
   460     (static_cast<RImplInfoPtrArray*> (aArray))->Close();
       
   461 }
       
   462 
       
   463 // End of file