bluetoothmgmt/btmgr/BTManServer/btmanserverburmgr.cpp
branchRCL_3
changeset 11 20fda83a6398
child 14 f8503e232b0c
equal deleted inserted replaced
10:8a27654f7b62 11:20fda83a6398
       
     1 // Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // Implements backup and restore support for the Bluetooth Manager server.
       
    15 //
       
    16 
       
    17 #include <e32std.h>
       
    18 #include <e32base.h>
       
    19 #include <e32property.h>
       
    20 #include <f32file.h>
       
    21 #include <s32file.h>
       
    22 #include "btmanserverutil.h"
       
    23 #include "btmanserverburmgr.h"
       
    24 #include "BTManServer.h"
       
    25 
       
    26 #include "btmanclient.h"
       
    27 #include "btdevice.h"
       
    28 #include <bluetooth/hci/hcitypes.h>
       
    29 #include <bluetooth/logger.h>
       
    30 #include "BTSec.h"
       
    31 
       
    32 #ifdef __FLOG_ACTIVE
       
    33 _LIT8(KLogComponent, LOG_COMPONENT_BT_MANAGER_SERVER);
       
    34 #endif
       
    35 
       
    36 
       
    37 /**
       
    38 Raises an EBTBURMgrInvalidState panic with state information encoded within the panic code.
       
    39 The first digit denotes the panic code (EBTBURMgrInvalidState).
       
    40 The second digit is a delimiter and is always 1.
       
    41 The next two digits represent the expected state
       
    42 The next digit again is a delimiter and is always 1.
       
    43 The final two digits represent the actual state. 
       
    44 
       
    45 For example, the panic code 7101100 indicates an EBTBURMgrInvalidState panic raised because the state
       
    46 machine is in the EBTBURStateNormal state when it was expected to be in the EBTBURStateBackupRequest state.
       
    47 **/
       
    48 void InvalidStatePanic(TBTBURState aExpectedState, TBTBURState aActualState)
       
    49 	{
       
    50 	LOG_STATIC_FUNC
       
    51 	User::Panic(KBTBackupPanicCat, (EBTBURMgrInvalidState*KBTBackupStatePanicMultiplier) + KBTBackupStatePanicMajorDelimiter + (aExpectedState * KBTBackupStateMultiplier) + KBTBackupStatePanicMinorDelimiter + aActualState);
       
    52 	}
       
    53 
       
    54 /**
       
    55 Raises an EBTBURMgrInvalidStateTransition panic with state information encoded within the panic code.
       
    56 The first digit denotes the panic code (EBTBURMgrInvalidStateTransition).
       
    57 The second digit is a delimiter and is always 1.
       
    58 The next two digits represent the expected state
       
    59 The next digit again is a delimiter and is always 1.
       
    60 The final two digits represent the actual state. 
       
    61 
       
    62 For example, the panic code 6101100 indicates an EBTBURMgrInvalidStateTransition panic raised because the state
       
    63 machine is in the EBTBURStateNormal state when it was expected to be in the EBTBURStateBackupRequest state.
       
    64 **/
       
    65 void InvalidStateTransitionPanic(TBTBURState aCurrentState, TBTBUREvent aEvent)
       
    66 	{
       
    67 	LOG_STATIC_FUNC
       
    68 	User::Panic(KBTBackupPanicCat, (EBTBURMgrInvalidStateTransition*KBTBackupStatePanicMultiplier) + KBTBackupStatePanicMajorDelimiter + (aCurrentState * KBTBackupStateMultiplier) + KBTBackupStatePanicMinorDelimiter + aEvent);
       
    69 	}
       
    70 
       
    71 
       
    72 /**
       
    73 CBTManServerBURMgr - Manages backup and restore support for the Bluetooth Manager server.
       
    74 **/
       
    75 
       
    76 /**
       
    77 Constructs a new instance of a CBTManServerBURMgr.
       
    78 An MBTBURNotify instance may be registered here for notifications. Ownership of the MBTBURNotify instance is not transferred.
       
    79 @see CBTManServerBURMgr::RequestBURNotification()
       
    80 **/
       
    81 CBTManServerBURMgr* CBTManServerBURMgr::NewL(CBTManServer& aBTManServer, MBTBURNotify* aBURNotify, TInt aPriority)
       
    82 	{
       
    83 	LOG_STATIC_FUNC
       
    84 	CBTManServerBURMgr* self = new(ELeave) CBTManServerBURMgr(aBTManServer, aBURNotify, aPriority);
       
    85 	CleanupStack::PushL(self);
       
    86 	self->ConstructL();
       
    87 	CleanupStack::Pop(self);
       
    88 	return self;
       
    89 	}
       
    90 
       
    91 CBTManServerBURMgr::CBTManServerBURMgr(CBTManServer& aBTManServer, MBTBURNotify* aBURNotify, TInt aPriority) 
       
    92 	: CActive(aPriority), 
       
    93 	iBTManServer(aBTManServer),  
       
    94 	iBUROperationStartNotified(EFalse)
       
    95 	{
       
    96 	LOG_FUNC
       
    97 
       
    98 	RequestBURNotification(aBURNotify);
       
    99 	CActiveScheduler::Add(this);
       
   100 	}
       
   101 
       
   102 CBTManServerBURMgr::~CBTManServerBURMgr()
       
   103 	{
       
   104 	LOG_FUNC
       
   105 
       
   106 	Cancel();
       
   107 	iProperty.Close();
       
   108 
       
   109 	// Close any open session on BT Manager
       
   110 	NotifyAnyBUROperationStopped();
       
   111 		
       
   112 	// Members which either hold data or are NULL
       
   113 	delete iActiveBackupClient;
       
   114 	delete iActiveBackupDataClient;
       
   115 	delete iBackupHandler;
       
   116 	delete iRestoreHandler;
       
   117 	delete iLocalAddrFetcher;
       
   118 
       
   119 	// Member that is instantiated for entire lifetime of CBTManServerBURMgr
       
   120 	delete iStateMachine;
       
   121 	}
       
   122 
       
   123 void CBTManServerBURMgr::ConstructL()
       
   124 	{
       
   125 	LOG_FUNC
       
   126 
       
   127 	// Construct state machine
       
   128 	iStateMachine = CBTManServerBURMgrStateFactory::NewL(*this);
       
   129 	// Construction counts as a transition into the default state (EBTBURStateNormal) of the state machine.
       
   130 	// However, since this does nothing if no backup/restore cleanup is required, we do not need to execute the 
       
   131 	// state action.
       
   132 	
       
   133 	// Setup iProperty to catch BUR flag from Secure Backup Engine
       
   134 	LEAVEIFERRORL(iProperty.Attach(KUidSystemCategory, KUidBackupRestoreKey));
       
   135 
       
   136 	// Subscribe to BUR P&S key to catch transitions
       
   137 	SubscribeToBackupRestoreKey();
       
   138 
       
   139 	// Also check flag now (it may have already transitioned)
       
   140 	TInt backupKeyValue = 0;
       
   141 	LEAVEIFERRORL(iProperty.Get(backupKeyValue));
       
   142 	TBURPartType backupState = GetBURPartType(backupKeyValue);	
       
   143 
       
   144 	// If we're not about to perform a restore, check if a restore file exists. If so, try to process restore file.
       
   145 	// The restore operation may not affect us, or may be postponed. In either case, we try to process the restore file
       
   146 	// again next time we start.
       
   147 	if (backupState != EBURRestoreFull && backupState != EBURRestorePartial)
       
   148 		{
       
   149 		// Delete any stale backup files
       
   150 		DeleteBackupFile();
       
   151 		// See if a restore file needs processing
       
   152 		CheckForRestoreFileL();
       
   153 		}
       
   154 
       
   155 	// Process flag
       
   156 	ProcessBackupState(backupState);
       
   157 	}
       
   158 
       
   159 /**
       
   160 Translates a given integer obtained from the KUidBackupRestoreKey P&S key to a TBURPartType value.
       
   161 This will validate the masked value to ensure that it falls within the range of the TBURPartType enum.
       
   162 In debug builds, a panic will be raised if this value is out of range.
       
   163 In release builds, EBURUnset is returned if the value is out of range.
       
   164 **/
       
   165 TBURPartType CBTManServerBURMgr::GetBURPartType(TInt aValue)
       
   166 	{
       
   167 	LOG_FUNC
       
   168 
       
   169 	switch (aValue & KBURPartTypeMask)
       
   170 		{
       
   171 	case EBURUnset:
       
   172 		return EBURUnset;
       
   173 	case EBURNormal:
       
   174 		return EBURNormal;
       
   175 	case EBURBackupFull:
       
   176 		return EBURBackupFull;
       
   177 	case EBURBackupPartial:
       
   178 		return EBURBackupPartial;
       
   179 	case EBURRestoreFull:
       
   180 		return EBURRestoreFull;
       
   181 	case EBURRestorePartial:
       
   182 		return EBURRestorePartial;
       
   183 	default:
       
   184 		__ASSERT_DEBUG(EFalse, PANIC(KBTBackupPanicCat, EBTBURMgrInvalidBackupRestoreState));
       
   185 		return EBURUnset;
       
   186 		}
       
   187 	}
       
   188 
       
   189 /**
       
   190 Attempts to locate a restore file in the private directory of this server.
       
   191 @return ETrue if the file can be found, EFalse otherwise.
       
   192 **/
       
   193 TBool CBTManServerBURMgr::RestoreFilePresent()
       
   194 	{
       
   195 	LOG_FUNC
       
   196 
       
   197 	RFs fsSession;
       
   198 	TInt err = fsSession.Connect();
       
   199 	if (err == KErrNone)
       
   200 		{
       
   201 		err = fsSession.SetSessionToPrivate(fsSession.GetSystemDrive());
       
   202 		if (err ==KErrNone)
       
   203 			{
       
   204 			TEntry entry;
       
   205 			err = fsSession.Entry(KBTManServerRestoreFileName, entry);
       
   206 			}
       
   207 
       
   208 		fsSession.Close();
       
   209 		}
       
   210 
       
   211 	// If restore file was found, err will be KErrNone
       
   212 	return (err == KErrNone);
       
   213 	}
       
   214 
       
   215 /**
       
   216 Checks for the existence of a restore file. If a restore file is found, then the local device address
       
   217 is feteched and processing of that restore file is initiated.
       
   218 **/
       
   219 void CBTManServerBURMgr::CheckForRestoreFileL()
       
   220 	{
       
   221 	LOG_FUNC
       
   222 
       
   223 	if (RestoreFilePresent())
       
   224 		{
       
   225 		// Fetch local address. When this is received, restore file processing will begin.
       
   226 		iLocalAddrFetcher = CBTLocalAddressFetcher::NewL(*this, iBTManServer.Registry());
       
   227 		iLocalAddrFetcher->FetchLocalAddress();
       
   228 		}
       
   229 	}
       
   230 
       
   231 /**
       
   232 Subscribes to the P&S flag provided by the Secure Backup Engine (to receive notification of backup/restore state changes).
       
   233 **/
       
   234 void CBTManServerBURMgr::SubscribeToBackupRestoreKey()
       
   235 	{
       
   236 	LOG_FUNC
       
   237 
       
   238 	iProperty.Subscribe(iStatus);
       
   239 	SetActive();	
       
   240 	}
       
   241 
       
   242 /**
       
   243 Processes a change in the backup/restore state of the device. 
       
   244 @param aBackupStateValue A value expressing the backup/restore state of the device. 
       
   245 **/
       
   246 void CBTManServerBURMgr::ProcessBackupState(TBURPartType aBURStateValue)
       
   247 	{
       
   248 	LOG_FUNC
       
   249 
       
   250 	iBURState = aBURStateValue;
       
   251 
       
   252 	switch (aBURStateValue)
       
   253 		{
       
   254 	case EBURBackupFull:
       
   255 		// Fall-through
       
   256 	case EBURBackupPartial:
       
   257 		iStateMachine->TransitionState(EBTBUREventBackup);
       
   258 		break;
       
   259 	case EBURRestoreFull:
       
   260 		// Fall-through
       
   261 	case EBURRestorePartial:
       
   262 		iStateMachine->TransitionState(EBTBUREventRestore);
       
   263 		break;
       
   264 	case EBURNormal:
       
   265 		iStateMachine->TransitionState(EBTBUREventNormal);
       
   266 		break;
       
   267 	default:	// EBURUnset
       
   268 		__ASSERT_DEBUG(aBURStateValue == EBURUnset, PANIC(KBTBackupPanicCat, EBTBURMgrUnknownBUREvent));
       
   269 		iStateMachine->TransitionState(EBTBUREventUnset);
       
   270 		}
       
   271 	}
       
   272 
       
   273 /**
       
   274 Registers an MBTBURNotify instance to receive notification of backup/restore operations starting and stopping.
       
   275 Ownership of this MBTBURNotify instance is not transferred.
       
   276 Any previous MBTBURNotify instance is deregistered on this method call.
       
   277 Supplying a NULL pointer will deregister the previously registered instance (if present).
       
   278 **/
       
   279 void CBTManServerBURMgr::RequestBURNotification(MBTBURNotify* aBURNotify)
       
   280 	{
       
   281 	LOG_FUNC
       
   282 
       
   283 	iBURNotify = aBURNotify;
       
   284 	}
       
   285 
       
   286 
       
   287 /**
       
   288 Receives a local address from a CBTLocalAddressFetcher instance.
       
   289 This will trigger processing of a pending restore file.
       
   290 **/
       
   291 void CBTManServerBURMgr::SetLocalAddress(TBTDevAddr& aLocalAddr)
       
   292 	{
       
   293 	LOG_FUNC
       
   294 	__ASSERT_DEBUG(aLocalAddr != TBTDevAddr(), PANIC(KBTBackupPanicCat, EBTBURMgrMissingLocalAddress));
       
   295 
       
   296 	// Use address only if it is non-zero.
       
   297 	if (aLocalAddr != TBTDevAddr())
       
   298 		{
       
   299 		// Take a copy
       
   300 		iLocalAddr = aLocalAddr;
       
   301 		// Attempt to start restore file processing.
       
   302 		// Note that this will fail if we are not in the normal state.
       
   303 		iStateMachine->TransitionState(EBTBUREventProcessRestoreFile);
       
   304 		}
       
   305 	}
       
   306 
       
   307 /**
       
   308 Receives notification that a restore file has been provided by the Secure Backup Engine.
       
   309 Upon receiving this notification, the restore file is renamed to have the appropriate extension and 
       
   310 the local device name is updated in the registry. The restore of the remote devices table is postponed
       
   311 until the next time BTManServer starts, so any ongoing BT connections are not affected.
       
   312 **/
       
   313 void CBTManServerBURMgr::RestoreFileReady()
       
   314 	{
       
   315 	LOG_FUNC
       
   316 	__ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateRestoreOngoing, InvalidStatePanic(EBTBURStateRestoreOngoing, iStateMachine->GetCurrentState()));
       
   317 
       
   318 	// Rename restore file
       
   319 	RenameBackupFileForRestore();
       
   320 	// Attempt to update local device name in the registry (best efforts only)
       
   321 	TRAP_IGNORE(UpdateLocalDeviceNameL());
       
   322 	}
       
   323 
       
   324 void CBTManServerBURMgr::HandleStateNormal()
       
   325 	{
       
   326 	LOG_FUNC
       
   327 	__ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateNormal, InvalidStatePanic(EBTBURStateNormal, iStateMachine->GetCurrentState()));
       
   328 
       
   329 	if (iActiveBackupClient)
       
   330 		{
       
   331 		// Backup or restore finished
       
   332 		if (iBackupHandler)
       
   333 			{
       
   334 			// Backup operation finished
       
   335 			// Delete backup file and destroy backup handler
       
   336 			DeleteBackupFile();
       
   337 			delete iBackupHandler;
       
   338 			iBackupHandler = NULL;
       
   339 			}
       
   340 		else
       
   341 			{
       
   342 			// Restore operation finished
       
   343 			delete iActiveBackupDataClient;
       
   344 			iActiveBackupDataClient = NULL;
       
   345 			}
       
   346 
       
   347 		// Destroy active backup client
       
   348 		delete iActiveBackupClient;
       
   349 		iActiveBackupClient = NULL;
       
   350 
       
   351 		// Notify that backup/restore operation has finished
       
   352 		NotifyBUROperationStopped();
       
   353 		}
       
   354 	}
       
   355 
       
   356 /**
       
   357 Determines if a BUR operation affects the Bluetooth Manager server.
       
   358 @return ETrue if a full backup or restore is ongoing, otherwise the return value
       
   359 given by CActiveBackupClient::DoesPartialBURAffectMeL()
       
   360 **/
       
   361 TBool CBTManServerBURMgr::DoesBURAffectMeL(CActiveBackupClient& aClient)
       
   362 	{
       
   363 	LOG_FUNC
       
   364 
       
   365 	if (iBURState == EBURBackupFull || iBURState == EBURRestoreFull)
       
   366 		{
       
   367 		return ETrue;
       
   368 		}
       
   369 	else
       
   370 		{
       
   371 		return aClient.DoesPartialBURAffectMeL();
       
   372 		}
       
   373 	}
       
   374 
       
   375 void CBTManServerBURMgr::HandleStateBackupRequestL()
       
   376 	{
       
   377 	LOG_FUNC
       
   378 	__ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateBackupRequest, InvalidStatePanic(EBTBURStateBackupRequest, iStateMachine->GetCurrentState()));
       
   379 
       
   380 	// Determine if this backup operation affects us and transition to next state based on this outcome.
       
   381 	iActiveBackupClient = CActiveBackupClient::NewL();
       
   382 
       
   383 	if (DoesBURAffectMeL(*iActiveBackupClient))
       
   384 		{
       
   385 		// We're affected, proceed with backup
       
   386 		iStateMachine->TransitionState(EBTBUREventBackupProceed);
       
   387 		}
       
   388 	else
       
   389 		{
       
   390 		// We're not effected, don't do any backup handling
       
   391 		iStateMachine->TransitionState(EBTBUREventBackupReject);
       
   392 		}
       
   393 	}
       
   394 
       
   395 void CBTManServerBURMgr::HandleStateBackupRequestError()
       
   396 	{
       
   397 	LOG_FUNC
       
   398 	__ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateBackupRequest, InvalidStatePanic(EBTBURStateBackupRequest, iStateMachine->GetCurrentState()));
       
   399 
       
   400 	// Transition to normal state
       
   401 	iStateMachine->TransitionState(EBTBUREventAbortStateAction);
       
   402 	}
       
   403 
       
   404 void CBTManServerBURMgr::HandleStateBackupOngoingL()
       
   405 	{
       
   406 	LOG_FUNC
       
   407 	__ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateBackupOngoing, InvalidStatePanic(EBTBURStateBackupOngoing, iStateMachine->GetCurrentState()));
       
   408 	__ASSERT_DEBUG(iActiveBackupClient, PANIC(KBTBackupPanicCat, EBTBURMgrActiveBackupClientNull));
       
   409 
       
   410 	// Provide notification that a BUR operation has started.
       
   411 	NotifyBUROperationStarted();
       
   412 
       
   413 	// Construct backup handler and prepare for backup
       
   414 	iBackupHandler = CBTBackupHandler::NewL(*this, iBTManServer.Registry());
       
   415 	iBackupHandler->CreateBackupFileL();
       
   416 
       
   417 	// Signal that we're ready for (passive) backup of prepared file
       
   418 	iActiveBackupClient->ConfirmReadyForBURL(KErrNone);
       
   419 
       
   420 	// Next state transition will be invoked when BUR P&S key changes
       
   421 	}
       
   422 
       
   423 void CBTManServerBURMgr::HandleStateBackupOngoingError()
       
   424 	{
       
   425 	LOG_FUNC
       
   426 	__ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateBackupOngoing, InvalidStatePanic(EBTBURStateBackupOngoing, iStateMachine->GetCurrentState()));
       
   427 
       
   428 	// Transition to normal state
       
   429 	iStateMachine->TransitionState(EBTBUREventAbortStateAction);
       
   430 	}
       
   431 
       
   432 void CBTManServerBURMgr::HandleStateBackupIgnore()
       
   433 	{
       
   434 	LOG_FUNC
       
   435 	__ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateBackupIgnore, InvalidStatePanic(EBTBURStateBackupIgnore, iStateMachine->GetCurrentState()));
       
   436 
       
   437 	// Destroy active backup client
       
   438 	delete iActiveBackupClient;
       
   439 	iActiveBackupClient = NULL;
       
   440 
       
   441 	// Next state transition will be invoked when BUR P&S key changes
       
   442 	}
       
   443 
       
   444 void CBTManServerBURMgr::HandleStateRestoreRequestL()
       
   445 	{
       
   446 	LOG_FUNC
       
   447 	__ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateRestoreRequest, InvalidStatePanic(EBTBURStateRestoreRequest, iStateMachine->GetCurrentState()));
       
   448 
       
   449 	// We do want a callback here. Even though the actual restore operation has been handled passively, we
       
   450 	// still need notificaton that the passive restore has completed (so we can then deal with the file).
       
   451 	iActiveBackupDataClient = CBTActiveBackupDataClient::NewL(*this);
       
   452 	iActiveBackupClient = CActiveBackupClient::NewL(iActiveBackupDataClient);
       
   453 
       
   454 	// Determine if this restore operation affects us and transition to next state based on this outcome
       
   455 	if (DoesBURAffectMeL(*iActiveBackupClient))
       
   456 		{
       
   457 		// We're affected, proceed with restore
       
   458 		iStateMachine->TransitionState(EBTBUREventRestoreProceed);
       
   459 		}
       
   460 	else
       
   461 		{
       
   462 		// We're not effected, don't do any restore handling
       
   463 		iStateMachine->TransitionState(EBTBUREventRestoreReject);
       
   464 		}
       
   465 	}
       
   466 
       
   467 void CBTManServerBURMgr::HandleStateRestoreRequestError()
       
   468 	{
       
   469 	LOG_FUNC
       
   470 	__ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateRestoreRequest, InvalidStatePanic(EBTBURStateRestoreRequest, iStateMachine->GetCurrentState()));
       
   471 	
       
   472 	// Transition to normal state
       
   473 	iStateMachine->TransitionState(EBTBUREventAbortStateAction);
       
   474 	}
       
   475 
       
   476 void CBTManServerBURMgr::HandleStateRestoreOngoingL()
       
   477 	{
       
   478 	LOG_FUNC
       
   479 	__ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateRestoreOngoing, InvalidStatePanic(EBTBURStateRestoreOngoing, iStateMachine->GetCurrentState()));
       
   480 
       
   481 	// Cancel any local address requests
       
   482 	if (iLocalAddrFetcher)
       
   483 		{
       
   484 		iLocalAddrFetcher->Cancel();
       
   485 		}
       
   486 
       
   487 	// Provide notification that a BUR operation has started.
       
   488 	NotifyBUROperationStarted();
       
   489 
       
   490 	// Signal that we're ready for active restore of prepared file
       
   491 	// (note that no data is actively restored, but we still need to invoke this method)
       
   492 	iActiveBackupClient->ConfirmReadyForBURL(KErrNone);
       
   493 
       
   494 	// Next state transition will be invoked when BUR P&S key changes
       
   495 	}
       
   496 
       
   497 void CBTManServerBURMgr::HandleStateRestoreOngoingError()
       
   498 	{
       
   499 	LOG_FUNC
       
   500 	__ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateRestoreOngoing, InvalidStatePanic(EBTBURStateRestoreOngoing, iStateMachine->GetCurrentState()));
       
   501 
       
   502 	// Transition to normal state
       
   503 	iStateMachine->TransitionState(EBTBUREventAbortStateAction);
       
   504 	}
       
   505 
       
   506 void CBTManServerBURMgr::HandleStateRestoreIgnore()
       
   507 	{
       
   508 	LOG_FUNC
       
   509 	__ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateRestoreIgnore, InvalidStatePanic(EBTBURStateRestoreIgnore, iStateMachine->GetCurrentState()));
       
   510 
       
   511 	// Destroy active backup client
       
   512 	delete iActiveBackupClient;
       
   513 	delete iActiveBackupDataClient;
       
   514 	iActiveBackupClient = NULL;
       
   515 	iActiveBackupDataClient = NULL;
       
   516 
       
   517 	// Next state transition will be invoked when BUR P&S key changes
       
   518 	}
       
   519 
       
   520 void CBTManServerBURMgr::HandleStateProcessRestoreFileL()
       
   521 	{
       
   522 	LOG_FUNC
       
   523 	__ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateProcessRestoreFile, InvalidStatePanic(EBTBURStateProcessRestoreFile, iStateMachine->GetCurrentState()));
       
   524 
       
   525 	// Start restore file processing
       
   526 	iRestoreHandler = CBTRestoreHandler::NewL(*this, iBTManServer);
       
   527 	iRestoreHandler->RestoreRemoteDeviceTableL(iLocalAddr);
       
   528 
       
   529 	iStateMachine->TransitionState(EBTBUREventProcessRestoreFileComplete);
       
   530 	}
       
   531 
       
   532 void CBTManServerBURMgr::HandleStateProcessRestoreFileError(TInt aError)
       
   533 	{
       
   534 	LOG_FUNC
       
   535 	__ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateProcessRestoreFile, InvalidStatePanic(EBTBURStateProcessRestoreFile, iStateMachine->GetCurrentState()));
       
   536 
       
   537 	// Delete restore handler
       
   538 	delete iRestoreHandler;
       
   539 	iRestoreHandler = NULL;
       
   540 	
       
   541 	// If aError is anything other than KErrNoMemory, then delete restore file.
       
   542 	// OOM errors may be temporary, and a subsequent restore attempt may succeed.
       
   543 	if (aError != KErrNoMemory)
       
   544 		{
       
   545 		DeleteRestoreFile();
       
   546 		}
       
   547 
       
   548 	// Transition to normal state
       
   549 	iStateMachine->TransitionState(EBTBUREventAbortStateAction);
       
   550 	}
       
   551 
       
   552 void CBTManServerBURMgr::HandleStateRestoreFileProcessingComplete()
       
   553 	{
       
   554 	LOG_FUNC
       
   555 	__ASSERT_DEBUG(iStateMachine->GetCurrentState() == EBTBURStateRestoreFileProcessingComplete, InvalidStatePanic(EBTBURStateRestoreFileProcessingComplete, iStateMachine->GetCurrentState()));
       
   556 	
       
   557 	// Delete restore file (we're now done with it)
       
   558 	DeleteRestoreFile();
       
   559 
       
   560 	// Delete restore handler
       
   561 	delete iRestoreHandler;
       
   562 	iRestoreHandler = NULL;
       
   563 
       
   564 	iStateMachine->TransitionState(EBTBUREventRestoreFileTransitionNormal);
       
   565 	}
       
   566 
       
   567 /**
       
   568 Sends notification to a registered MBTBURNotify instance that a backup or restore operation has started.
       
   569 @see CBTManServerBURMgr::RequestBURNotification()
       
   570 **/
       
   571 void CBTManServerBURMgr::NotifyBUROperationStarted()
       
   572 	{
       
   573 	LOG_FUNC
       
   574 	__ASSERT_DEBUG(!iBUROperationStartNotified, PANIC(KBTBackupPanicCat, EBTBURMgrBUROperationStartAlreadyNotified));
       
   575 	
       
   576 	if (!iBUROperationStartNotified)
       
   577 		{
       
   578 		iBUROperationStartNotified = ETrue;
       
   579 
       
   580 		if (iBURNotify)
       
   581 			{
       
   582 			iBURNotify->BUROperationStarted();
       
   583 			}
       
   584 		}
       
   585 	}
       
   586 
       
   587 /**
       
   588 Sends notification to the MBTBURNotify instance that a backup or restore operation has started. 
       
   589 This should correspond to a call to NotifyBUROperationStarted().
       
   590 @see CBTManServerBURMgr::RequestBURNotification()
       
   591 **/
       
   592 void CBTManServerBURMgr::NotifyBUROperationStopped()
       
   593 	{
       
   594 	LOG_FUNC
       
   595 	__ASSERT_DEBUG(iBUROperationStartNotified, PANIC(KBTBackupPanicCat, EBTBURMgrBUROperationStartNotNotified));
       
   596 	
       
   597 	if (iBUROperationStartNotified)
       
   598 		{
       
   599 		iBUROperationStartNotified = EFalse;
       
   600 
       
   601 		if (iBURNotify)
       
   602 			{
       
   603 			iBURNotify->BUROperationStopped();
       
   604 			}
       
   605 		}
       
   606 	}
       
   607 
       
   608 /**
       
   609 Sends notification to the MBTBURNotify instance that a backup or restore operation has started. 
       
   610 This will send notification only if NotifyBUROperationStarted() has been called without a corresponding 
       
   611 call to NotifyBUROperationStopped().
       
   612 This is intended for use in error situations only.
       
   613 **/
       
   614 void CBTManServerBURMgr::NotifyAnyBUROperationStopped()
       
   615 	{
       
   616 	LOG_FUNC
       
   617 
       
   618 	// We deliberately want to fail silently here if no stop notification is expected.
       
   619 	if (iBUROperationStartNotified)
       
   620 		{
       
   621 		iBUROperationStartNotified = EFalse;
       
   622 
       
   623 		if (iBURNotify)
       
   624 			{
       
   625 			iBURNotify->BUROperationStopped();
       
   626 			}
       
   627 		}
       
   628 	}
       
   629 
       
   630 /**
       
   631 Utility function to delete a named file from the private directory of this process on the system drive.
       
   632 This is a best-efforts attempt which fails silently on error.
       
   633 @param aFileName The name of the file to delete.
       
   634 **/
       
   635 void CBTManServerBURMgr::DeleteFile(const TDesC& aFileName)
       
   636 	{
       
   637 	LOG_FUNC
       
   638 
       
   639 	RFs fsSession;
       
   640 	// Attempt to delete file
       
   641 	// This is best-efforts, failing silently on any error (as there is no remedy action that we can take).
       
   642 	if (fsSession.Connect() == KErrNone)
       
   643 		{
       
   644 		if (fsSession.SetSessionToPrivate(fsSession.GetSystemDrive()) == KErrNone)
       
   645 			{
       
   646 			// Try to ensure read-only and system attributes are not set
       
   647 			TUint attrs;
       
   648 			TInt err = fsSession.Att(aFileName, attrs);
       
   649 			if (err == KErrNone)
       
   650 				{
       
   651 				// Unset the files read-only and system attributes if these are set.
       
   652 				TUint unsetAttrs = (attrs & KEntryAttReadOnly) | (attrs & KEntryAttSystem);
       
   653 				if (unsetAttrs != KEntryAttNormal)
       
   654 					{
       
   655 					err = fsSession.SetAtt(aFileName, KEntryAttNormal, unsetAttrs);
       
   656 					}
       
   657 
       
   658 				// Attempt to delete the file, if we've managed to successfully retrieve and reset the file attributes. 
       
   659 				// Note that this is best-efforts.
       
   660 				if (err == KErrNone)
       
   661 					{
       
   662 					static_cast<void>(fsSession.Delete(aFileName));
       
   663 					}
       
   664 				}
       
   665 			}
       
   666 
       
   667 		fsSession.Close();
       
   668 		}
       
   669 	}	
       
   670 
       
   671 /**
       
   672 Deletes the backup file (with name KBTManServerBackupFileName) from the private directory of this process on the system drive.
       
   673 This is a best-efforts attempt which fails silently on error.
       
   674 **/
       
   675 void CBTManServerBURMgr::DeleteBackupFile()
       
   676 	{
       
   677 	LOG_FUNC
       
   678 
       
   679 	DeleteFile(KBTManServerBackupFileName);
       
   680 	}
       
   681 
       
   682 /**
       
   683 Deletes the restore file (with name KBTManServerRestoreFileName) from the private directory of this process on the system drive.
       
   684 This is a best-efforts attempt which fails silently on error.
       
   685 **/
       
   686 void CBTManServerBURMgr::DeleteRestoreFile()
       
   687 	{
       
   688 	LOG_FUNC
       
   689 
       
   690 	DeleteFile(KBTManServerRestoreFileName);
       
   691 	}
       
   692 
       
   693 /**
       
   694 Renames a restored backup file from KBTManServerBackupFileName to KBTManServerRestoreFileName.
       
   695 This facilitates processing of the restore file when the Bluetooth Manager server next starts.
       
   696 This is a best-efforts attempt, as no remedial action can be taken if this operation fails.
       
   697 **/
       
   698 void CBTManServerBURMgr::RenameBackupFileForRestore()
       
   699 	{
       
   700 	LOG_FUNC
       
   701 
       
   702 	// Delete any previous restore file
       
   703 	DeleteRestoreFile();
       
   704 	
       
   705 	RFs fsSession;
       
   706 	if (fsSession.Connect() == KErrNone)
       
   707 		{
       
   708 		static_cast<void>(fsSession.Rename(KBTManServerBackupFileName, KBTManServerRestoreFileName));
       
   709 		fsSession.Close();
       
   710 		}
       
   711 	}
       
   712 
       
   713 /**
       
   714 Parses the restore file and updates the loal device name in the registry.
       
   715 This update takes place as soon as the restore file is available, regardless of whether or not the local device
       
   716 address matches that held in the registry. If the local device name has already been set to a non-default value,
       
   717 then it is not modified.
       
   718 **/
       
   719 void CBTManServerBURMgr::UpdateLocalDeviceNameL()
       
   720 	{
       
   721 	LOG_FUNC
       
   722 		
       
   723 	CBTRestoreHandler* restoreHandler = CBTRestoreHandler::NewL(*this, iBTManServer);
       
   724 	CleanupStack::PushL(restoreHandler);
       
   725 
       
   726 	restoreHandler->RestoreLocalDeviceNameL();
       
   727 
       
   728 	CleanupStack::PopAndDestroy(restoreHandler);
       
   729 	}
       
   730 
       
   731 void CBTManServerBURMgr::RunL()
       
   732 	{
       
   733 	LOG_FUNC
       
   734 	
       
   735 	if (iStatus == KErrNone)
       
   736 		{
       
   737 		// Subscribe to catch the next transition
       
   738 		SubscribeToBackupRestoreKey();
       
   739 
       
   740 		// Handle this event
       
   741 		TInt backupKeyValue = 0;
       
   742 		LEAVEIFERRORL(iProperty.Get(backupKeyValue));
       
   743 		TBURPartType backupState = GetBURPartType(backupKeyValue);
       
   744 
       
   745 		ProcessBackupState(backupState);
       
   746 		}
       
   747 	}
       
   748 
       
   749 TInt CBTManServerBURMgr::RunError(TInt /*aError*/)
       
   750 	{
       
   751 	LOG_FUNC
       
   752 
       
   753 	// Problem occured in obtaining backup key value.
       
   754 	// Ignore the error, as there is nothing we can do.
       
   755 	return KErrNone;
       
   756 	}
       
   757 
       
   758 void CBTManServerBURMgr::DoCancel()
       
   759 	{
       
   760 	LOG_FUNC
       
   761 	
       
   762 	// Cancel our subscription
       
   763 	iProperty.Cancel();
       
   764 	}
       
   765 
       
   766 /**
       
   767  CBTBackupHandler - Handles the task of backing up the BT registry into a backup file ready for passive backup.
       
   768  **/
       
   769 CBTBackupHandler* CBTBackupHandler::NewL(CBTManServerBURMgr& aBURMgr, CBTRegistry& aRegistry)
       
   770 	{
       
   771 	LOG_STATIC_FUNC
       
   772 
       
   773 	CBTBackupHandler* result = new(ELeave) CBTBackupHandler(aBURMgr, aRegistry);
       
   774 	CleanupStack::PushL(result);
       
   775 	result->ConstructL();
       
   776 	CleanupStack::Pop(result);
       
   777 	return result;
       
   778 	}
       
   779 
       
   780 CBTBackupHandler::CBTBackupHandler(CBTManServerBURMgr& aBURMgr, CBTRegistry& aRegistry) 
       
   781 	: iBURMgr(aBURMgr), 
       
   782 	iRegistry(aRegistry)
       
   783 	{
       
   784 	LOG_FUNC
       
   785 	}
       
   786 
       
   787 void CBTBackupHandler::ConstructL()
       
   788 	{
       
   789 	LOG_FUNC
       
   790 
       
   791 	iRegistryData=CBTRegistryBURData::NewL();
       
   792 	}
       
   793 
       
   794 CBTBackupHandler::~CBTBackupHandler()
       
   795 	{
       
   796 	LOG_FUNC
       
   797 
       
   798 	delete iRegistryData;
       
   799 	}
       
   800 
       
   801 void CBTBackupHandler::CreateBackupFileL()
       
   802 	{
       
   803 	LOG_FUNC
       
   804 
       
   805 	// Collect backup registry data
       
   806 	iRegistryData->ReadFromRegistryL(iRegistry);
       
   807 	
       
   808 	// Only continue if the registry is populated (i.e. it may be in its default state, which does not need to be backed up).
       
   809 	// Determine this by examining the local device address stored in the registry. The default registry has this set to 0x0.
       
   810 	if (iRegistryData->IsLocalAddressNonZeroL())
       
   811 		{
       
   812 		// Construct backup file in private directory.
       
   813 		RFs fsSession;
       
   814 		LEAVEIFERRORL(fsSession.Connect());
       
   815 		CleanupClosePushL(fsSession);
       
   816 		LEAVEIFERRORL(fsSession.SetSessionToPrivate(fsSession.GetSystemDrive()));
       
   817 		// Create private path if it does not already exist.
       
   818 		LEAVEIFERRORL(fsSession.CreatePrivatePath(fsSession.GetSystemDrive()));
       
   819 
       
   820 		RFileWriteStream fStream;
       
   821 		// Create backup file, overwriting if necessary (don't care about previous backup files).
       
   822 		LEAVEIFERRORL(fStream.Replace(fsSession, KBTManServerBackupFileName, EFileWrite));
       
   823 		fStream.PushL();
       
   824 			    
       
   825 		// Write out data
       
   826 		iRegistryData->WriteToStreamL(fStream);
       
   827 		fStream.CommitL();
       
   828 
       
   829 		CleanupStack::PopAndDestroy(2, &fsSession);
       
   830 		}
       
   831 	}
       
   832 
       
   833 /**
       
   834  CBTRestoreHandler - Handles the task of restoring the BT registry from a restore file given by passive restore.
       
   835  **/
       
   836 CBTRestoreHandler* CBTRestoreHandler::NewL(CBTManServerBURMgr& aBURMgr, CBTManServer& aManServer)
       
   837 	{
       
   838 	LOG_STATIC_FUNC
       
   839 
       
   840 	CBTRestoreHandler* result = new(ELeave) CBTRestoreHandler(aBURMgr, aManServer);
       
   841 	CleanupStack::PushL(result);
       
   842 	result->ConstructL();
       
   843 	CleanupStack::Pop(result);
       
   844 	return result;
       
   845 	}
       
   846 
       
   847 CBTRestoreHandler::CBTRestoreHandler(CBTManServerBURMgr& aBURMgr, CBTManServer& aManServer) 
       
   848 	: iBURMgr(aBURMgr), 
       
   849 	iManServer(aManServer)
       
   850 	{
       
   851 	LOG_FUNC
       
   852 	}
       
   853 	
       
   854 void CBTRestoreHandler::ConstructL()
       
   855 	{
       
   856 	LOG_FUNC
       
   857 
       
   858 	iRegistryData = CBTRegistryBURData::NewL();
       
   859 	}
       
   860 
       
   861 CBTRestoreHandler::~CBTRestoreHandler()
       
   862 	{
       
   863 	LOG_FUNC
       
   864 
       
   865 	delete iRegistryData;
       
   866 	}
       
   867 
       
   868 void CBTRestoreHandler::RestoreLocalDeviceNameL()
       
   869 	{
       
   870 	LOG_FUNC
       
   871 
       
   872 	LoadRestoreDataL();
       
   873 
       
   874 	// If the local device name is still default, restore without validating the local address
       
   875 	// (otherwise we will not be able to restore this field before the next stack start, which may cause problems with some UIs)
       
   876 	CBTRegistry& registry = iManServer.Registry();
       
   877 	if (iRegistryData->WriteLocalDeviceNameToRegistryL(registry))
       
   878 		{
       
   879 		NotifyLocalTableChange();
       
   880 		}
       
   881 	}
       
   882 
       
   883 void CBTRestoreHandler::RestoreRemoteDeviceTableL(TBTDevAddr& aLocalAddr)
       
   884 	{
       
   885 	LOG_FUNC
       
   886 	__ASSERT_DEBUG(aLocalAddr != TBTDevAddr(), PANIC(KBTBackupPanicCat, EBTBURMgrMissingLocalAddress));
       
   887 
       
   888 	LoadRestoreDataL();
       
   889     
       
   890 	// Compare local address held in restore file with our local address
       
   891 	if (iRegistryData->IsLocalAddressEqualL(aLocalAddr))
       
   892 		{
       
   893     		// Proceed with restore of remote devices table
       
   894 		CBTRegistry& registry = iManServer.Registry();
       
   895 
       
   896 		TInt noRemoteDevices = iRegistryData->CountRemoteDevicesL();
       
   897 		for (TInt i = 0; i < noRemoteDevices; i++)
       
   898 			{
       
   899 			if (iRegistryData->WriteRemoteDeviceToRegistryL(registry, i))
       
   900 				{
       
   901 				NotifyRemoteTableChangeL(iRegistryData->GetRemoteDeviceL(i).BDAddr());
       
   902 				}
       
   903 			}
       
   904 		}
       
   905 	}
       
   906 
       
   907 void CBTRestoreHandler::LoadRestoreDataL()
       
   908 	{
       
   909 	LOG_FUNC
       
   910 
       
   911 	// Read restore file
       
   912 	RFs fsSession;
       
   913 	LEAVEIFERRORL(fsSession.Connect());
       
   914 	CleanupClosePushL(fsSession);
       
   915 	LEAVEIFERRORL(fsSession.SetSessionToPrivate(fsSession.GetSystemDrive()));
       
   916 	// Assuming private directory exists at this point
       
   917 	
       
   918 	RFileReadStream fStream;
       
   919 	LEAVEIFERRORL(fStream.Open(fsSession, KBTManServerRestoreFileName, EFileRead));
       
   920 	fStream.PushL();
       
   921 
       
   922 	// Read in data
       
   923 	iRegistryData->ReadFromStreamL(fStream);
       
   924 
       
   925 	// Cleanup
       
   926 	CleanupStack::PopAndDestroy(2, &fsSession);	//fStream and fsSession
       
   927 	}
       
   928 
       
   929 /**
       
   930 Sends a notification that the persistence table has been changed.
       
   931 The notification is observable through the P&S key KPropertyKeyBluetoothGetRegistryTableChange. 
       
   932 **/
       
   933 void CBTRestoreHandler::NotifyLocalTableChange()
       
   934 	{
       
   935 	LOG_FUNC
       
   936 	
       
   937 	// Notify the P&S key that the remote devices table has changed
       
   938 	iManServer.Publish(KPropertyKeyBluetoothGetRegistryTableChange, KRegistryChangeLocalTable);
       
   939 	}
       
   940 
       
   941 /**
       
   942 Sends a notification that a device in the remote devices table has been changed.
       
   943 The notification is observable through the P&S key KPropertyKeyBluetoothGetRegistryTableChange. 
       
   944 Interested parties can also use RBTRegistry::NotifyViewChange() to detect if the change affects their view.
       
   945 **/
       
   946 void CBTRestoreHandler::NotifyRemoteTableChangeL(const TBTDevAddr& aAddress)
       
   947 	{
       
   948 	LOG_FUNC
       
   949 	
       
   950 	// Construct SQL constraint which selects the device
       
   951 	RBTDbQuery query;
       
   952 	CleanupClosePushL(query);
       
   953 	query.FindDeviceL(aAddress);
       
   954 
       
   955 	HBufC* conDes = query.ConstraintBuf().AllocLC();
       
   956 
       
   957 	// Notify the P&S key that the remote devices table has changed
       
   958 	iManServer.Publish(KPropertyKeyBluetoothGetRegistryTableChange, KRegistryChangeRemoteTable);
       
   959 
       
   960 	// Signal notifiers waiting on view change
       
   961 	iManServer.NotifyViewChange(*conDes);
       
   962 
       
   963 	// Cleanup constDes and query
       
   964 	CleanupStack::PopAndDestroy(2, &query);
       
   965 	}
       
   966 
       
   967 /**
       
   968 CBTRegistryBURData - manages data from the Bluetooth registry that is to be backed up or restored.
       
   969 **/
       
   970 CBTRegistryBURData* CBTRegistryBURData::NewL()
       
   971 	{
       
   972 	LOG_STATIC_FUNC
       
   973 
       
   974 	CBTRegistryBURData* self = new(ELeave) CBTRegistryBURData();
       
   975 	CleanupStack::PushL(self);
       
   976 	self->ConstructL();
       
   977 	CleanupStack::Pop(self);
       
   978 	return self;
       
   979 	}
       
   980 
       
   981 CBTRegistryBURData::CBTRegistryBURData() 
       
   982 	: iHasRegistryData(EFalse)
       
   983 	{
       
   984 	LOG_FUNC
       
   985 	}
       
   986 
       
   987 CBTRegistryBURData::~CBTRegistryBURData()
       
   988 	{
       
   989 	LOG_FUNC
       
   990 
       
   991 	if (iRemoteDevices)	// Dont use ClearRegistryData() here as leave may have occured in ReadFromRegistryL() or ReadFromStreamL()
       
   992 		{
       
   993 		// Destroy all CBTDevices in iRemoteDevices (necessary before array deletion for CArrayPtrFlat)
       
   994 		iRemoteDevices->ResetAndDestroy();
       
   995 		}
       
   996 
       
   997 	delete iLocalDevice;
       
   998 	delete iRemoteDevicesSid;
       
   999 	delete iRemoteDevices;
       
  1000 	}
       
  1001 
       
  1002 void CBTRegistryBURData::ConstructL()
       
  1003 	{
       
  1004 	LOG_FUNC
       
  1005 
       
  1006 	iRemoteDevicesSid = new (ELeave) CArrayFixFlat<TSecureId>(1);
       
  1007 	iRemoteDevices = new(ELeave) CBTDeviceArray(1);
       
  1008 	}
       
  1009 	
       
  1010 /**
       
  1011 Writes the registry data held in this instance to a given stream.
       
  1012 This does not write those registry fields which contain unset values.
       
  1013 @param aStream The stream to write the registry data to.
       
  1014 **/
       
  1015 void CBTRegistryBURData::WriteToStreamL(RWriteStream& aStream) const
       
  1016 	{
       
  1017 	LOG_FUNC
       
  1018 
       
  1019 	// Writes registry data out to a given stream, avoiding any use of class externalisation.
       
  1020 	if (HasRegistryData())
       
  1021 		{
       
  1022 		// This follows a specific file-format (tied to the registry version information), which is documented seperately.
       
  1023 
       
  1024 		// We should already have the following information for the local device.
       
  1025 		__ASSERT_DEBUG(iLocalDevice->IsValidAddress(), PANIC(KBTBackupPanicCat, EBTBURMgrExpectedDataMissing));
       
  1026 
       
  1027 		// Write out version information
       
  1028 		aStream.WriteUint32L(iRegistryVersionMajor);
       
  1029 		aStream.WriteUint32L(iRegistryVersionMinor);
       
  1030 
       
  1031 		// Persistence table:
       
  1032 		// Local device address and name only (both are mandatory).
       
  1033 		aStream.WriteL(iLocalDevice->Address().Des(), KBTDevAddrSize);
       
  1034 
       
  1035 		__ASSERT_DEBUG(iLocalDevice->DeviceName().Length() <= KMaxTUint8, PANIC(KBTBackupPanicCat, EBTBURMgrDescriptorLengthTooLong));
       
  1036 		aStream.WriteUint8L(iLocalDevice->DeviceName().Length());
       
  1037 		aStream.WriteL(iLocalDevice->DeviceName(), iLocalDevice->DeviceName().Length());
       
  1038 
       
  1039 		// Remote devices table
       
  1040 		TInt rdCount=CountRemoteDevicesL();
       
  1041 
       
  1042 		aStream.WriteUint32L(rdCount);
       
  1043 		for (TInt i = 0; i < rdCount; i++)
       
  1044 			{
       
  1045 			const CBTDevice& nextRemDev = GetRemoteDeviceL(i);
       
  1046 			const TBTNamelessDevice& nextRemDevNameless = nextRemDev.AsNamelessDevice();
       
  1047 
       
  1048 			__ASSERT_DEBUG(nextRemDev.IsValidBDAddr(), PANIC(KBTBackupPanicCat, EBTBURMgrExpectedDataMissing));
       
  1049 
       
  1050 			// Work out what is set and derive bitmask (can use TBTDeviceSet here as is public)
       
  1051 			TUint32 rdSetMask = TBTNamelessDevice::EAddress;
       
  1052 			if (nextRemDev.IsValidDeviceClass())
       
  1053 				{
       
  1054 				rdSetMask |= TBTNamelessDevice::EDeviceClass;
       
  1055 				}
       
  1056 			if (nextRemDev.IsValidLinkKey())
       
  1057 				{
       
  1058 				rdSetMask |= TBTNamelessDevice::ELinkKey;
       
  1059 				}
       
  1060 			if (nextRemDev.IsValidGlobalSecurity())
       
  1061 				{
       
  1062 				rdSetMask |= TBTNamelessDevice::EGlobalSecurity;
       
  1063 				}
       
  1064 			if (nextRemDevNameless.IsValidPageScanRepMode())
       
  1065 				{
       
  1066 				rdSetMask |= TBTNamelessDevice::EPageScanRepMode;
       
  1067 				}
       
  1068 			if (nextRemDevNameless.IsValidPageScanMode())
       
  1069 				{
       
  1070 				rdSetMask |= TBTNamelessDevice::EPageScanMode;
       
  1071 				}
       
  1072 			if (nextRemDevNameless.IsValidPageScanPeriodMode())
       
  1073 				{
       
  1074 				rdSetMask |= TBTNamelessDevice::EPageScanPeriodMode;
       
  1075 				}
       
  1076 			if (nextRemDevNameless.IsValidClockOffset())
       
  1077 				{
       
  1078 				rdSetMask |= TBTNamelessDevice::EClockOffset;
       
  1079 				}
       
  1080 			if (nextRemDev.IsValidUsed())
       
  1081 				{
       
  1082 				rdSetMask |= TBTNamelessDevice::EUsed;
       
  1083 				}
       
  1084 			if (nextRemDev.IsValidSeen())
       
  1085 				{
       
  1086 				rdSetMask |= TBTNamelessDevice::ESeen;
       
  1087 				}
       
  1088 			if (nextRemDev.IsValidPassKey())
       
  1089 				{
       
  1090 				rdSetMask |= TBTNamelessDevice::EPassKey;
       
  1091 				}
       
  1092 			if (nextRemDev.IsValidUiCookie())
       
  1093 				{
       
  1094 				rdSetMask |= TBTNamelessDevice::EUiCookie;
       
  1095 				}
       
  1096 			if (nextRemDev.IsValidDeviceName())
       
  1097 				{
       
  1098 				rdSetMask |= CBTDevice::EDeviceName;
       
  1099 				}
       
  1100 			if (nextRemDev.IsValidFriendlyName())
       
  1101 				{
       
  1102 				rdSetMask |= CBTDevice::EFriendlyName;
       
  1103 				}
       
  1104 			// Now write out bitmask
       
  1105 			aStream.WriteUint32L(rdSetMask);
       
  1106 
       
  1107 			// Write valid setting for next remote device
       
  1108 			aStream.WriteUint32L(GetRemoteDeviceEntrySidL(i));
       
  1109 			aStream.WriteL(nextRemDev.BDAddr().Des(), KBTDevAddrSize);
       
  1110 			if (rdSetMask & TBTNamelessDevice::EDeviceClass)
       
  1111 				{
       
  1112 				aStream.WriteUint32L(nextRemDev.DeviceClass().DeviceClass());
       
  1113 				}
       
  1114 			if (rdSetMask & TBTNamelessDevice::ELinkKey)
       
  1115 				{
       
  1116 				const TBTLinkKey& nextRemDevLinkKey = nextRemDev.LinkKey();
       
  1117 				aStream.WriteL(nextRemDevLinkKey, KHCILinkKeySize);
       
  1118 				aStream.WriteUint8L(nextRemDev.LinkKeyType());
       
  1119 				}
       
  1120 			if (rdSetMask & TBTNamelessDevice::EGlobalSecurity)
       
  1121 				{
       
  1122 				TBTDeviceSecurity nextRemDevGlobSec = nextRemDev.GlobalSecurity();
       
  1123 				aStream.WriteUint8L(nextRemDevGlobSec.SecurityValue());
       
  1124 				aStream.WriteUint32L(nextRemDevGlobSec.PasskeyMinLength());
       
  1125 				}
       
  1126 			if (rdSetMask & TBTNamelessDevice::EPageScanRepMode)
       
  1127 				{
       
  1128 				aStream.WriteUint8L(nextRemDevNameless.PageScanRepMode());
       
  1129 				}
       
  1130 			if (rdSetMask & TBTNamelessDevice::EPageScanMode)
       
  1131 				{
       
  1132 				aStream.WriteUint8L(nextRemDevNameless.PageScanMode());
       
  1133 				}
       
  1134 			if (rdSetMask & TBTNamelessDevice::EPageScanPeriodMode)
       
  1135 				{
       
  1136 				aStream.WriteUint8L(nextRemDevNameless.PageScanPeriodMode());
       
  1137 				}
       
  1138 			if (rdSetMask & TBTNamelessDevice::EClockOffset)
       
  1139 				{
       
  1140 				aStream.WriteUint16L(nextRemDevNameless.ClockOffset());
       
  1141 				}
       
  1142 			if (rdSetMask & TBTNamelessDevice::EUsed)
       
  1143 				{
       
  1144 				const TInt64& used = nextRemDev.Used().Int64();
       
  1145 				aStream.WriteInt32L(I64HIGH(used));
       
  1146 				aStream.WriteInt32L(I64LOW(used));
       
  1147 				}
       
  1148 			if (rdSetMask & TBTNamelessDevice::ESeen)
       
  1149 				{
       
  1150 				const TInt64& seen = nextRemDev.Seen().Int64();
       
  1151 				aStream.WriteInt32L(I64HIGH(seen));
       
  1152 				aStream.WriteInt32L(I64LOW(seen));
       
  1153 				}
       
  1154 			if (rdSetMask & TBTNamelessDevice::EPassKey)
       
  1155 				{
       
  1156 				const TBTPinCode& nextRemDevPassKey = nextRemDev.PassKey();
       
  1157 				__ASSERT_DEBUG(nextRemDevPassKey.Length() == KHCIPINCodeSize + 1, PANIC(KBTBackupPanicCat, EBTBURMgrDescriptorUnexpectedLength));
       
  1158 				aStream.WriteL(nextRemDevPassKey, KHCIPINCodeSize + 1);
       
  1159 				}
       
  1160 			if (rdSetMask & TBTNamelessDevice::EUiCookie)
       
  1161 				{
       
  1162 				aStream.WriteUint32L(nextRemDev.UiCookie());
       
  1163 				}
       
  1164 			if (rdSetMask & CBTDevice::EDeviceName)
       
  1165 				{
       
  1166 				__ASSERT_DEBUG(nextRemDev.DeviceName().Length() <= KMaxTUint8, PANIC(KBTBackupPanicCat, EBTBURMgrDescriptorLengthTooLong));
       
  1167 				aStream.WriteUint8L(nextRemDev.DeviceName().Length());
       
  1168 				aStream.WriteL(nextRemDev.DeviceName(), nextRemDev.DeviceName().Length());
       
  1169 				}
       
  1170 			if (rdSetMask & CBTDevice::EFriendlyName)
       
  1171 				{
       
  1172 				__ASSERT_DEBUG(nextRemDev.FriendlyName().Length() <= KMaxTUint8, PANIC(KBTBackupPanicCat, EBTBURMgrDescriptorLengthTooLong));
       
  1173 				aStream.WriteUint8L(nextRemDev.FriendlyName().Length());
       
  1174 				aStream.WriteL(nextRemDev.FriendlyName(), nextRemDev.FriendlyName().Length());
       
  1175 				}
       
  1176 			}
       
  1177 		}
       
  1178 	else
       
  1179 		{
       
  1180 		User::Leave(KErrNotFound);
       
  1181 		}
       
  1182 	}
       
  1183 
       
  1184 /**
       
  1185 Reads registry data from a given stream and stores within this instance.
       
  1186 Any registry data currently held is cleared first.
       
  1187 @param aStream The stream to ready the registry data from.
       
  1188 **/
       
  1189 void CBTRegistryBURData::ReadFromStreamL(RReadStream& aStream)
       
  1190 	{
       
  1191 	LOG_FUNC
       
  1192 
       
  1193 	// This follows a specific file-format (tied to the registry version information), which is documented seperately.
       
  1194 	
       
  1195 	// Note that we dont make *ANY* assumptions as to what data should always be available, since the restore file could be corrupt.
       
  1196 	// We will fail the restore if it turns out we do not have enough information, or if we have invalid information.
       
  1197 	
       
  1198 	// WARNING: When a new registry version is produced, this implementaton of backup/restore support will need modification.
       
  1199 	// This assert should be updated to include all supported registry versions.
       
  1200 	__ASSERT_DEBUG(KRegistryDBVersionMajor == 1 && KRegistryDBVersionMinor == 2, PANIC(KBTBackupPanicCat, EBTBURMgrUnsupportedRegistryVersion));
       
  1201 	
       
  1202 	// Extract version information and continue if we can handle it.
       
  1203 	TUint32 regVersionMajor = aStream.ReadUint32L();
       
  1204 	TUint32 regVersionMinor = aStream.ReadUint32L();
       
  1205 	if (regVersionMajor == KRegistryDBVersionMajor && regVersionMinor == KRegistryDBVersionMinor)
       
  1206 		{
       
  1207 		// We support this version and this version only - read in registry data
       
  1208 		ClearRegistryData();
       
  1209 
       
  1210 		iLocalDevice = new(ELeave) TBTLocalDevice;
       
  1211 		
       
  1212 		// Note version information for this registry
       
  1213 		iRegistryVersionMajor = regVersionMajor;
       
  1214 		iRegistryVersionMinor = regVersionMinor;
       
  1215 
       
  1216 		// Persistence table:
       
  1217 		// Local device address and name only (both fields are mandatory).
       
  1218 		TBTDevAddr address;
       
  1219 		TPtr8 addrPtr(address.Des());
       
  1220 		aStream.ReadL(addrPtr, KBTDevAddrSize);
       
  1221 		if (addrPtr.Length() == KBTDevAddrSize)
       
  1222 			{
       
  1223 			iLocalDevice->SetAddress(address);
       
  1224 			}
       
  1225 		else
       
  1226 			{
       
  1227 			User::Leave(KErrCorrupt);
       
  1228 			}
       
  1229 
       
  1230 		TInt deviceNameLength = static_cast<TInt>(aStream.ReadUint8L());
       
  1231 		if (deviceNameLength <= KMaxBluetoothNameLen)
       
  1232 			{
       
  1233 			RBuf8 deviceName;
       
  1234 			deviceName.CreateL(KMaxBluetoothNameLen);
       
  1235 			CleanupClosePushL(deviceName);
       
  1236 
       
  1237 			aStream.ReadL(deviceName,deviceNameLength);
       
  1238 			if (deviceName.Length() == deviceNameLength)
       
  1239 				{
       
  1240 				iLocalDevice->SetDeviceName(deviceName);
       
  1241 				}
       
  1242 			else
       
  1243 				{
       
  1244 				User::Leave(KErrCorrupt);
       
  1245 				}
       
  1246 			CleanupStack::PopAndDestroy(&deviceName);
       
  1247 			}
       
  1248 		else
       
  1249 			{
       
  1250 			User::Leave(KErrCorrupt);
       
  1251 			}
       
  1252 		
       
  1253 		// Remote devices table:
       
  1254 		TInt rdCount = aStream.ReadUint32L();
       
  1255 		for (TInt i = 0; i < rdCount; i++)
       
  1256 			{
       
  1257 			// First read bitmask of available data
       
  1258 			TUint32 rdSetMask = aStream.ReadUint32L();
       
  1259 
       
  1260 			// Then read available data from file and store
       
  1261 			CBTDevice *rdInstance = CBTDevice::NewLC();
       
  1262 			TBTNamelessDevice& rdNamelessDevInstance = rdInstance->AsNamelessDevice();
       
  1263 			TSecureId rdSid = aStream.ReadUint32L();
       
  1264 
       
  1265 			// Remote BT address is mandatory
       
  1266 			if (rdSetMask & TBTNamelessDevice::EAddress)
       
  1267 				{
       
  1268 				TBTDevAddr rdAddr;
       
  1269 				TPtr8 rdAddrPtr(rdAddr.Des());
       
  1270 				aStream.ReadL(rdAddrPtr, KBTDevAddrSize);
       
  1271 
       
  1272 				// Ensure address is of required length and is non-zero
       
  1273 				if (rdAddrPtr.Length() == KBTDevAddrSize && rdAddr != TBTDevAddr())
       
  1274 					{
       
  1275 					rdInstance->SetDeviceAddress(rdAddr);
       
  1276 					}
       
  1277 				else
       
  1278 					{
       
  1279 					User::Leave(KErrCorrupt);
       
  1280 					}
       
  1281 				}
       
  1282 			else
       
  1283 				{
       
  1284 				User::Leave(KErrCorrupt);
       
  1285 				}
       
  1286 
       
  1287 			if (rdSetMask & TBTNamelessDevice::EDeviceClass)
       
  1288 				{
       
  1289 				TBTDeviceClass rdClass = TBTDeviceClass(aStream.ReadUint32L());
       
  1290 				rdInstance->SetDeviceClass(rdClass);
       
  1291 				}
       
  1292 
       
  1293 			if (rdSetMask & TBTNamelessDevice::ELinkKey)
       
  1294 				{
       
  1295 				TBTLinkKey rdLinkKey;
       
  1296 				aStream.ReadL(rdLinkKey, KHCILinkKeySize);
       
  1297 				if (rdLinkKey.Length() == KHCILinkKeySize)
       
  1298 					{
       
  1299 					TUint8 rdLinkKeyType = static_cast<TBTLinkKeyType>(aStream.ReadUint8L());
       
  1300 					// Ensure value is in the valid range (ELinkKeyCombination is zero so (pointless) comparison with this gives warnings).
       
  1301 					if (rdLinkKeyType <= ELinkKeyDebug)
       
  1302 						{
       
  1303 						rdInstance->SetLinkKey(rdLinkKey, static_cast<TBTLinkKeyType>(rdLinkKeyType));
       
  1304 						}
       
  1305 					else
       
  1306 						{
       
  1307 						User::Leave(KErrCorrupt);
       
  1308 						}
       
  1309 
       
  1310 					}
       
  1311 				else
       
  1312 					{
       
  1313 					User::Leave(KErrCorrupt);
       
  1314 					}
       
  1315 				}
       
  1316 
       
  1317 			if (rdSetMask & TBTNamelessDevice::EGlobalSecurity)
       
  1318 				{
       
  1319 				TBTDeviceSecurity rdGlobSec;
       
  1320 				TUint8 globSecValue = aStream.ReadUint8L();
       
  1321 				// Ensure value is in the valid range (lower value is zero so (pointless) comparison with this gives warnings).
       
  1322 				if (globSecValue <= KBTBURMgrMaxGlobalSecurityValue)
       
  1323 					{
       
  1324 					rdGlobSec.SetSecurityValue(globSecValue);
       
  1325 
       
  1326 					TUint32 passKeyMinLen = aStream.ReadUint32L();
       
  1327 
       
  1328 					if (passKeyMinLen <= KHCIPINCodeSize)
       
  1329 						{
       
  1330 						rdGlobSec.SetPasskeyMinLength(passKeyMinLen);
       
  1331 						rdInstance->SetGlobalSecurity(rdGlobSec);
       
  1332 						}
       
  1333 					else
       
  1334 						{
       
  1335 						User::Leave(KErrCorrupt);
       
  1336 						}
       
  1337 					}
       
  1338 				else
       
  1339 					{
       
  1340 					User::Leave(KErrCorrupt);
       
  1341 					}
       
  1342 				}
       
  1343 
       
  1344 			if (rdSetMask & TBTNamelessDevice::EPageScanRepMode)
       
  1345 				{
       
  1346 				TUint8 rdPageScanRepMode = aStream.ReadUint8L();
       
  1347 				// Ensure value is in the valid range (lower value is zero so (pointless) comparison with this gives warnings).
       
  1348 				if (rdPageScanRepMode <= EPageScanModeR2)
       
  1349 					{
       
  1350 					rdNamelessDevInstance.SetPageScanRepMode(rdPageScanRepMode);
       
  1351 					}
       
  1352 				else
       
  1353 					{
       
  1354 					User::Leave(KErrCorrupt);
       
  1355 					}
       
  1356 				}
       
  1357 
       
  1358 			if (rdSetMask & TBTNamelessDevice::EPageScanMode)
       
  1359 				{
       
  1360 				TUint8 rdPageScanMode = aStream.ReadUint8L();
       
  1361 				// Ensure value is in the valid range (lower value is zero so (pointless) comparison with this gives warnings).
       
  1362 				if (rdPageScanMode <= KBTBURMgrMaxPageScanMode)
       
  1363 					{
       
  1364 					rdNamelessDevInstance.SetPageScanMode(rdPageScanMode);
       
  1365 					}
       
  1366 				else
       
  1367 					{
       
  1368 					User::Leave(KErrCorrupt);
       
  1369 					}
       
  1370 				}
       
  1371 
       
  1372 			if (rdSetMask & TBTNamelessDevice::EPageScanPeriodMode)
       
  1373 				{
       
  1374 				TUint8 rdPageScanPeriodMode = aStream.ReadUint8L();
       
  1375 				// Ensure value is in the valid range (lower value is zero so (pointless) comparison with this gives warnings).
       
  1376 				if (rdPageScanPeriodMode <= KBTBURMgrMaxPageScanPeriodMode)
       
  1377 					{
       
  1378 					rdNamelessDevInstance.SetPageScanPeriodMode(rdPageScanPeriodMode);
       
  1379 					}
       
  1380 				else
       
  1381 					{
       
  1382 					User::Leave(KErrCorrupt);
       
  1383 					}
       
  1384 				}
       
  1385 
       
  1386 			if (rdSetMask & TBTNamelessDevice::EClockOffset)
       
  1387 				{
       
  1388 				TUint16 rdClockOffset = aStream.ReadUint16L();
       
  1389 				rdNamelessDevInstance.SetClockOffset(rdClockOffset);
       
  1390 				}
       
  1391 
       
  1392 			if (rdSetMask & TBTNamelessDevice::EUsed)
       
  1393 				{
       
  1394 				TInt32 usedU = aStream.ReadInt32L();
       
  1395 				TInt32 usedL = aStream.ReadInt32L();
       
  1396 				TInt64 rdUsed = MAKE_TINT64(usedU, usedL);
       
  1397 				rdNamelessDevInstance.SetUsed(rdUsed);
       
  1398 				}
       
  1399 
       
  1400 			if (rdSetMask & TBTNamelessDevice::ESeen)
       
  1401 				{
       
  1402 				TInt32 seenU = aStream.ReadInt32L();
       
  1403 				TInt32 seenL = aStream.ReadInt32L();
       
  1404 				TInt64 rdSeen = MAKE_TINT64(seenU, seenL);
       
  1405 				rdNamelessDevInstance.SetSeen(rdSeen);	
       
  1406 				}
       
  1407 
       
  1408 			if (rdSetMask & TBTNamelessDevice::EPassKey)
       
  1409 				{
       
  1410 				TBTPinCode rdPassKey;
       
  1411 				aStream.ReadL(rdPassKey, KHCIPINCodeSize + 1);
       
  1412 				if (rdPassKey.Length() == KHCIPINCodeSize + 1)
       
  1413 					{
       
  1414 					rdInstance->SetPassKey(rdPassKey);
       
  1415 					}
       
  1416 				else
       
  1417 					{
       
  1418 					User::Leave(KErrCorrupt);
       
  1419 					}
       
  1420 				}
       
  1421 			
       
  1422 			if (rdSetMask & TBTNamelessDevice::EUiCookie)
       
  1423 				{
       
  1424 				TUint32 rdUiCookie = aStream.ReadUint32L();
       
  1425 				rdNamelessDevInstance.SetUiCookie(rdUiCookie);
       
  1426 				}
       
  1427 
       
  1428 			if (rdSetMask & CBTDevice::EDeviceName)
       
  1429 				{
       
  1430 				TInt rdNameLen = static_cast<TInt>(aStream.ReadUint8L());
       
  1431 				if (rdNameLen <= KMaxBluetoothNameLen)
       
  1432 					{
       
  1433 					RBuf8 rdName;
       
  1434 					rdName.CreateL(KMaxBluetoothNameLen);
       
  1435 					CleanupClosePushL(rdName);
       
  1436 					
       
  1437 					aStream.ReadL(rdName, rdNameLen);
       
  1438 					if (rdName.Length() == rdNameLen)
       
  1439 						{
       
  1440 						rdInstance->SetDeviceNameL(rdName);
       
  1441 						}
       
  1442 					else
       
  1443 						{
       
  1444 						User::Leave(KErrCorrupt);
       
  1445 						}
       
  1446 					CleanupStack::PopAndDestroy(&rdName);
       
  1447 					}
       
  1448 				else
       
  1449 					{
       
  1450 					User::Leave(KErrCorrupt);
       
  1451 					}
       
  1452 				}
       
  1453 
       
  1454 			if (rdSetMask & CBTDevice::EFriendlyName)
       
  1455 				{
       
  1456 				TInt rdFriendlyNameLen = static_cast<TInt>(aStream.ReadUint8L());
       
  1457 				if (rdFriendlyNameLen <= KMaxFriendlyNameLen)
       
  1458 					{
       
  1459 					RBuf rdFriendlyName;
       
  1460 					rdFriendlyName.CreateL(KMaxFriendlyNameLen);
       
  1461 					CleanupClosePushL(rdFriendlyName);
       
  1462 
       
  1463 					aStream.ReadL(rdFriendlyName, rdFriendlyNameLen);
       
  1464 					if (rdFriendlyName.Length() == rdFriendlyNameLen)
       
  1465 						{
       
  1466 						rdInstance->SetFriendlyNameL(rdFriendlyName);
       
  1467 						}
       
  1468 					else
       
  1469 						{
       
  1470 						User::Leave(KErrCorrupt);
       
  1471 						}
       
  1472 					CleanupStack::PopAndDestroy(&rdFriendlyName);
       
  1473 					}
       
  1474 				else
       
  1475 					{
       
  1476 					User::Leave(KErrCorrupt);
       
  1477 					}
       
  1478 				}
       
  1479 			
       
  1480 			// Data now stored, add rdInstance to our remote devices list
       
  1481 			iRemoteDevices->AppendL(rdInstance);
       
  1482 			iRemoteDevicesSid->AppendL(rdSid);
       
  1483 			CleanupStack::Pop(rdInstance);
       
  1484 			}
       
  1485 
       
  1486 		// Mark that we now have registry data 
       
  1487 		iHasRegistryData = ETrue;
       
  1488 		}
       
  1489 	}
       
  1490 
       
  1491 /**
       
  1492 Reads registry data from the registry into this instance.
       
  1493 Any existing registry data held in this instance is cleared first.
       
  1494 @param aRegistry The CBTRegistry instance to use for registry access.
       
  1495 **/
       
  1496 void CBTRegistryBURData::ReadFromRegistryL(CBTRegistry& aRegistry)
       
  1497 	{
       
  1498 	LOG_FUNC
       
  1499 
       
  1500 	ClearRegistryData();
       
  1501 
       
  1502 	// The meta information from our registry is known.
       
  1503 	iRegistryVersionMajor = KRegistryDBVersionMajor;
       
  1504 	iRegistryVersionMinor = KRegistryDBVersionMinor;
       
  1505 
       
  1506 	// Persistence table
       
  1507 	iLocalDevice = aRegistry.GetLocalDeviceL();
       
  1508 
       
  1509 	// Remote device table
       
  1510 	// Create a view on the table.
       
  1511 	RBTDbQuery query;
       
  1512 	CleanupClosePushL(query);
       
  1513 	TBTRegistrySearch searchCriteria;
       
  1514 	searchCriteria.FindAll();
       
  1515 	query.SearchL(searchCriteria);
       
  1516 	TDbBookmark bookmark;
       
  1517 	RDbView* view = aRegistry.OpenViewL(query, bookmark);
       
  1518 	CleanupCloseDeletePushL(view);
       
  1519 
       
  1520 	// Populate iRemoteDevices from the view.
       
  1521 	while (!view->AtEnd())
       
  1522 		{
       
  1523 		CBTDevice *next = aRegistry.GetNextDeviceL(*view, bookmark, ETrue);
       
  1524 		CleanupStack::PushL(next);
       
  1525 		
       
  1526 		// CBTRegisty::CreatingProcessUidL() requires a rowset with exactly one row.
       
  1527 		// So we have to requery for this device to get a singular row.
       
  1528 		TDbBookmark singleBookmark;
       
  1529 		RDbView* singleView = aRegistry.OpenDeviceL(next->BDAddr(), singleBookmark);
       
  1530 		CleanupCloseDeletePushL(singleView);
       
  1531 		TSecureId nextSid = aRegistry.CreatingProcessUidL(*singleView);
       
  1532 		CleanupStack::PopAndDestroy(singleView);
       
  1533 		
       
  1534 		iRemoteDevices->AppendL(next);
       
  1535 		iRemoteDevicesSid->AppendL(nextSid);
       
  1536 		
       
  1537 		CleanupStack::Pop(next);	// iRemoteDevices now takes ownership
       
  1538 		}
       
  1539 
       
  1540 	CleanupStack::PopAndDestroy(2, &query);	// view and query
       
  1541 
       
  1542 	// Mark that we now have registry data 
       
  1543 	iHasRegistryData = ETrue;
       
  1544 	}
       
  1545 
       
  1546 /**
       
  1547 Updates the persistence table of the registry with local device name held in this instance
       
  1548 if the registry currently holds a default name.
       
  1549 @param aRegistry The CBTRegistry instance to use for registry access.
       
  1550 @return ETrue if an update was made to the registry.
       
  1551 **/
       
  1552 TBool CBTRegistryBURData::WriteLocalDeviceNameToRegistryL(CBTRegistry& aRegistry) const
       
  1553 	{
       
  1554 	LOG_FUNC
       
  1555 
       
  1556 	TBool updateDone = EFalse;
       
  1557 
       
  1558 	// Update device name only if the registry has a default name 
       
  1559 	TBTLocalDevice defaultDevice;
       
  1560 	TRAP_IGNORE(aRegistry.GetDefaultDeviceFromIniL(defaultDevice));
       
  1561 
       
  1562 	if (!defaultDevice.IsValidDeviceName())
       
  1563 		{
       
  1564 		// Could not obtain a default name - use KDefaultLocalName instead
       
  1565 		defaultDevice.SetDeviceName(KDefaultLocalName);
       
  1566 		}
       
  1567 
       
  1568 	TBTLocalDevice* localDevice = aRegistry.GetLocalDeviceL();
       
  1569 	CleanupStack::PushL(localDevice);
       
  1570 
       
  1571 	if (localDevice->DeviceName() == defaultDevice.DeviceName())
       
  1572 		{
       
  1573 		// Local device name is default, update with restored value.
       
  1574 		localDevice->SetDeviceName(GetLocalDeviceNameL());
       
  1575 		aRegistry.UpdateLocalDeviceL(*localDevice);
       
  1576 		updateDone = ETrue;
       
  1577 		}
       
  1578 
       
  1579 	CleanupStack::PopAndDestroy(localDevice);
       
  1580 
       
  1581 	return updateDone;
       
  1582 	}
       
  1583 
       
  1584 /**
       
  1585 Updates an entry of the remote devices table of the registry with data held in this instance.
       
  1586 If the remote device already exists in the registry, the registry version is updated only if it
       
  1587 does not hold a link key.
       
  1588 Otherwise, the remote device is added to the registry.
       
  1589 @param aRegistry The CBTRegistry instance to use for registry access.
       
  1590 @param aDeviceIndex The remote device held in this CBTRegistryBURData instance to be written to the registry.
       
  1591 @return ETrue if an update was made to the registry.
       
  1592 **/
       
  1593 TBool CBTRegistryBURData::WriteRemoteDeviceToRegistryL(CBTRegistry& aRegistry, TInt aDeviceIndex) const
       
  1594 	{
       
  1595 	LOG_FUNC
       
  1596 
       
  1597 	TBool updateDone = EFalse;
       
  1598 	
       
  1599 	// Get device and SID
       
  1600 	const CBTDevice& nextRemDevice = GetRemoteDeviceL(aDeviceIndex);
       
  1601 	TSecureId nextRemDeviceSid = GetRemoteDeviceEntrySidL(aDeviceIndex);
       
  1602 
       
  1603 	// Try to add device to registry. If this fails with KErrAlreadExists, then update existing device.
       
  1604 	TRAPD(err, aRegistry.CreateDeviceL(nextRemDevice, nextRemDevice.IsValidUiCookie(), nextRemDeviceSid));
       
  1605 
       
  1606 	if (err == KErrNone)
       
  1607 		{
       
  1608 		// New device added successfully
       
  1609 		updateDone = ETrue;
       
  1610 		}
       
  1611 	else if (err == KErrAlreadyExists)
       
  1612 		{
       
  1613 		// Device already exists. Extract and examine
       
  1614 		TDbBookmark bookmark;
       
  1615 		RDbView* view = aRegistry.OpenDeviceL(nextRemDevice.BDAddr(), bookmark);
       
  1616 		CleanupCloseDeletePushL(view);
       
  1617 		CBTDevice *regDev = aRegistry.GetNextDeviceL(*view, bookmark, ETrue);
       
  1618 		CleanupStack::PushL(regDev);
       
  1619 
       
  1620 		if (!regDev->IsValidLinkKey())
       
  1621 			{
       
  1622 			// No link key - safe to restore remote device from file.
       
  1623 			view->FirstL();
       
  1624 			aRegistry.UpdateDeviceL(*view, nextRemDevice);
       
  1625 			updateDone = ETrue;
       
  1626 			}
       
  1627 
       
  1628 		CleanupStack::PopAndDestroy(2, view);
       
  1629 		}
       
  1630 	else
       
  1631 		{
       
  1632 		// Unexpected error - pass upward for handling
       
  1633 		User::Leave(err);
       
  1634 		}
       
  1635 
       
  1636 	return updateDone;
       
  1637 	}
       
  1638 
       
  1639 void CBTRegistryBURData::GetRegistryVersionL(TUint32& aRegistryVersionMajor, TUint32& aRegistryVersionMinor) const
       
  1640 	{
       
  1641 	LOG_FUNC
       
  1642 
       
  1643 	if (!HasRegistryData())
       
  1644 		{
       
  1645 		User::Leave(KErrNotFound);
       
  1646 		}
       
  1647 	
       
  1648 	aRegistryVersionMajor = iRegistryVersionMajor;
       
  1649 	aRegistryVersionMinor = iRegistryVersionMinor;
       
  1650 	}
       
  1651 
       
  1652 const TDesC8& CBTRegistryBURData::GetLocalDeviceNameL() const
       
  1653 	{
       
  1654 	LOG_FUNC
       
  1655 
       
  1656 	if (!HasRegistryData())
       
  1657 		{
       
  1658 		User::Leave(KErrNotFound);
       
  1659 		}
       
  1660 
       
  1661 	__ASSERT_DEBUG(iLocalDevice, PANIC(KBTBackupPanicCat, EBTBURMgrExpectedDataMissing));
       
  1662 	return iLocalDevice->DeviceName();
       
  1663 	}
       
  1664 
       
  1665 TBool CBTRegistryBURData::IsLocalAddressNonZeroL() const
       
  1666 	{
       
  1667 	LOG_FUNC
       
  1668 
       
  1669 	TBTDevAddr zeroAddr;
       
  1670 	return !IsLocalAddressEqualL(zeroAddr);
       
  1671 	}
       
  1672 
       
  1673 TBool CBTRegistryBURData::IsLocalAddressEqualL(TBTDevAddr& aAddr) const
       
  1674 	{
       
  1675 	LOG_FUNC
       
  1676 
       
  1677 	if (!HasRegistryData())
       
  1678 		{
       
  1679 		User::Leave(KErrNotFound);
       
  1680 		}
       
  1681 
       
  1682 	__ASSERT_DEBUG(iLocalDevice, PANIC(KBTBackupPanicCat, EBTBURMgrExpectedDataMissing));
       
  1683 	return (iLocalDevice->Address() == aAddr);
       
  1684 	}
       
  1685 
       
  1686 TInt CBTRegistryBURData::CountRemoteDevicesL() const
       
  1687 	{
       
  1688 	LOG_FUNC
       
  1689 
       
  1690 	if (!HasRegistryData())
       
  1691 		{
       
  1692 		User::Leave(KErrNotFound);
       
  1693 		}
       
  1694 	
       
  1695 	__ASSERT_DEBUG(iRemoteDevices->Count() == iRemoteDevicesSid->Count(), PANIC(KBTBackupPanicCat, EBTBURMgrArraySizeMisMatch));	
       
  1696 	return iRemoteDevices->Count();
       
  1697 	}
       
  1698 
       
  1699 const CBTDevice& CBTRegistryBURData::GetRemoteDeviceL(TInt aDeviceIndex) const
       
  1700 	{
       
  1701 	LOG_FUNC
       
  1702 
       
  1703 	if (!HasRegistryData() || !((aDeviceIndex >= 0) && (aDeviceIndex < iRemoteDevices->Count())))
       
  1704 		{
       
  1705 		User::Leave(KErrNotFound);
       
  1706 		}
       
  1707 
       
  1708 	__ASSERT_DEBUG(iRemoteDevices->Count() == iRemoteDevicesSid->Count(), PANIC(KBTBackupPanicCat, EBTBURMgrArraySizeMisMatch));	
       
  1709 	return *(iRemoteDevices->At(aDeviceIndex));
       
  1710 	}
       
  1711 
       
  1712 TSecureId CBTRegistryBURData::GetRemoteDeviceEntrySidL(TInt aDeviceIndex) const
       
  1713 	{
       
  1714 	LOG_FUNC
       
  1715 
       
  1716 	if (!HasRegistryData() || !((aDeviceIndex >= 0) && (aDeviceIndex < iRemoteDevicesSid->Count())))
       
  1717 		{
       
  1718 		User::Leave(KErrNotFound);
       
  1719 		}
       
  1720 	
       
  1721 	__ASSERT_DEBUG(iRemoteDevices->Count() == iRemoteDevicesSid->Count(), PANIC(KBTBackupPanicCat, EBTBURMgrArraySizeMisMatch));	
       
  1722 	return iRemoteDevicesSid->At(aDeviceIndex);
       
  1723 	}
       
  1724 
       
  1725 /**
       
  1726 Clears any registry data stored internally within this instance.
       
  1727 If no data is stored, this method does nothing.
       
  1728 **/
       
  1729 void CBTRegistryBURData::ClearRegistryData()
       
  1730 	{
       
  1731 	LOG_FUNC
       
  1732 
       
  1733 	// This is a no-op if we have no registry data to clear
       
  1734 	if (HasRegistryData())
       
  1735 		{
       
  1736 		// Clear data held previously
       
  1737 		iRemoteDevicesSid->Reset();
       
  1738 		iRemoteDevices->ResetAndDestroy();
       
  1739 		delete iLocalDevice;
       
  1740 		iLocalDevice = NULL;
       
  1741 
       
  1742 		iHasRegistryData = EFalse;
       
  1743 		}
       
  1744 	}
       
  1745 
       
  1746 /**
       
  1747 CBTLocalAddressFetcher - Fetches the local device address, or waits for the addresss to become available, and 
       
  1748 passes to CBTManServerBURMgr.
       
  1749 **/
       
  1750 CBTLocalAddressFetcher* CBTLocalAddressFetcher::NewL(CBTManServerBURMgr& aBURMgr, CBTRegistry& aRegistry, TInt aPriority)
       
  1751 	{
       
  1752 	LOG_STATIC_FUNC
       
  1753 
       
  1754 	CBTLocalAddressFetcher* result = new(ELeave) CBTLocalAddressFetcher(aBURMgr, aRegistry, aPriority);
       
  1755 	CleanupStack::PushL(result);
       
  1756 	result->ConstructL();
       
  1757 	CleanupStack::Pop(result);
       
  1758 	return result;
       
  1759 	}
       
  1760 
       
  1761 CBTLocalAddressFetcher::CBTLocalAddressFetcher(CBTManServerBURMgr& aBURMgr, CBTRegistry& aRegistry, TInt aPriority) 
       
  1762 	: CActive(aPriority), 
       
  1763 	iBURMgr(aBURMgr), 
       
  1764 	iRegistry(aRegistry)
       
  1765 	{
       
  1766 	LOG_FUNC
       
  1767 
       
  1768 	CActiveScheduler::Add(this);
       
  1769 	}
       
  1770 
       
  1771 CBTLocalAddressFetcher::~CBTLocalAddressFetcher()
       
  1772 	{
       
  1773 	LOG_FUNC
       
  1774 
       
  1775 	// Cancel any outstanding requests
       
  1776 	Cancel();
       
  1777 	iProperty.Close();
       
  1778 	}
       
  1779 
       
  1780 void CBTLocalAddressFetcher::ConstructL()
       
  1781 	{
       
  1782 	LOG_FUNC
       
  1783 
       
  1784 	// Attach to KPropertyKeyBluetoothGetLocalDeviceAddress
       
  1785 	LEAVEIFERRORL(iProperty.Attach(KPropertyUidBluetoothCategory, KPropertyKeyBluetoothGetLocalDeviceAddress));
       
  1786 	}
       
  1787 
       
  1788 void CBTLocalAddressFetcher::FetchLocalAddress()
       
  1789 	{
       
  1790 	LOG_FUNC
       
  1791 
       
  1792 	// Subscribe for local address, in case we need to wait
       
  1793 	SubscribeToGetLocalDeviceAddressKey();	
       
  1794 
       
  1795 	// Attempt to read the BT address from KPropertyKeyBluetoothGetLocalDeviceAddress key
       
  1796 	// If key is not found or yields a zero address then try the registry.
       
  1797 	// If the registry also holds a zero address then wait for notification from the P&S key.
       
  1798 	TBuf8<KBTDevAddrSize> btAddrDes;
       
  1799 	TBTDevAddr btAddr;
       
  1800 	TInt err = iProperty.Get(btAddrDes);
       
  1801 	
       
  1802 	if (err != KErrNone)
       
  1803 		{
       
  1804 		// Key does not exist or could not be read.
       
  1805 		// Stack may not be loaded, so now try registry.
       
  1806 		// Ignore any errors; if we can't read this now then we will wait for the stack.
       
  1807 		TRAP_IGNORE(btAddr = GetLocalAddressFromRegistryL());
       
  1808 		}
       
  1809 	else
       
  1810 		{
       
  1811 		// Convert btAddrDes to TBTDevAddr if it has the required size.
       
  1812 		if (btAddrDes.Length() == KBTDevAddrSize)
       
  1813 			{
       
  1814 			btAddr = btAddrDes;	
       
  1815 			}
       
  1816 
       
  1817 		if (btAddr == TBTDevAddr())
       
  1818 			{
       
  1819 			// Key exists, so stack is loaded, but address is zero, so now try registry
       
  1820 			// Ignore any errors; if we can't read this now then we will wait for the stack.
       
  1821 			TRAP_IGNORE(btAddr = GetLocalAddressFromRegistryL());
       
  1822 			}
       
  1823 		}
       
  1824 	
       
  1825 	// We have tried our best to get the local address.
       
  1826 	// If this is non-zero, provide to CBTManServerBURMgr instance. 
       
  1827 	// Otherwise, wait on P&S key
       
  1828 	if (btAddr != TBTDevAddr())
       
  1829 		{
       
  1830 		// We have a non-zero address.
       
  1831 		// Cancel subscription and inform CBTManServerBURMgr.
       
  1832 		Cancel();
       
  1833 		iBURMgr.SetLocalAddress(btAddr);
       
  1834 		}	
       
  1835 	}
       
  1836 
       
  1837 void CBTLocalAddressFetcher::SubscribeToGetLocalDeviceAddressKey()
       
  1838 	{
       
  1839 	LOG_FUNC
       
  1840 
       
  1841 	// Subscribe to KPropertyKeyBluetoothGetLocalDeviceAddress key
       
  1842 	iProperty.Subscribe(iStatus);
       
  1843 	SetActive();
       
  1844 	}
       
  1845 
       
  1846 TBTDevAddr CBTLocalAddressFetcher::GetLocalAddressFromRegistryL()
       
  1847 	{
       
  1848 	LOG_FUNC
       
  1849 	
       
  1850 	TBTLocalDevice* regLocalDevice=iRegistry.GetLocalDeviceL();
       
  1851 	TBTDevAddr result=regLocalDevice->Address();
       
  1852 	delete regLocalDevice;
       
  1853 	
       
  1854 	return result;	
       
  1855 	}
       
  1856 
       
  1857 void CBTLocalAddressFetcher::RunL()
       
  1858 	{
       
  1859 	LOG_FUNC
       
  1860 
       
  1861 	if (iStatus == KErrNone)
       
  1862 		{
       
  1863 		// Obtain address and send to CBTManServerBURMgr
       
  1864 		TBuf8<KBTDevAddrSize> btAddrDes;
       
  1865 		TBTDevAddr btAddr;
       
  1866 		TInt err = iProperty.Get(btAddrDes);
       
  1867 				
       
  1868 		__ASSERT_DEBUG(err == KErrNone, PANIC(KBTBackupPanicCat, EBTBURMgrUnexpectedRPropertyError));
       
  1869 		
       
  1870 		if (err == KErrNone) 
       
  1871 			{
       
  1872 			btAddr = btAddrDes;
       
  1873 			iBURMgr.SetLocalAddress(btAddr);
       
  1874 			}
       
  1875 		}
       
  1876 	}
       
  1877 
       
  1878 void CBTLocalAddressFetcher::DoCancel()
       
  1879 	{
       
  1880 	LOG_FUNC
       
  1881 
       
  1882 	// Cancel our subscription
       
  1883 	iProperty.Cancel();
       
  1884 	}
       
  1885 
       
  1886 /**
       
  1887 CBTActiveBackupDataClient - Active callback implementation (for restore notification)
       
  1888 **/
       
  1889 CBTActiveBackupDataClient* CBTActiveBackupDataClient::NewL(CBTManServerBURMgr& aBURMgr)
       
  1890 	{
       
  1891 	LOG_STATIC_FUNC
       
  1892 
       
  1893 	CBTActiveBackupDataClient* result = new (ELeave) CBTActiveBackupDataClient(aBURMgr);
       
  1894 	return result;
       
  1895 	}
       
  1896 
       
  1897 CBTActiveBackupDataClient::CBTActiveBackupDataClient(CBTManServerBURMgr& aBURMgr) 
       
  1898 	: iBURMgr(aBURMgr)
       
  1899 	{
       
  1900 	LOG_FUNC
       
  1901 	}
       
  1902 
       
  1903 CBTActiveBackupDataClient::~CBTActiveBackupDataClient()
       
  1904 	{
       
  1905 	LOG_FUNC
       
  1906 	}
       
  1907 
       
  1908 // Backup methods (not used)
       
  1909 void CBTActiveBackupDataClient::AllSnapshotsSuppliedL()
       
  1910 	{
       
  1911 	LOG_FUNC
       
  1912 
       
  1913 	//Not supported
       
  1914 	User::Leave(KErrNotSupported);
       
  1915 	}
       
  1916  
       
  1917 void CBTActiveBackupDataClient::ReceiveSnapshotDataL(TDriveNumber /*aDrive*/, TDesC8& /*aBuffer*/, TBool /*aLastSection*/)
       
  1918 	{
       
  1919 	LOG_FUNC
       
  1920 
       
  1921  	//Not supported
       
  1922 	User::Leave(KErrNotSupported);	
       
  1923 	}
       
  1924  
       
  1925 TUint CBTActiveBackupDataClient::GetExpectedDataSize(TDriveNumber /*aDrive*/)
       
  1926 	{
       
  1927 	LOG_FUNC
       
  1928 
       
  1929 	//Not supported - so expected size can be 0
       
  1930 	return 0;
       
  1931 	}
       
  1932  
       
  1933 void CBTActiveBackupDataClient::GetSnapshotDataL(TDriveNumber /*aDrive*/, TPtr8& /*aBuffer*/, TBool& /*aFinished*/)
       
  1934 	{
       
  1935 	LOG_FUNC
       
  1936 
       
  1937 	//Not supported
       
  1938 	User::Leave(KErrNotSupported);
       
  1939 	}
       
  1940  
       
  1941 void CBTActiveBackupDataClient::InitialiseGetBackupDataL(TDriveNumber /*aDrive*/)
       
  1942 	{
       
  1943 	LOG_FUNC
       
  1944 
       
  1945 	//Not supported
       
  1946 	User::Leave(KErrNotSupported);
       
  1947 	}
       
  1948  
       
  1949 void CBTActiveBackupDataClient::GetBackupDataSectionL(TPtr8& /*aBuffer*/, TBool& /*aFinished*/)
       
  1950 	{
       
  1951 	LOG_FUNC
       
  1952 
       
  1953 	//Not supported
       
  1954 	User::Leave(KErrNotSupported);
       
  1955 	}
       
  1956          
       
  1957 //Restore methods (only the notification method RestoreComplete() is used)
       
  1958  
       
  1959 void CBTActiveBackupDataClient::InitialiseRestoreBaseDataL(TDriveNumber /*aDrive*/)
       
  1960 	{
       
  1961 	LOG_FUNC
       
  1962 
       
  1963 	//Note that we are doing a base restore.
       
  1964 	User::Leave(KErrNotSupported);
       
  1965 	}
       
  1966  
       
  1967 void CBTActiveBackupDataClient::RestoreBaseDataSectionL(TDesC8& /*aBuffer*/, TBool /*aFinished*/)
       
  1968 	{
       
  1969 	LOG_FUNC
       
  1970 
       
  1971 	//Not supported
       
  1972 	User::Leave(KErrNotSupported);
       
  1973 	}	
       
  1974  
       
  1975 void CBTActiveBackupDataClient::InitialiseRestoreIncrementDataL(TDriveNumber /*aDrive*/)
       
  1976 	{
       
  1977 	LOG_FUNC
       
  1978 
       
  1979 	//Not supported
       
  1980 	User::Leave(KErrNotSupported);
       
  1981 	}
       
  1982  
       
  1983 void CBTActiveBackupDataClient::RestoreIncrementDataSectionL(TDesC8& /*aBuffer*/, TBool /*aFinished*/)
       
  1984 	{
       
  1985 	LOG_FUNC
       
  1986 
       
  1987 	//Not supported
       
  1988 	User::Leave(KErrNotSupported);
       
  1989 	}
       
  1990  
       
  1991 void CBTActiveBackupDataClient::RestoreComplete(TDriveNumber aDrive)
       
  1992 	{
       
  1993 	LOG_FUNC
       
  1994 
       
  1995 	// Allow CBTManServerBURMgr instance to handle arrival of restore file.
       
  1996 	if (aDrive == RFs::GetSystemDrive())
       
  1997 		{
       
  1998 		iBURMgr.RestoreFileReady();
       
  1999 		}
       
  2000 	}
       
  2001  
       
  2002          
       
  2003 //General methods
       
  2004  
       
  2005 void CBTActiveBackupDataClient::TerminateMultiStageOperation()
       
  2006 	{
       
  2007 	LOG_FUNC
       
  2008 
       
  2009 	//Dont care - we will see the operation is cancelled when normal or unset mode is invoked.
       
  2010 	}
       
  2011  
       
  2012 //Test methods
       
  2013  
       
  2014 TUint CBTActiveBackupDataClient::GetDataChecksum(TDriveNumber /*aDrive*/)
       
  2015 	{
       
  2016 	LOG_FUNC
       
  2017 
       
  2018 	//Return an invariant checksum
       
  2019 	return 0;
       
  2020 	}