bluetoothmgmt/btmgr/BTManServer/BTRegistryDB.cpp
changeset 0 29b1cd4cb562
child 8 2b6718f05bdb
equal deleted inserted replaced
-1:000000000000 0:29b1cd4cb562
       
     1 // Copyright (c) 1999-2009 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 // This does the main work on behalf of the subsessions of liasing with DBMS
       
    15 // 
       
    16 //
       
    17 
       
    18 #include "BTRegistryDB.h"
       
    19 #include "btmanserverutil.h"
       
    20 #include <utf.h>
       
    21 #include <bluetooth/logger.h>
       
    22 #include <bafl/sysutil.h>
       
    23 
       
    24 #ifdef __FLOG_ACTIVE
       
    25 _LIT8(KLogComponent, LOG_COMPONENT_BT_REGISTRY);
       
    26 #endif
       
    27 
       
    28 #ifdef _DEBUG
       
    29 PANICCATEGORY("btregdb");
       
    30 #endif
       
    31 
       
    32 
       
    33 void Panic(TBTRegistryDBPanic aPanic)
       
    34 	{
       
    35 	LOG_STATIC_FUNC
       
    36 	_LIT(KRegistryDBPanicName, "BT RegistryDB Panic");
       
    37 	User::Panic(KRegistryDBPanicName, aPanic);
       
    38 	}
       
    39 //
       
    40 
       
    41 CBTRegistry::CBTRegistry()
       
    42 	{
       
    43 	LOG_FUNC
       
    44 	}
       
    45 
       
    46 CBTRegistry::~CBTRegistry()
       
    47 	{
       
    48 	LOG_FUNC
       
    49 	iDB.Close();
       
    50 	iDBMSServer.Close();
       
    51 	}
       
    52 
       
    53 CBTRegistry* CBTRegistry::NewL()
       
    54 	{
       
    55 	LOG_STATIC_FUNC
       
    56 	CBTRegistry* self = new (ELeave) CBTRegistry;
       
    57 	CleanupStack::PushL(self);
       
    58 	self->ConstructL();
       
    59 #ifdef _DEBUG
       
    60 	CleanupStack::Check(self);
       
    61 #endif
       
    62 	CleanupStack::Pop();
       
    63 	return self;
       
    64 	}
       
    65 
       
    66 void CBTRegistry::ConstructL()
       
    67 	{
       
    68 	LOG_FUNC
       
    69 	// we use a DBMS Server session as multiple clients may
       
    70 	// be updating their views concurrently.  Without this
       
    71 	// DBMS would (rightly) panic a rowset already in update
       
    72 	User::LeaveIfError(iDBMSServer.Connect());
       
    73 	OpenRegistryL();
       
    74 	}
       
    75 
       
    76 void CBTRegistry::OpenRegistryL()
       
    77 /**
       
    78 	Open the Registry DB.
       
    79 	If it doesn't exist, attempt to create the necessary path,file and DB
       
    80 **/
       
    81 	{
       
    82 	LOG_FUNC
       
    83 	const static TInt KMaxTries=4;
       
    84 	TInt err;
       
    85 	TInt loopCount=0;
       
    86 	
       
    87 
       
    88 	//	In secure EKA2 DBMS land, registry DB is created in DBMS data cage
       
    89 	do
       
    90 		{
       
    91 		err=iDB.Open(iDBMSServer, TBTRegistryDatabaseSecure()(), KBTRegistryDatabaseSecurePolicy());
       
    92 			
       
    93 		if(err == KErrNotFound)
       
    94 			{
       
    95 			CreateRegistryL();
       
    96 			}
       
    97 		else if (err != KErrNone)
       
    98 			{
       
    99 			// If we get here the BT registry file must be corrupt. 
       
   100 			// Delete the file and go round the while loop once more.
       
   101 			DeleteCorruptRegistryL();
       
   102 			}
       
   103 		else
       
   104 			{
       
   105 			TRAP(err,ValidateMetaTableL()); // make sure it's ok version etc.
       
   106 			if(err==KErrNone)
       
   107 				{
       
   108 				TRAP(err,ValidatePersistTableL()); // make sure it's been properly written to
       
   109 				}
       
   110 			if (err!=KErrNone)
       
   111 				{
       
   112 				// Either the Meta Table validate failed or the Persist Table validate failed.
       
   113 				// Delete the file and go round the while loop once more.
       
   114 				DeleteCorruptRegistryL();
       
   115 				}
       
   116 			}	
       
   117 		loopCount++;
       
   118 		} while (err!=KErrNone && loopCount<KMaxTries);
       
   119 
       
   120 	if(err != KErrNone)
       
   121 		{
       
   122 		User::Leave(KErrAbort);		// give up gracefully
       
   123 		}
       
   124 
       
   125 	// Purge any SSP debug link keys left over from a previous SSP debug session
       
   126 	PurgeDebugLinkKeysL();
       
   127 
       
   128 	(void)iDB.Compact();	// compact now
       
   129 	// ready!
       
   130 	}
       
   131 
       
   132 
       
   133 
       
   134 RDbTable* CBTRegistry::OpenTableL(const TDesC& aTable)
       
   135 /**
       
   136 	Find tables of a given name
       
   137 	@param	aTable	Name of table to open
       
   138 	@return table and ownership
       
   139 **/
       
   140 	{
       
   141 	LOG_FUNC
       
   142 	RDbTable* table = new (ELeave) RDbTable;
       
   143 	CleanupCloseDeletePushL(table);
       
   144 
       
   145 	TInt err;
       
   146 
       
   147 	err = table->Open(iDB, aTable);
       
   148 	User::LeaveIfError(err);
       
   149 
       
   150 	CleanupStack::Pop(); // table
       
   151 
       
   152 	return table;
       
   153 	}
       
   154 
       
   155 RDbTable* CBTRegistry::OpenPersistTableL()
       
   156 /**
       
   157 	Find the persist table (local device settings)
       
   158 	and return it and ownership
       
   159 
       
   160 	@return ownership of table
       
   161 **/
       
   162 	{
       
   163 	LOG_FUNC
       
   164 	return OpenTableL(KPersistTable);
       
   165 	}
       
   166 
       
   167 RDbTable* CBTRegistry::OpenDeviceTableL()
       
   168 /**
       
   169 	Find the remote device table
       
   170 	@return table and ownership
       
   171 **/
       
   172 	{
       
   173 	LOG_FUNC
       
   174 	return OpenTableL(KDeviceTable);
       
   175 	}
       
   176 
       
   177 RDbTable* CBTRegistry::OpenCSYTableL()
       
   178 /**
       
   179 	Find the CSY table
       
   180 	@return table and ownership
       
   181 **/
       
   182 	{
       
   183 	LOG_FUNC
       
   184 	return OpenTableL(KCSYTable);
       
   185 	}
       
   186 
       
   187 void CBTRegistry::ValidateMetaTableL()
       
   188 /**
       
   189 	Go to Meta table and check version numbers etc
       
   190 **/
       
   191 	{
       
   192 	LOG_FUNC
       
   193 	RDbTable* table = OpenTableL(KMetaTable);
       
   194 	CleanupCloseDeletePushL(table);
       
   195 
       
   196 	// get the processSID
       
   197 	TBool success = table->FirstL();
       
   198 	if (!success)
       
   199 		{
       
   200 		LOG(_L("BT Registry DB Meta Table CORRUPT!"));
       
   201 		User::Leave(KErrEof);
       
   202 		}
       
   203 
       
   204 	table->GetL();
       
   205 	
       
   206 
       
   207 	//put version checking in when we think about backup server
       
   208 	TUint major = table->ColUint32(ColumnNoL(KMetaColName_VersionMajor, *table));
       
   209 	TUint minor = table->ColUint32(ColumnNoL(KMetaColName_VersionMinor, *table));
       
   210 	LOG(_L("CBTRegistry opened registry DB Meta Table"));
       
   211 	LOG1(_L("\tMajorVersion: %d"), major); 
       
   212 	LOG1(_L("\tMinorVersion: %d"), minor); 
       
   213 
       
   214 	if(KRegistryDBVersionMajor != major || 
       
   215 			KRegistryDBVersionMinor != minor)
       
   216 		{
       
   217 		User::Leave(KErrCorrupt);
       
   218 		}
       
   219 
       
   220 	CleanupStack::PopAndDestroy(table);
       
   221 	}
       
   222 
       
   223 void CBTRegistry::ValidatePersistTableL()
       
   224 /**
       
   225 	Go to Persist table and check local device values
       
   226 **/
       
   227 	{
       
   228 	LOG_FUNC
       
   229 	RDbTable* table = OpenTableL(KPersistTable);
       
   230 	CleanupCloseDeletePushL(table);
       
   231 
       
   232 	// get the processSID
       
   233 	TBool success = table->FirstL();
       
   234 	if (!success)
       
   235 		{
       
   236 		LOG(_L("BT Registry DB Local Device Table (Persist Table) CORRUPT!"));
       
   237 		User::Leave(KErrEof);
       
   238 		}
       
   239 		
       
   240 	table->GetL();
       
   241 	
       
   242 #ifdef _DEBUG
       
   243 	// check the Local device configuration (aka Stack Persistance data)
       
   244 	TPtrC8 addrBuf(table->ColDes8(ColumnNoL(KColName_DeviceAddress, *table)));
       
   245 	TUint32 CoD = table->ColUint32(ColumnNoL(KPersistColName_CoD, *table));
       
   246 	TUint8 scanEnable = table->ColUint8(ColumnNoL(KPersistColName_ScanEnable, *table));
       
   247 	TPtrC8 name = table->ColDes8(ColumnNoL(KPersistColName_LocalName, *table));
       
   248 	TUint8 powerSettings = table->ColUint8(ColumnNoL(KPersistColName_PowerSettings, *table));
       
   249 	TUint8 limDisc = table->ColUint8(ColumnNoL(KPersistColName_LimitedDiscoverable, *table));
       
   250 	TBool afhChannelAssessmentMode = table->ColUint8(ColumnNoL(KPersistColName_AFHChannelAssessmentMode, *table));
       
   251 	TBool acceptPairedOnlyMode = table->ColUint8(ColumnNoL(KPersistColName_AcceptPairedOnlyMode, *table));
       
   252 	LOG(_L("CBTRegistry opened registry DB Persist Table"));
       
   253 	LOG6(_L("\tDevice Address (zero is acceptable): %02x%02x %02x%02x%02x%02x"),
       
   254 			addrBuf[0],
       
   255 			addrBuf[1],
       
   256 			addrBuf[2],
       
   257 			addrBuf[3],
       
   258 			addrBuf[4],
       
   259 			addrBuf[5]
       
   260 			);
       
   261 	LOG1(_L("\tCoD: 0x%02x"),CoD);
       
   262 	LOG1(_L("\tScan Enable: 0x%02x"),scanEnable);
       
   263 	LOG1(_L8("\tLocal Name: \"%S\""),&name); //name is an 8 bit string
       
   264 	LOG1(_L("\tPower Settings: 0x%02x"),powerSettings);
       
   265 	LOG1(_L("\tLimited Discoverable: 0x%02x"),limDisc);
       
   266 	LOG1(_L("\tAFHChannelAssessmentMode: %d"),afhChannelAssessmentMode);
       
   267 	LOG1(_L("\tAcceptPairedOnlyMode: %d"),acceptPairedOnlyMode);
       
   268 #endif
       
   269 
       
   270 	CleanupStack::PopAndDestroy(table);
       
   271 	}
       
   272 
       
   273 void CBTRegistry::CreateRegistryL()
       
   274 /**
       
   275 	Creates the Database and Tables we need
       
   276 **/
       
   277 	{
       
   278 	LOG_FUNC
       
   279 	//	In secure DBMS land, the BT Manager DB is created in DBMS's data cage.
       
   280 	TInt err = iDB.Create(iDBMSServer, TBTRegistryDatabaseSecure()(), KBTRegistryDatabaseSecurePolicy()); // This leaves iDB in an open state.
       
   281 
       
   282 
       
   283 	User::LeaveIfError(err);
       
   284 	
       
   285 	SetupDefaultRegistryL();
       
   286 	
       
   287 	// close the database
       
   288 	iDB.Close();	
       
   289 	LOG(_L("BT Registry DB Created successfully"));
       
   290 	}
       
   291 
       
   292 void CBTRegistry::PurgeDebugLinkKeysL()
       
   293 /**
       
   294  	Remove (if present) any SSP debug link keys that may have been created by a previous SSP debug session.
       
   295 **/
       
   296 	{
       
   297 	LOG_FUNC
       
   298 	RBTDbQuery query;
       
   299 	CleanupClosePushL(query);
       
   300 	query.MatchLinkKeyTypeL(ELinkKeyDebug);
       
   301 
       
   302 	//We dont use the bookmark here, so employ a dummy bookmark.
       
   303 	TDbBookmark dummy;
       
   304 	RDbView* view = OpenViewL(query, dummy);
       
   305 	CleanupCloseDeletePushL(view);
       
   306 
       
   307 	if (!view->IsEmptyL())
       
   308 		{
       
   309 		// Debug link keys found in registry, unpair these.
       
   310 		UnpairViewL(*view);
       
   311 		}
       
   312 	
       
   313 	CleanupStack::PopAndDestroy(2, &query);	// view and query
       
   314 	}
       
   315 
       
   316 
       
   317 void CBTRegistry::CreatePersistTableL()
       
   318 /**
       
   319 	Create the table with all that is necessary for storing local device details
       
   320 **/
       
   321 	{
       
   322 	LOG_FUNC
       
   323 	CDbColSet* theColumns = CDbColSet::NewLC();
       
   324 
       
   325 	// add in the columns for the Local device configuration (aka Stack Persistance data)
       
   326 	theColumns->AddL(TDbCol(KColName_DeviceAddress,						EDbColText8));	// Binary not allowed in SQL
       
   327 	theColumns->AddL(TDbCol(KPersistColName_CoD,						EDbColUint32));
       
   328 	theColumns->AddL(TDbCol(KPersistColName_ScanEnable,					EDbColUint8));
       
   329 	// specify the maximum local name length to be KMaxBluetoothNameLen
       
   330 	theColumns->AddL(TDbCol(KPersistColName_LocalName,					EDbColText8, KMaxBluetoothNameLen));
       
   331 	theColumns->AddL(TDbCol(KPersistColName_PowerSettings,				EDbColUint8));
       
   332 	theColumns->AddL(TDbCol(KPersistColName_LimitedDiscoverable,		EDbColBit));
       
   333 	theColumns->AddL(TDbCol(KPersistColName_AFHChannelAssessmentMode,	EDbColBit));
       
   334 	theColumns->AddL(TDbCol(KPersistColName_AcceptPairedOnlyMode,		EDbColBit));
       
   335 	User::LeaveIfError(iDB.CreateTable(KPersistTable, *theColumns));
       
   336 
       
   337 	CleanupStack::PopAndDestroy(theColumns);
       
   338 	}
       
   339 
       
   340 void CBTRegistry::CreateDeviceTableL()
       
   341 /**
       
   342 	Create the table with all that is necessary to store details about remote devices
       
   343 	
       
   344 	To provide better CoD searching than the underlying SQL supports
       
   345 	this table uses >1 column for device class of remote device
       
   346 	
       
   347 	This also allows for future versions of the CoD field in the BT Spec
       
   348 **/
       
   349 	{
       
   350 	LOG_FUNC
       
   351 	CDbColSet* theColumns = CDbColSet::NewLC();
       
   352 
       
   353 	theColumns->AddL(TDbCol(KColName_ProcessSID,			EDbColUint32));	//SID of process adding record
       
   354 	theColumns->AddL(TDbCol(KColName_DeviceAddress,			EDbColText8));	// Binary not allowed in SQL
       
   355 	theColumns->AddL(TDbCol(KDeviceColName_CoD_MajorDev,	EDbColUint32));
       
   356 	theColumns->AddL(TDbCol(KDeviceColName_CoD_MinorDev,	EDbColUint32));
       
   357 	theColumns->AddL(TDbCol(KDeviceColName_CoD_Service,		EDbColUint32));
       
   358 	theColumns->AddL(TDbCol(KDeviceColName_BluetoothName,	EDbColText8, KMaxBluetoothNameLen));	// keep UTF8
       
   359 	theColumns->AddL(TDbCol(KDeviceColName_FriendlyName,	EDbColText16, KMaxBluetoothNameLen));	// possible UNICODE?
       
   360 	theColumns->AddL(TDbCol(KDeviceColName_LinkKey,			EDbColText8));	// Binary not allowed in SQL
       
   361 	theColumns->AddL(TDbCol(KDeviceColName_PassKey,			EDbColText8));	// Binary not allowed in SQL	
       
   362 	theColumns->AddL(TDbCol(KDeviceColName_PageScanMode,	EDbColUint8));
       
   363 	theColumns->AddL(TDbCol(KDeviceColName_PageScanRepMode,	EDbColUint8));
       
   364 	theColumns->AddL(TDbCol(KDeviceColName_PageScanPeriodMode,	EDbColUint8));
       
   365 	theColumns->AddL(TDbCol(KDeviceColName_LastSeen,		EDbColInt64));
       
   366 	theColumns->AddL(TDbCol(KDeviceColName_LastUsed,		EDbColInt64));
       
   367 	theColumns->AddL(TDbCol(KDeviceColName_GlobalSecSecurity,	EDbColUint8));
       
   368 	theColumns->AddL(TDbCol(KDeviceColName_GlobalSecPasskeyLen,	EDbColUint32));
       
   369 	theColumns->AddL(TDbCol(KDeviceColName_LinkKeyType,		EDbColUint8));
       
   370 	theColumns->AddL(TDbCol(KDeviceColName_UiCookie,		EDbColText8)); // Can only simulate "bit-masked" searching in SQL if stored as text
       
   371 
       
   372 	User::LeaveIfError(iDB.CreateTable(KDeviceTable, *theColumns));
       
   373 
       
   374 	CleanupStack::PopAndDestroy(theColumns);
       
   375 	}
       
   376 
       
   377 void CBTRegistry::CreateMetaTableL()
       
   378 /**
       
   379 	Stores useful information about the database
       
   380 	Version - useful for attempting to see if we can restore an old db
       
   381 	Originating process
       
   382 **/
       
   383 	{
       
   384 	LOG_FUNC
       
   385 	CDbColSet* theColumns = CDbColSet::NewLC();
       
   386 
       
   387 	theColumns->AddL(TDbCol(KMetaColName_VersionMajor,	EDbColUint32));
       
   388 	theColumns->AddL(TDbCol(KMetaColName_VersionMinor,	EDbColUint32));
       
   389 	theColumns->AddL(TDbCol(KColName_ProcessSID,		EDbColUint32));	//SID of process adding record
       
   390 
       
   391 	User::LeaveIfError(iDB.CreateTable(KMetaTable, *theColumns));
       
   392 
       
   393 	CleanupStack::PopAndDestroy(theColumns);
       
   394 
       
   395 	SetMetaDataL();
       
   396 	}
       
   397 
       
   398 void CBTRegistry::CreateCSYTableL()
       
   399 /**
       
   400 	Create the table with all that is necessary to store details about virtual serial ports
       
   401 **/
       
   402 	{
       
   403 	LOG_FUNC
       
   404 	CDbColSet* theColumns = CDbColSet::NewLC();
       
   405 
       
   406 	theColumns->AddL(TDbCol(KColName_ProcessSID,		EDbColUint32));	//SID of process adding record
       
   407 	theColumns->AddL(TDbCol(KBTCOMMColName_Port,		EDbColUint32));	
       
   408 	theColumns->AddL(TDbCol(KColName_DeviceAddress,		EDbColText8));	//Device address
       
   409 	theColumns->AddL(TDbCol(KBTCOMMColName_ServiceUUID,	EDbColText8));	//SDP UUID - 16bytes
       
   410 	theColumns->AddL(TDbCol(KBTCOMMColName_Security,	EDbColUint8));	//Security
       
   411 	theColumns->AddL(TDbCol(KBTCOMMColName_ServiceName,	EDbColText));	//ServiceName
       
   412 
       
   413 	User::LeaveIfError(iDB.CreateTable(KCSYTable, *theColumns));
       
   414 
       
   415 	CleanupStack::PopAndDestroy(theColumns);
       
   416 	}
       
   417 
       
   418 
       
   419 TDbColNo CBTRegistry::ColumnNoL(const TDesC& aColName, const RDbRowSet& aRowSet)
       
   420 /**
       
   421 Looks up column names and returns the column number
       
   422 
       
   423 	@param	aColName the name of the column
       
   424 	@param	aRowSet	the rowset in which to find the column
       
   425 	@return the column number with aColName
       
   426 **/
       
   427 	{
       
   428 	LOG_FUNC
       
   429 	// get the schema from the table - we own this
       
   430 #ifdef _DEBUG
       
   431 	CDbColSet* schema = NULL;
       
   432 	TRAPD(err, schema = aRowSet.ColSetL());
       
   433 	if(err == KErrNoMemory)
       
   434 		{
       
   435 		User::Leave(err);
       
   436 		}
       
   437 	//This __ASSERT_DEBUG is here to catch any 'Leaves'
       
   438 	//in RDbRowSet::ColSetL other than that\those using
       
   439 	//KErrNoMemory.
       
   440 	__ASSERT_DEBUG(err == KErrNone, Panic(EBTManColSetError));
       
   441 #else
       
   442 	CDbColSet* schema = aRowSet.ColSetL(); // no need to push onto cleanup
       
   443 #endif
       
   444 	// get the column number, based on name
       
   445 	TDbColNo column = schema->ColNo(aColName);
       
   446 	delete schema;
       
   447 	return column;
       
   448 	}
       
   449 
       
   450 
       
   451 
       
   452 TBool CBTRegistry::DevicePresentL(const TBTDevAddr& aAddress)
       
   453 /**
       
   454 	Checks to see if a device is present in the Registry
       
   455 	@param	aAddress	The key to finding a device
       
   456 	@return True if Device is present, false if not
       
   457 **/
       
   458 	{
       
   459 	LOG_FUNC
       
   460 	// form an SQL query for the device with address aAddress
       
   461 	RBTDbQuery query;
       
   462 	CleanupClosePushL(query);
       
   463 	query.FindDeviceL(aAddress);
       
   464 
       
   465 	TDbBookmark dummy;
       
   466 	RDbView* view = NULL;
       
   467 
       
   468 	// open the view with that SQL query
       
   469 	view = OpenViewL(query, dummy);	// uses a private view...
       
   470 	CleanupCloseDeletePushL(view);
       
   471 
       
   472 	TInt count = view->CountL();
       
   473 	
       
   474 	__ASSERT_ALWAYS(count <= 1, Panic(ETooManyRemoteDeviceEntries));
       
   475 
       
   476 	CleanupStack::PopAndDestroy(2, &query); // view and query
       
   477 	return (count!=0);
       
   478 	}
       
   479 
       
   480 void CBTRegistry::CreateDeviceL(const CBTDevice& aDetails, TBool aStoreUiCookie, const TSecureId& aClientSID)
       
   481 /**
       
   482 	Add a new record into the DB
       
   483 
       
   484 	@param	aDetails	The new device details to add
       
   485 	@param	aClientUid	The ID of the process adding the new record
       
   486 	@leave	KErrCorrupt if device to add is not valid
       
   487 	@leave	KErrAlreadyExists if device to add is already present
       
   488 **/
       
   489 	{
       
   490 	LOG_FUNC
       
   491 	if (!aDetails.IsValidBDAddr())
       
   492 		{
       
   493 		User::Leave(KErrCorrupt);
       
   494 		}
       
   495 
       
   496 	if (DevicePresentL(aDetails.BDAddr()))
       
   497 		{
       
   498 		User::Leave(KErrAlreadyExists);
       
   499 		}
       
   500 
       
   501 	RDbTable* table = OpenDeviceTableL();
       
   502 	CleanupCloseDeletePushL(table);
       
   503 
       
   504 	table->InsertL();
       
   505 	table->SetColL(ColumnNoL(KColName_DeviceAddress, *table), aDetails.BDAddr().Des());
       
   506 
       
   507 	table->SetColL(ColumnNoL(KColName_ProcessSID, *table), aClientSID);
       
   508 
       
   509 	// got some initial details; stick them in now...
       
   510 	SetDeviceL(*table, aDetails, !aStoreUiCookie);	// does the remaining columns
       
   511 	CleanupStack::PopAndDestroy(table);
       
   512 	}
       
   513 
       
   514 void CBTRegistry::UnpairL(RDbRowSet& aRowSet)
       
   515 /**
       
   516 	Unpairs a set of devices
       
   517 
       
   518 	@pre	A rowset constraining the view to a single device
       
   519 	@param	aRowSet	The set of records to unpair
       
   520 	@see    DBMS for leave codes
       
   521 **/
       
   522 	{
       
   523 	LOG_FUNC
       
   524 	aRowSet.UpdateL();
       
   525 	aRowSet.SetColNullL(ColumnNoL(KDeviceColName_LinkKey, aRowSet));
       
   526 	aRowSet.SetColNullL(ColumnNoL(KDeviceColName_PassKey, aRowSet));
       
   527 	aRowSet.SetColNullL(ColumnNoL(KDeviceColName_LinkKeyType, aRowSet));
       
   528 	
       
   529 	CleanPutL(aRowSet);
       
   530 	}
       
   531 
       
   532 void CBTRegistry::UnpairViewL(RDbRowSet& aRowSet)
       
   533 /**
       
   534 	Unpairs all sets of devices in the supplied rowset
       
   535 
       
   536 	@pre	A rowset constraining the view 
       
   537 	@param	aRowSet	The set of records to unpair
       
   538 	@see    DBMS for leave codes
       
   539 **/
       
   540 	{
       
   541 	LOG_FUNC
       
   542 	aRowSet.FirstL();
       
   543 	TInt c = aRowSet.CountL();
       
   544 	for (TInt i=0; i<c; i++)
       
   545 		{
       
   546 		UnpairL(aRowSet);
       
   547 		aRowSet.NextL();
       
   548 		}
       
   549 	}
       
   550 
       
   551 void CBTRegistry::UpdateDeviceL(RDbRowSet& aRowSet, const CBTDevice& aDetails)
       
   552 /**
       
   553 	Given a rowset (from a previous find) and
       
   554 	mark the rowset for update, and make the changes
       
   555 
       
   556 	@param	aRowSet	The set of rows to update - typically one row...
       
   557 **/
       
   558 	{
       
   559 	LOG_FUNC
       
   560 	aRowSet.UpdateL();
       
   561 	SetDeviceL(aRowSet, aDetails);
       
   562 	}
       
   563 
       
   564 void CBTRegistry::UpdateNameL(const TBTDevAddr& aAddress,
       
   565 							  const TDesC8& aName,
       
   566 							  TBTManServerRequest aRequest)
       
   567 /**
       
   568 	Update the name of a device - either friendly or Bluetooth name
       
   569 
       
   570 	@param	aAddress    The device to update
       
   571 	@param  aName	    The new name
       
   572 	@param  aRequest	Determines the type of name to change
       
   573 
       
   574 	Could change this so subsession opens the rowset and just gives that to this
       
   575 **/
       
   576 	{
       
   577 	LOG_FUNC
       
   578 	// Find the row
       
   579 	RBTDbQuery deviceQuery;
       
   580 	CleanupClosePushL(deviceQuery);
       
   581 	deviceQuery.FindDeviceL(aAddress);
       
   582 
       
   583 	TDbBookmark dummy;
       
   584 
       
   585 	RDbView* view = OpenViewL(deviceQuery, dummy);
       
   586 	CleanupCloseDeletePushL(view);
       
   587 
       
   588 	view->UpdateL();
       
   589 
       
   590 	switch (aRequest)
       
   591 		{
       
   592 	case EBTRegistryModifyFriendlyName:
       
   593 		{
       
   594 		TBuf<KMaxFriendlyNameLen> temp;
       
   595 		User::LeaveIfError(CnvUtfConverter::ConvertToUnicodeFromUtf8(temp,aName));
       
   596 		view->SetColL(ColumnNoL(KDeviceColName_FriendlyName, *view), temp);
       
   597 		break;
       
   598 		}
       
   599 
       
   600 	case EBTRegistryModifyBluetoothName:
       
   601 		{
       
   602 		view->SetColL(ColumnNoL(KDeviceColName_BluetoothName, *view), aName);
       
   603 		break;
       
   604 		}
       
   605 	default:
       
   606 		Panic(EBadNameToUpdate);
       
   607 		}
       
   608 	CleanPutL(*view);
       
   609 	CleanupStack::PopAndDestroy(2, &deviceQuery);	// view and deviceQuery
       
   610 	}
       
   611 
       
   612 void CBTRegistry::UpdateLocalDeviceL(const TBTLocalDevice& aLocalDevice)
       
   613 /**
       
   614 	@param	aLocalDevice The new settings
       
   615 **/
       
   616 	{
       
   617 	LOG_FUNC
       
   618 	// obliterate what's there
       
   619 	RDbTable* table = OpenPersistTableL();
       
   620 	CleanupCloseDeletePushL(table);	
       
   621 
       
   622 	TInt count = table->CountL();
       
   623 	__ASSERT_DEBUG(count <=1, Panic(ETooManyLocalDeviceEntries));
       
   624 	if (!count)
       
   625 		{
       
   626 		// we need to insert the one and only row as this is a fresh table
       
   627 		table->InsertL();
       
   628 		}
       
   629 	else
       
   630 		{
       
   631 		// go to the only row
       
   632 		TBool success = table->FirstL();
       
   633 		if (!success)
       
   634 			{
       
   635 			LOG(_L("BT Registry DB Local Device Table (Persist Table) CORRUPT!"));
       
   636 			User::Leave(KErrEof);
       
   637 			}
       
   638 
       
   639 		table->UpdateL();
       
   640 		}
       
   641 
       
   642 	if (aLocalDevice.IsValidAddress())
       
   643 		table->SetColL(ColumnNoL(KColName_DeviceAddress, *table),
       
   644 					aLocalDevice.Address().Des());
       
   645 
       
   646 	if (aLocalDevice.IsValidDeviceClass())
       
   647 		table->SetColL(ColumnNoL(KPersistColName_CoD, *table),
       
   648 					static_cast<TUint>(aLocalDevice.DeviceClass()));
       
   649 
       
   650 	if (aLocalDevice.IsValidDeviceName())
       
   651 		table->SetColL(ColumnNoL(KPersistColName_LocalName, *table),
       
   652 					aLocalDevice.DeviceName());
       
   653 
       
   654 	if (aLocalDevice.IsValidScanEnable())
       
   655 		table->SetColL(ColumnNoL(KPersistColName_ScanEnable, *table),
       
   656 					static_cast<TUint>(aLocalDevice.ScanEnable()));
       
   657 
       
   658 	if (aLocalDevice.IsValidPowerSetting())
       
   659 		table->SetColL(ColumnNoL(KPersistColName_PowerSettings, *table),
       
   660 					static_cast<TUint>(aLocalDevice.PowerSetting()));
       
   661 
       
   662 	if (aLocalDevice.IsValidAFHChannelAssessmentMode())
       
   663 		table->SetColL(ColumnNoL(KPersistColName_AFHChannelAssessmentMode, *table),
       
   664 					static_cast<TBool>(aLocalDevice.AFHChannelAssessmentMode()));
       
   665 
       
   666 	if (aLocalDevice.IsValidLimitedDiscoverable())
       
   667 		table->SetColL(ColumnNoL(KPersistColName_LimitedDiscoverable, *table),
       
   668 					static_cast<TBool>(aLocalDevice.LimitedDiscoverable()));
       
   669 
       
   670 	if (aLocalDevice.IsValidAcceptPairedOnlyMode())
       
   671 		table->SetColL(ColumnNoL(KPersistColName_AcceptPairedOnlyMode, *table),
       
   672 					static_cast<TBool>(aLocalDevice.AcceptPairedOnlyMode()));
       
   673 
       
   674 	CleanPutL(*table);
       
   675 	CleanupStack::PopAndDestroy(table);
       
   676 	}
       
   677 
       
   678 void CBTRegistry::SetMetaDataL()
       
   679 /**
       
   680 	Set the values for the MetaData Table
       
   681 **/
       
   682 	{
       
   683 	LOG_FUNC
       
   684 	// put defaults in
       
   685 	RDbTable* table = OpenTableL(KMetaTable);
       
   686 	CleanupCloseDeletePushL(table);
       
   687 	
       
   688 #ifdef _DEBUG
       
   689 	TInt c=0;
       
   690 	TRAP_IGNORE(c=table->CountL());
       
   691 	__ASSERT_DEBUG(c==0, Panic(EMetaTableBroken));
       
   692 #endif
       
   693 
       
   694 	table->InsertL();
       
   695 
       
   696 	table->SetColL(ColumnNoL(KColName_ProcessSID, *table), RProcess().SecureId());
       
   697 
       
   698 	table->SetColL(ColumnNoL(KMetaColName_VersionMajor, *table), KRegistryDBVersionMajor);
       
   699 	table->SetColL(ColumnNoL(KMetaColName_VersionMinor, *table), KRegistryDBVersionMinor);
       
   700 
       
   701 	CleanPutL(*table);
       
   702 	CleanupStack::PopAndDestroy(table);
       
   703 	}
       
   704 
       
   705 void CBTRegistry::SetDeviceL(RDbRowSet& aRowSet, const CBTDevice& aDetails, TBool aIgnoreUiCookie)
       
   706 /**
       
   707 	Set the values for the device record if the Details are valid
       
   708 
       
   709 	@param	aRowSet		The rowset to adjust...typically one row
       
   710 	@param 	aDetails	The new details
       
   711 **/
       
   712 	{
       
   713 	LOG_FUNC
       
   714 	if (aDetails.AsNamelessDevice().IsValidPageScanMode())
       
   715 		{
       
   716 		aRowSet.SetColL(ColumnNoL(KDeviceColName_PageScanMode, aRowSet), static_cast<TUint>(aDetails.AsNamelessDevice().PageScanMode()));
       
   717 		}
       
   718 	if (aDetails.AsNamelessDevice().IsValidPageScanRepMode())
       
   719 		{
       
   720 		aRowSet.SetColL(ColumnNoL(KDeviceColName_PageScanRepMode, aRowSet), static_cast<TUint>(aDetails.AsNamelessDevice().PageScanRepMode()));
       
   721 		}
       
   722 	if (aDetails.AsNamelessDevice().IsValidPageScanPeriodMode())
       
   723 		{
       
   724 		aRowSet.SetColL(ColumnNoL(KDeviceColName_PageScanPeriodMode, aRowSet), static_cast<TUint>(aDetails.AsNamelessDevice().PageScanPeriodMode()));
       
   725 		}
       
   726 	if (aDetails.IsValidDeviceClass())
       
   727 		{
       
   728 		const TBTDeviceClass& cod = aDetails.DeviceClass();
       
   729 		
       
   730 		aRowSet.SetColL(ColumnNoL(KDeviceColName_CoD_MajorDev, aRowSet), static_cast<TUint>(cod.MajorDeviceClass()));
       
   731 		aRowSet.SetColL(ColumnNoL(KDeviceColName_CoD_MinorDev, aRowSet), static_cast<TUint>(cod.MinorDeviceClass()));
       
   732 		aRowSet.SetColL(ColumnNoL(KDeviceColName_CoD_Service, aRowSet), static_cast<TUint>(cod.MajorServiceClass()));
       
   733 		}
       
   734 	if (aDetails.IsValidDeviceName())
       
   735 		{
       
   736 		aRowSet.SetColL(ColumnNoL(KDeviceColName_BluetoothName, aRowSet), aDetails.DeviceName());
       
   737 		}
       
   738 	if (aDetails.IsValidFriendlyName())
       
   739 		{
       
   740 		aRowSet.SetColL(ColumnNoL(KDeviceColName_FriendlyName, aRowSet), aDetails.FriendlyName());
       
   741 		}
       
   742 	if (aDetails.IsValidUsed())
       
   743 		{
       
   744 		aRowSet.SetColL(ColumnNoL(KDeviceColName_LastUsed, aRowSet), aDetails.Used().Int64());
       
   745 		}
       
   746 	if (aDetails.IsValidSeen())
       
   747 		{
       
   748 		aRowSet.SetColL(ColumnNoL(KDeviceColName_LastSeen, aRowSet), aDetails.Seen().Int64());
       
   749 		}
       
   750 	if (aDetails.IsValidGlobalSecurity())
       
   751 		{
       
   752 		aRowSet.SetColL(ColumnNoL(KDeviceColName_GlobalSecSecurity, aRowSet), static_cast<TUint>(aDetails.GlobalSecurity().SecurityValue()));
       
   753 		aRowSet.SetColL(ColumnNoL(KDeviceColName_GlobalSecPasskeyLen, aRowSet), static_cast<TUint>(aDetails.GlobalSecurity().PasskeyMinLength()));
       
   754 		}
       
   755 	if (aDetails.IsValidLinkKey())
       
   756 		{
       
   757 		aRowSet.SetColL(ColumnNoL(KDeviceColName_LinkKey, aRowSet), aDetails.LinkKey());
       
   758 		aRowSet.SetColL(ColumnNoL(KDeviceColName_LinkKeyType, aRowSet), aDetails.LinkKeyType());
       
   759 		}
       
   760 	else
       
   761 		{
       
   762 		LOG(_L("Sec\tNot setting link key"))
       
   763 		}
       
   764 	if (aDetails.IsValidPassKey())
       
   765 		{
       
   766 		aRowSet.SetColL(ColumnNoL(KDeviceColName_PassKey, aRowSet), aDetails.PassKey());
       
   767 		}
       
   768 	if (aDetails.IsValidUiCookie() && !aIgnoreUiCookie)
       
   769 		{
       
   770 		static const TUint8 KCookieBinaryRepresentationWidth = 32; // 32bits encoded as binary string.
       
   771 		TBuf8<KCookieBinaryRepresentationWidth> textCookieValue;
       
   772 		textCookieValue.NumFixedWidth(aDetails.UiCookie(), EBinary, KCookieBinaryRepresentationWidth);
       
   773 		aRowSet.SetColL(ColumnNoL(KDeviceColName_UiCookie, aRowSet), textCookieValue);
       
   774 		}
       
   775 	
       
   776 	CleanPutL(aRowSet);
       
   777 	}
       
   778 
       
   779 void CBTRegistry::CleanPutL(RDbRowSet& aRowSet)
       
   780 /**
       
   781 	Try to put the changes into a RowSet
       
   782 	If this fails cancel the update and reset
       
   783 	Then re-leave
       
   784 **/
       
   785 	{
       
   786 	LOG_FUNC
       
   787 	TRAPD(dbResult, aRowSet.PutL());
       
   788 
       
   789 	if (dbResult!=KErrNone)
       
   790 		{
       
   791 		aRowSet.Cancel();
       
   792 		aRowSet.Reset();
       
   793 		User::Leave(KErrCorrupt); // this will complete the client message
       
   794 		}
       
   795 	}
       
   796 
       
   797 RDbView* CBTRegistry::OpenDeviceL(const TBTDevAddr& aAddr, TDbBookmark& aBookmark)
       
   798 /**
       
   799 	Open a view onto a given record in the Registry
       
   800 	@return a bookmark to the entry should the caller want it
       
   801 **/
       
   802 	{
       
   803 	LOG_FUNC
       
   804 	RBTDbQuery query;
       
   805 	CleanupClosePushL(query);
       
   806 	query.FindDeviceL(aAddr);
       
   807 
       
   808 	// open the device
       
   809 	RDbView* view = NULL;
       
   810 	view = OpenViewL(query, aBookmark);
       
   811 
       
   812 	CleanupCloseDeletePushL(view);
       
   813 
       
   814 #ifdef _DEBUG
       
   815 	TInt c=0;
       
   816 	TRAP_IGNORE(c=view->CountL());
       
   817 	__ASSERT_DEBUG(c<=1, Panic(ETooManyRemoteDeviceEntries));
       
   818 #endif
       
   819 
       
   820 	CleanupStack::Pop(view); // view (pass ownership)
       
   821 	CleanupStack::PopAndDestroy(&query); // query
       
   822 	return view;
       
   823 	}
       
   824 
       
   825 RDbView* CBTRegistry::OpenViewL(const TDesC& aSQLQuery, TDbBookmark& aBookmark)
       
   826 /**
       
   827 	Returns a view resulting from the execution of the aSQLQuery
       
   828 	Update aBookmark to be the beginning of the view
       
   829 **/
       
   830 	{
       
   831 	LOG_FUNC
       
   832 	RDbView* view = new (ELeave) RDbView;
       
   833 	CleanupCloseDeletePushL(view);	
       
   834 
       
   835 	// open the view based on the SQL query
       
   836 	User::LeaveIfError(view->Prepare(iDB, aSQLQuery));
       
   837 	// could separate this into separate Evaluates, but expected to be smallish DB
       
   838 	User::LeaveIfError(view->EvaluateAll());
       
   839 
       
   840 	// move to first row, and bookmark it
       
   841 	view->FirstL();
       
   842 	aBookmark = view->Bookmark();	// set bookmark in case user would like it
       
   843 
       
   844 	CleanupStack::Pop(view);
       
   845 	return view;	// returns ownership
       
   846 	}
       
   847 
       
   848 RDbView* CBTRegistry::OpenViewL(const RBTDbQuery& aQuery, TDbBookmark& aBookmark)
       
   849 /**
       
   850 	Overload allowing just a RBTDbQuery to be executed - hides the SQL query
       
   851 **/
       
   852 	{
       
   853 	LOG_FUNC
       
   854 	return OpenViewL(aQuery.QueryBuf(), aBookmark);
       
   855 	}
       
   856 
       
   857 void CBTRegistry::IncrementRowL(RDbRowSet& aRowSet, TDbBookmark& aBookmark)
       
   858 /**
       
   859 	Move to the next row in a RowSet and return a bookmark should the caller be interested
       
   860 **/
       
   861 	{
       
   862 	LOG_FUNC
       
   863 	aRowSet.NextL();	// move onto next row for next get
       
   864 	aBookmark = aRowSet.Bookmark();
       
   865 	}
       
   866 
       
   867 void CBTRegistry::GetRowL(RDbRowSet& aRowSet, const TDbBookmark& aBookmark)
       
   868 /**
       
   869 	Mark the rowset for reading
       
   870 **/
       
   871 	{
       
   872 	LOG_FUNC
       
   873 	if (!aRowSet.AtEnd())
       
   874 		{
       
   875 		aRowSet.GotoL(aBookmark);
       
   876 		aRowSet.GetL();		// get the row (which is a remote device on this table)
       
   877 		}
       
   878 	else
       
   879 		{
       
   880 		User::Leave(KErrEof);
       
   881 		}
       
   882 	}
       
   883 
       
   884 
       
   885 void CBTRegistry::GetNamelessDetailsL(TBTNamelessDevice& aDevice, 
       
   886 									  RDbRowSet& aRowSet, 
       
   887 									  TBool includeKeys)
       
   888 /**
       
   889 	Gets the next device (row) out of a rowset and puts them in a CBTDevice
       
   890 	The CBTDevice and its ownership is returned to the caller
       
   891 **/
       
   892 	{
       
   893 	LOG_FUNC
       
   894 	__ASSERT_DEBUG(!aRowSet.IsColNull(ColumnNoL(KColName_DeviceAddress, aRowSet)), Panic(ECorruptDeviceEntry));
       
   895 
       
   896 	TPtrC8 addrBuf(aRowSet.ColDes8(ColumnNoL(KColName_DeviceAddress, aRowSet)));
       
   897 	aDevice.SetAddress(static_cast<TBTDevAddr>(addrBuf));
       
   898 
       
   899 	TDbColNo column;
       
   900 
       
   901 	column = ColumnNoL(KDeviceColName_PageScanMode, aRowSet);
       
   902 	if (!aRowSet.IsColNull(column))
       
   903 		{
       
   904 		aDevice.SetPageScanMode(aRowSet.ColUint8(column));
       
   905 		}
       
   906 
       
   907 	column = ColumnNoL(KDeviceColName_PageScanPeriodMode, aRowSet);
       
   908 	if (!aRowSet.IsColNull(column))
       
   909 		{
       
   910 		aDevice.SetPageScanPeriodMode(aRowSet.ColUint8(column));
       
   911 		}
       
   912 
       
   913 	column = ColumnNoL(KDeviceColName_PageScanRepMode, aRowSet);
       
   914 	if (!aRowSet.IsColNull(column))
       
   915 		{
       
   916 		aDevice.SetPageScanRepMode(aRowSet.ColUint8(column));
       
   917 		}
       
   918 
       
   919 /*	column = ColumnNoL(KDeviceColName_CoD, aRowSet);
       
   920 	if (!aRowSet.IsColNull(column))
       
   921 		{
       
   922 		aDevice.SetDeviceClass(aRowSet.ColUint32(column));
       
   923 		}
       
   924 */
       
   925 	// all CoD columns must be set - just test one
       
   926 	column = ColumnNoL(KDeviceColName_CoD_MajorDev, aRowSet);
       
   927 	if (!aRowSet.IsColNull(column))
       
   928 		{
       
   929 		TUint majorDeviceClass = aRowSet.ColUint(column);
       
   930 
       
   931 		column = ColumnNoL(KDeviceColName_CoD_MinorDev, aRowSet);
       
   932 		TUint minorDeviceClass = aRowSet.ColUint(column);
       
   933 
       
   934 		column = ColumnNoL(KDeviceColName_CoD_Service, aRowSet);
       
   935 		TUint serviceClass = aRowSet.ColUint(column);
       
   936 		
       
   937 		aDevice.SetDeviceClass(TBTDeviceClass(static_cast<TUint16>(serviceClass),
       
   938 											  static_cast<TUint8>(majorDeviceClass),
       
   939 											  static_cast<TUint8>(minorDeviceClass)));
       
   940 		
       
   941 		}
       
   942 	
       
   943 	column = ColumnNoL(KDeviceColName_GlobalSecSecurity, aRowSet);
       
   944 	if (!aRowSet.IsColNull(column))
       
   945 		{
       
   946 		TBTDeviceSecurity devSec;
       
   947 		devSec.SetSecurityValue(aRowSet.ColUint8(column));
       
   948 		column = ColumnNoL(KDeviceColName_GlobalSecPasskeyLen, aRowSet);
       
   949 		devSec.SetPasskeyMinLength(aRowSet.ColUint32(column));
       
   950 				
       
   951 		aDevice.SetGlobalSecurity(devSec);
       
   952 		}
       
   953 
       
   954 	column = ColumnNoL(KDeviceColName_LinkKey, aRowSet);
       
   955 	TDbColNo typeColumn = ColumnNoL(KDeviceColName_LinkKeyType, aRowSet);
       
   956 
       
   957 	if (!aRowSet.IsColNull(column))
       
   958 		{
       
   959 		if(includeKeys)
       
   960 			{
       
   961 			TBTLinkKey linkKey;
       
   962 			linkKey.Copy(aRowSet.ColDes8(column));
       
   963 			aDevice.SetLinkKey(linkKey, static_cast<TBTLinkKeyType>(aRowSet.ColUint8(typeColumn)));
       
   964 			}
       
   965 		else
       
   966 			{
       
   967 			LOG(_L("Device paired but lack of capability to retrieve link key"));
       
   968 			aDevice.SetPaired(static_cast<TBTLinkKeyType>(aRowSet.ColUint8(typeColumn)));
       
   969 			}
       
   970 		}
       
   971 	else
       
   972 		{
       
   973 		LOG(_L("Sec\tDevice has NULL LinkKey column => Unpaired"))
       
   974 		}
       
   975 
       
   976 	column = ColumnNoL(KDeviceColName_PassKey, aRowSet);
       
   977 
       
   978 	if (!aRowSet.IsColNull(column))
       
   979 		{
       
   980 		if(includeKeys)
       
   981 			{
       
   982 			TBTPinCode passKey;
       
   983 			passKey.Copy(aRowSet.ColDes8(column));
       
   984 			aDevice.SetPassKey(passKey);
       
   985 			}
       
   986 		else
       
   987 			{
       
   988 			LOG(_L("Device has PIN code but lack of capability to retrieve PIN code"));
       
   989 			}
       
   990 		}
       
   991 	else
       
   992 		{
       
   993 		LOG(_L("Sec\tDevice has NULL PinCode column"))
       
   994 		}
       
   995 		
       
   996 	column = ColumnNoL(KDeviceColName_LastSeen, aRowSet);
       
   997 	if (!aRowSet.IsColNull(column))
       
   998 		{
       
   999 		aDevice.SetSeen(TTime(aRowSet.ColInt64(column)));
       
  1000 		}
       
  1001 
       
  1002 	column = ColumnNoL(KDeviceColName_LastUsed, aRowSet);
       
  1003 	if (!aRowSet.IsColNull(column))
       
  1004 		{
       
  1005 		aDevice.SetUsed(TTime(aRowSet.ColInt64(column)));
       
  1006 		}
       
  1007 	
       
  1008 	column = ColumnNoL(KDeviceColName_UiCookie, aRowSet);
       
  1009 	if (!aRowSet.IsColNull(column))
       
  1010 		{
       
  1011 		TPtrC8 cookieBuf(aRowSet.ColDes8(column));
       
  1012 		TLex8 lexer(cookieBuf);
       
  1013 		TUint32 cookieValue = 0;
       
  1014 		TInt err = lexer.Val(cookieValue, EBinary);
       
  1015 		if(err != KErrNone)
       
  1016 			{
       
  1017 			// discard the specific lexer errors, the fundemental issue
       
  1018 			// is that the device entry is corrupted in someway.
       
  1019 			User::Leave(KErrCorrupt);
       
  1020 			}
       
  1021 		aDevice.SetUiCookie(cookieValue);
       
  1022 		}
       
  1023 	}
       
  1024 
       
  1025 const TBTNamelessDevice* CBTRegistry::GetNextNamelessDeviceLC(RDbRowSet& aRowSet, 
       
  1026 															  TDbBookmark& aBookmark, 
       
  1027 															  TBool includeKeys)
       
  1028 /**
       
  1029 	Get the next row from the rowset; building and return TBTNamelessDevice via heap
       
  1030 **/
       
  1031 	{
       
  1032 	LOG_FUNC
       
  1033 	GetRowL(aRowSet, aBookmark);
       
  1034 	// there is a row to get, instantiate an object to receive details
       
  1035 	TBTNamelessDevice* device = new(ELeave) TBTNamelessDevice; // for passing ownership
       
  1036 	CleanupStack::PushL(device);
       
  1037 	GetNamelessDetailsL(*device, aRowSet, includeKeys);
       
  1038 	IncrementRowL(aRowSet, aBookmark);
       
  1039 	return device;
       
  1040 	}
       
  1041 
       
  1042 CBTDevice* CBTRegistry::GetNextDeviceL(RDbRowSet& aRowSet, 
       
  1043 											 TDbBookmark& aBookmark, 
       
  1044 											 TBool includeLinkKey)
       
  1045 /**
       
  1046 	Get the next row from the rowset; building and return CBTDevice via heap
       
  1047 **/
       
  1048 	{
       
  1049 	LOG_FUNC
       
  1050 	GetRowL(aRowSet, aBookmark);
       
  1051 	// there is a row to get, so instantiate an object to receive details
       
  1052 	CBTDevice* device = CBTDevice::NewLC();
       
  1053 	GetNamelessDetailsL(device->AsNamelessDevice(), aRowSet, includeLinkKey);
       
  1054 
       
  1055 	TDbColNo column = ColumnNoL(KDeviceColName_BluetoothName, aRowSet);
       
  1056 	if (!aRowSet.IsColNull(column))
       
  1057 		{
       
  1058 		device->SetDeviceNameL(aRowSet.ColDes8(column));
       
  1059 		}
       
  1060 
       
  1061 	column = ColumnNoL(KDeviceColName_FriendlyName, aRowSet);
       
  1062 	if (!aRowSet.IsColNull(column))
       
  1063 		{
       
  1064 		TBuf<KMaxFriendlyNameLen> unicodeBuf;
       
  1065 		unicodeBuf.Copy(aRowSet.ColDes(column));
       
  1066 		device->SetFriendlyNameL(unicodeBuf);
       
  1067 		}
       
  1068 	IncrementRowL(aRowSet, aBookmark);
       
  1069 	CleanupStack::Pop(device);
       
  1070 	return device;
       
  1071 	}
       
  1072 
       
  1073 const TUid CBTRegistry::CreatingProcessUidL(RDbRowSet& aRowSet)
       
  1074 /**
       
  1075 	@return	Value read from DB of the process that created a rowset
       
  1076 **/
       
  1077 	{
       
  1078 	LOG_FUNC
       
  1079 #ifdef _DEBUG
       
  1080 	TInt c=0;
       
  1081 	TRAP_IGNORE(c=aRowSet.CountL());
       
  1082 	__ASSERT_DEBUG(c==1, Panic(ETooManyRemoteDeviceEntries));
       
  1083 #endif
       
  1084 
       
  1085 	aRowSet.GetL();	// this makes the semantics of this function a bit odd...it leaves the rowset open for read
       
  1086 	TInt val = aRowSet.ColUint32(ColumnNoL(KColName_ProcessSID, aRowSet));
       
  1087 	return TUid::Uid(val);
       
  1088 	}
       
  1089 
       
  1090 
       
  1091 void CBTRegistry::DeleteViewL(RDbRowSet& aRowSet, TBool aDeleteAll, const TSecureId& aSecureId)
       
  1092 /**
       
  1093 	Delete all the rows in the set whose originating Id is the same as 
       
  1094 	aSecureId
       
  1095 	
       
  1096 	@param aRowSet The rowset whose records are to be deleted
       
  1097 	@param aDeleteAll If set to ETrue, all rows are deleted. If EFalse, only those
       
  1098 	rows whose SID value is same as aSecureId will be deleted.
       
  1099 	@param aSecureId The SID of the calling process.
       
  1100 **/
       
  1101 	{
       
  1102 	LOG_FUNC
       
  1103 	aRowSet.FirstL();
       
  1104 	TInt c = aRowSet.CountL();
       
  1105 	
       
  1106 	if(	c == 0 )
       
  1107 		{
       
  1108 		//	No rows, nothing to do
       
  1109 		return;
       
  1110 		}
       
  1111 		
       
  1112 	TDbColNo secureIdColNo=ColumnNoL(KColName_ProcessSID, aRowSet);
       
  1113 	//	There should always be a ProcessSID column present in the view
       
  1114 	__ASSERT_ALWAYS(secureIdColNo != KDbNullColNo, Panic(EColumnNotFound));
       
  1115 	
       
  1116 	for (TInt i=0; i<c; i++)
       
  1117 		{
       
  1118 		//	Retrieve the current row ready to be accessed
       
  1119 		aRowSet.GetL();
       
  1120 		if( aDeleteAll || (aRowSet.ColUint32(secureIdColNo) == aSecureId) )
       
  1121 			{
       
  1122 			aRowSet.DeleteL();
       
  1123 			}
       
  1124 		//	Regardless of the DeleteL or no DeleteL, the cursor remains
       
  1125 		//	in the same location, so we always need to call NextL.
       
  1126 		aRowSet.NextL();
       
  1127 		}
       
  1128 	// better try to compact now to avoid ballooning
       
  1129 	(void)iDB.Compact();
       
  1130 	}
       
  1131 
       
  1132 
       
  1133 TBTLocalDevice* CBTRegistry::GetLocalDeviceLC()
       
  1134 /**
       
  1135 	Get the single row pertaining to the local device
       
  1136 	Build and return a TBTLocalDevice
       
  1137 **/
       
  1138 	{
       
  1139 	LOG_FUNC
       
  1140 	TBTLocalDevice* device = new(ELeave) TBTLocalDevice; // for passing ownership
       
  1141 	CleanupStack::PushL(device);
       
  1142 
       
  1143 	RDbTable* table = OpenPersistTableL();
       
  1144 	CleanupCloseDeletePushL(table);
       
  1145 
       
  1146 #ifdef _DEBUG
       
  1147 	TInt c=0;
       
  1148 	TRAP_IGNORE(c=table->CountL());
       
  1149 	__ASSERT_DEBUG(c==1, Panic(ENotOneLocalDeviceEntry));
       
  1150 #endif
       
  1151 
       
  1152 
       
  1153 	TBool success = table->FirstL();	// go to only row in table
       
  1154 	if (!success)
       
  1155 		{
       
  1156 		LOG(_L("BT Registry DB Local Device Table (Persist Table) CORRUPT!"));
       
  1157 		User::Leave(KErrEof);
       
  1158 		}
       
  1159 
       
  1160 	table->GetL();		// mark for retrieval
       
  1161 
       
  1162 	TPtrC8 addrBuf(table->ColDes8(ColumnNoL(KColName_DeviceAddress, *table)));
       
  1163 	device->SetAddress(static_cast<TBTDevAddr>(addrBuf));
       
  1164 
       
  1165 	device->SetDeviceClass(table->ColUint32(ColumnNoL(KPersistColName_CoD, *table)));
       
  1166 	device->SetDeviceName(table->ColDes8(ColumnNoL(KPersistColName_LocalName, *table)));
       
  1167 	device->SetScanEnable(static_cast<THCIScanEnable>(table->ColUint8(ColumnNoL(KPersistColName_ScanEnable, *table))));
       
  1168 	device->SetPowerSetting(table->ColUint8(ColumnNoL(KPersistColName_PowerSettings, *table)));
       
  1169 	device->SetAFHChannelAssessmentMode(table->ColUint8(ColumnNoL(KPersistColName_AFHChannelAssessmentMode, *table)));
       
  1170 	device->SetLimitedDiscoverable(table->ColUint8(ColumnNoL(KPersistColName_LimitedDiscoverable, *table)));
       
  1171 	device->SetAcceptPairedOnlyMode(table->ColUint8(ColumnNoL(KPersistColName_AcceptPairedOnlyMode, *table)));
       
  1172 	CleanupStack::PopAndDestroy(table); //table
       
  1173 	return device;
       
  1174 	}
       
  1175 
       
  1176 const TBTCommPortSettings* CBTRegistry::GetCommPortSettingsLC(const TBTCommPortSettings& aSettings)
       
  1177 /**
       
  1178 	Get the virtual serial port settings for the port referred to in aSettings
       
  1179 **/
       
  1180 	{
       
  1181 	LOG_FUNC
       
  1182 	TBTCommPortSettings* settings = new(ELeave) TBTCommPortSettings; // for passing ownership
       
  1183 	CleanupStack::PushL(settings);
       
  1184 
       
  1185 	RDbView* view = OpenCommPortLC(aSettings);
       
  1186 
       
  1187 	// mark for retrieval
       
  1188 	view->GetL();
       
  1189 	// get the unit number
       
  1190 	settings->SetPort(aSettings.Port());
       
  1191 	// get the device address
       
  1192 	TPtrC8 addrBuf(view->ColDes8(ColumnNoL(KColName_DeviceAddress, *view)));
       
  1193 	settings->SetBTAddr(static_cast<TBTDevAddr>(addrBuf));
       
  1194 
       
  1195 	// get the uuid
       
  1196 	TUUID uuid;
       
  1197 	uuid.SetL(view->ColDes8(ColumnNoL(KBTCOMMColName_ServiceUUID, *view)));
       
  1198 	settings->SetUUID(uuid);
       
  1199 
       
  1200 	// get the service uuid and name
       
  1201 	settings->SetSecurityLevel(view->ColUint8(ColumnNoL(KBTCOMMColName_Security, *view)));
       
  1202 	settings->SetName(view->ColDes(ColumnNoL(KBTCOMMColName_ServiceName, *view)));
       
  1203 
       
  1204 	CleanupStack::PopAndDestroy(view); //closes view
       
  1205 	// don't pop settings - C function
       
  1206 	return settings;	
       
  1207 	}
       
  1208 
       
  1209 void CBTRegistry::PutCommPortSettingsInTableL(RDbRowSet& aRowSet,
       
  1210 											  const TBTCommPortSettings& aSettings) 
       
  1211 /**
       
  1212 	Update the port settings
       
  1213 **/
       
  1214 	{
       
  1215 	LOG_FUNC
       
  1216 	aRowSet.SetColL(ColumnNoL(KBTCOMMColName_Port, aRowSet), aSettings.Port());
       
  1217 	aRowSet.SetColL(ColumnNoL(KColName_DeviceAddress, aRowSet), aSettings.BDAddr().Des());
       
  1218 	aRowSet.SetColL(ColumnNoL(KBTCOMMColName_ServiceUUID, aRowSet), aSettings.UUID().Des());
       
  1219 	aRowSet.SetColL(ColumnNoL(KBTCOMMColName_Security, aRowSet), static_cast<TUint>(aSettings.SecurityLevel()));
       
  1220 	aRowSet.SetColL(ColumnNoL(KBTCOMMColName_ServiceName, aRowSet), aSettings.Name());
       
  1221 
       
  1222 	TRAPD(err,aRowSet.PutL());
       
  1223 	if (err!=KErrNone)
       
  1224 		{
       
  1225 		aRowSet.Cancel();
       
  1226 		aRowSet.Reset();
       
  1227 		User::Leave(err);
       
  1228 		}
       
  1229 	}
       
  1230 
       
  1231 RDbView* CBTRegistry::OpenCommPortL(const TBTCommPortSettings& aSettings)
       
  1232 /**
       
  1233 	Return view of the com port specified
       
  1234 **/
       
  1235 	{
       
  1236 	LOG_FUNC
       
  1237 	// Form the SQL query based on the search criteria
       
  1238 	RBTDbQuery query;
       
  1239 	CleanupClosePushL(query);
       
  1240 	query.FindCommPortL(aSettings.Port());	// just search on port for now
       
  1241 
       
  1242 	// execute the SQL with dummy bookmark for now
       
  1243 	TDbBookmark dummy;
       
  1244 	RDbView* view = OpenViewL(query, dummy);
       
  1245 	CleanupCloseDeletePushL(view);
       
  1246 
       
  1247 	TInt count = view->CountL();
       
  1248 	
       
  1249 	if (!count)
       
  1250 		{
       
  1251 		User::Leave(KErrNotFound); // nothing in there: which may be OK!
       
  1252 		}
       
  1253 
       
  1254 	CleanupStack::Pop(view); // returns ownership - don't destroy
       
  1255 	CleanupStack::PopAndDestroy(&query); // query
       
  1256 	return view;
       
  1257 	}
       
  1258 
       
  1259 RDbView* CBTRegistry::OpenCommPortLC(const TBTCommPortSettings& aSettings)
       
  1260 	{
       
  1261 	LOG_FUNC
       
  1262 	RDbView* view = OpenCommPortL(aSettings);
       
  1263 	CleanupCloseDeletePushL(view);
       
  1264 	return view;
       
  1265 	}
       
  1266 
       
  1267 void CBTRegistry::DeleteCommPortSettingsL(RDbView& aCommPortSettingsView)
       
  1268 	{
       
  1269 	LOG_FUNC
       
  1270 	aCommPortSettingsView.DeleteL();
       
  1271 	}
       
  1272 
       
  1273 void CBTRegistry::AddCommPortSettingsL(const TBTCommPortSettings& aSettings, 
       
  1274 									   const TSecureId& aClientSID)
       
  1275 /**
       
  1276 	Add port settings row
       
  1277 	Create row and enter values in aSettings.
       
  1278 	THIS must only be called if the table has been checked for existing settings
       
  1279 **/
       
  1280 	{
       
  1281 	LOG_FUNC
       
  1282 #ifdef _DEBUG
       
  1283 	// check it's not already there
       
  1284 	TRAPD(err, OpenCommPortL(aSettings));
       
  1285 	ASSERT_DEBUG(err==KErrNotFound);
       
  1286 #endif
       
  1287 	
       
  1288 	RDbTable* table = OpenTableL(KCSYTable);
       
  1289 
       
  1290 	//create a record for this port, it wasn't there
       
  1291 	CleanupCloseDeletePushL(table);
       
  1292 	table->InsertL();
       
  1293 
       
  1294 	table->SetColL(ColumnNoL(KColName_ProcessSID, *table), aClientSID);	// store originating client ID
       
  1295 
       
  1296 	//put the port values in
       
  1297 	PutCommPortSettingsInTableL(*table, aSettings);
       
  1298 	CleanupStack::PopAndDestroy(table); //table
       
  1299 	}
       
  1300 
       
  1301 void CBTRegistry::UpdateCommPortSettingsL(RDbView& aView,
       
  1302 										  const TBTCommPortSettings& aSettings) 
       
  1303 /**
       
  1304 	Update the port settings
       
  1305 **/
       
  1306 	{
       
  1307 	LOG_FUNC
       
  1308 	aView.UpdateL();	// mark for update
       
  1309 	PutCommPortSettingsInTableL(aView, aSettings);
       
  1310 	}
       
  1311 
       
  1312 void CBTRegistry::DeleteCorruptRegistryL()
       
  1313 	{
       
  1314 	LOG_FUNC
       
  1315 	// The registry is corrupt so we need to create a new one and notify 
       
  1316 	// interested parties that all of the user's pairings may have been lost.
       
  1317 
       
  1318 	
       
  1319 	// close the database (if open)
       
  1320 	iDB.Close();
       
  1321 	TInt err = KErrNone;
       
  1322 
       
  1323 	// The RDbs method must be used to access the private data cage.
       
  1324 	err = iDBMSServer.DeleteDatabase(TBTRegistryDatabaseSecure()(), KBTManServerUid);  
       
  1325 	if(err)
       
  1326 		{
       
  1327 		LOG1(_L("UNSUCCESSFUL attempt to delete Corrupt BT Registry DB, error %d"), err);
       
  1328 		}
       
  1329 	else
       
  1330 		{
       
  1331 		LOG(_L("Corrupt BT Registry DB Deleted successfully"));
       
  1332 		// Use P&S to let UIs know that the registry may have lost some 
       
  1333 		// of the user's pairings.			
       
  1334 		RProperty::Set(KPropertyUidBluetoothCategory,
       
  1335 					   KPropertyKeyBluetoothCorruptRegistryReset,
       
  1336 					   User::TickCount());	   			   	
       
  1337 		}
       
  1338 	}
       
  1339 
       
  1340 void CBTRegistry::SetupDefaultRegistryL()
       
  1341 	{
       
  1342 	LOG_FUNC
       
  1343 	CreateMetaTableL();
       
  1344 	CreatePersistTableL();
       
  1345 	CreateCSYTableL();
       
  1346 	CreateDeviceTableL();
       
  1347 
       
  1348 	// now add default values for the tables: set all the states to 'unset'
       
  1349 	TBTLocalDevice defaultDevice;
       
  1350 	
       
  1351 	
       
  1352 	// Set up the defaults - these will get overwritten if there are appropriate values in the ini file
       
  1353 	defaultDevice.SetAddress(TBTDevAddr(0));
       
  1354 	defaultDevice.SetDeviceName(KDefaultLocalName);
       
  1355 	defaultDevice.SetScanEnable(EPageScanOnly);
       
  1356 	defaultDevice.SetLimitedDiscoverable(EFalse);
       
  1357 	defaultDevice.SetDeviceClass(0);
       
  1358 	// The registry is being kicked off with a default channel assessment 
       
  1359 	// mode setting of 'enabled'. This is the default if h/w supports 
       
  1360 	// channel assessment. If h/w does not support channel assessment,
       
  1361 	// this value becomes meaningless.
       
  1362 	// Any use of it to update h/w will be rejected.
       
  1363 	defaultDevice.SetAFHChannelAssessmentMode(ETrue);
       
  1364 	defaultDevice.SetAcceptPairedOnlyMode(EFalse);
       
  1365 	
       
  1366 	// Try and get any relevant parameters from the ini file
       
  1367 	TRAP_IGNORE(GetDefaultDeviceFromIniL(defaultDevice)); // Ignore any leaves as they cannot result in corruption of defaultDevice
       
  1368 
       
  1369 	UpdateLocalDeviceL(defaultDevice);
       
  1370 //#pragma message("defaults for persist table ini file/licensee?")
       
  1371 	}
       
  1372 
       
  1373 //
       
  1374 
       
  1375 TInt CBTRegistry::SetDeviceName(const TDesC& aDeviceName, TBTLocalDevice& aDevice)
       
  1376 	{
       
  1377 	// GetDefaultDeviceName() returns 16bit unicode, it need to be converted to 8bit UTF
       
  1378 	TBTDeviceName8 tempBuf;
       
  1379 	TInt error = CnvUtfConverter::ConvertFromUnicodeToUtf8(tempBuf, aDeviceName);
       
  1380 	if(error == KErrNone)
       
  1381 		{
       
  1382 		aDevice.SetDeviceName(tempBuf);
       
  1383 		}
       
  1384 	return error;
       
  1385 	}
       
  1386 
       
  1387 TBool CBTRegistry::SetDeviceNameFromIniFile(TBTLocalDevice& aDevice, RBuf8& bufPtr)
       
  1388 	{
       
  1389 	// Default so try the old mechanism.
       
  1390 	_LIT8(KVarDeviceName, "DeviceName");
       
  1391 	TPtrC8 devName(NULL, 0);
       
  1392 	if (FindVar(bufPtr, KVarDeviceName, devName) && devName.Length() <= KMaxBCBluetoothNameLen)
       
  1393 		{
       
  1394 		aDevice.SetDeviceName(devName);
       
  1395 		return ETrue;
       
  1396 		}
       
  1397 	return EFalse;
       
  1398 	}
       
  1399 
       
  1400 void CBTRegistry::GetDefaultDeviceFromIniL(TBTLocalDevice& aDevice)
       
  1401 	{
       
  1402 	LOG_FUNC
       
  1403 	// Try and open the .ini file and get any relavent parameters
       
  1404 	RFs	fileSession;
       
  1405 	User::LeaveIfError(fileSession.Connect());
       
  1406 	CleanupClosePushL(fileSession);
       
  1407 	
       
  1408 	_LIT(KIniDrive, "Z:");
       
  1409 	_LIT(KIniName, "DefaultBtReg.ini");
       
  1410 	TFileName	iniFileName;
       
  1411 	fileSession.PrivatePath(iniFileName);
       
  1412 	iniFileName.Insert(0, KIniDrive);
       
  1413 	iniFileName.Append(KIniName);
       
  1414 	
       
  1415 	RFile file;
       
  1416 	User::LeaveIfError(file.Open(fileSession, iniFileName, EFileStreamText|EFileRead));
       
  1417 	CleanupClosePushL(file);
       
  1418 	TInt data_size = 0;
       
  1419 	User::LeaveIfError(file.Size(data_size));
       
  1420 
       
  1421 	// All text encoding is narrow 8-bit ASCII as ini files generated on a PC will be encoded that way
       
  1422 	// and the bluetooth specification only allows 8-bit ASCII strings so there is no need to convert
       
  1423 	// between ASCII and Unicode and back again.
       
  1424 	RBuf8 bufPtr;
       
  1425 	bufPtr.CreateL(data_size);
       
  1426 	CleanupClosePushL(bufPtr);
       
  1427 	User::LeaveIfError(file.Read(bufPtr));
       
  1428 	
       
  1429 	// Any or all of the following variables may be specified in this ini file:
       
  1430 	//
       
  1431 	// Variable:								Variable Name:			Values Taken:
       
  1432 	//	Default device name						DeviceName				String
       
  1433 	//	Inquiry scan enabled by default			InquiryScan				0 or 1
       
  1434 	//	Page scanning enabled by default		PageScan				0 or 1
       
  1435 	//	Limited discovery enabled by default	LimitedDiscovery		0 or 1
       
  1436 	//	Default device class					DeviceClass				Integer (decimal format)
       
  1437 	//	Allow paired only eanabled by default	AcceptPairedOnlyMode	0 or 1
       
  1438 	//
       
  1439 	// Notes on file syntax:
       
  1440 	// - Variable Names are followed by an ‘=’ character and then the value taken.
       
  1441 	// - There are no whitespaces in variable names.
       
  1442 	// - Variable names may be followed by any number of whitespaces, until the first character of the value taken. Thereafter any whitespaces are considered part of the value until the end of line.
       
  1443 	// - All characters should be narrow (standard 8bit ASCII).
       
  1444 	// - Integers should contain only the standard characters 0 to 9.
       
  1445 	// - Boolean values should be indicated by a 0 or 1.
       
  1446 	// - Strings may contain whitespaces, but any at the beginning will be stripped.
       
  1447 	// - There is no need to terminate the file with a new line.
       
  1448 	// - Anything after "//" on a line is ignored as comments
       
  1449 	
       
  1450 
       
  1451 	// Remove any comments from the buffer
       
  1452 	TInt slashPos;
       
  1453 	TInt commentLength;
       
  1454 	TPtr8 comment(NULL, 0);
       
  1455 	_LIT8(KDoubleSlash, "//");
       
  1456 	while ((slashPos = bufPtr.Find(KDoubleSlash)) != KErrNotFound)
       
  1457 		{
       
  1458 		_LIT8(KEol, "\n");
       
  1459 		comment.Set(bufPtr.MidTPtr(slashPos));
       
  1460 		if ((commentLength = comment.Find(KEol)) == KErrNotFound)
       
  1461 			{
       
  1462 			commentLength = comment.Length(); // just to end of file
       
  1463 			}
       
  1464 		bufPtr.Replace(slashPos, commentLength, KNullDesC8);
       
  1465 		}
       
  1466 
       
  1467 	// Get the default device name
       
  1468 	// we try to get the device name from deviceattributes.ini as a first resort,
       
  1469 	// deviceattributes.ini is global device configuration for setting global data like the device name
       
  1470 
       
  1471 	CDeviceTypeInformation* deviceInfo = NULL;
       
  1472 	TRAPD(ret, deviceInfo = SysUtil::GetDeviceTypeInfoL());
       
  1473 	CleanupStack::PushL(deviceInfo);
       
  1474 	TPtrC16 deviceName;
       
  1475 
       
  1476 	if (ret == KErrNone)
       
  1477 		{
       
  1478 		ret = deviceInfo->GetDefaultDeviceName(deviceName);
       
  1479 		if (ret == KErrNone)
       
  1480 			{
       
  1481 			LEAVEIFERRORL(SetDeviceName(deviceName, aDevice));
       
  1482 			}
       
  1483 		else if (ret == CDeviceTypeInformation::KDefaultValue)
       
  1484 			{
       
  1485 			if(!SetDeviceNameFromIniFile(aDevice, bufPtr))
       
  1486 				{
       
  1487 				ret = SetDeviceName(deviceName, aDevice);
       
  1488 				__ASSERT_DEBUG(ret == KErrNone,Panic(ECorruptDeviceEntry));
       
  1489 				if(ret != KErrNone)
       
  1490 					{
       
  1491 					SetDeviceNameFromIniFile(aDevice, bufPtr);
       
  1492 					}
       
  1493 				}
       
  1494 			}
       
  1495 		else
       
  1496 			{
       
  1497 			SetDeviceNameFromIniFile(aDevice, bufPtr);
       
  1498 			}
       
  1499 		}
       
  1500 	else
       
  1501 		{ // if the above did not work, then use the old mechanism
       
  1502 		SetDeviceNameFromIniFile(aDevice, bufPtr);
       
  1503 		}
       
  1504 
       
  1505 	// Get default scan enabled status
       
  1506 	TInt scanStatus = aDevice.ScanEnable();
       
  1507 	TInt result = 0;
       
  1508 	_LIT8(KVarInquiryScan, "InquiryScan");
       
  1509 	if (FindVar(bufPtr, KVarInquiryScan, result))
       
  1510 		{
       
  1511 		if (result)
       
  1512 			scanStatus |= EInquiryScanOnly;
       
  1513 		else
       
  1514 			scanStatus &= ~EInquiryScanOnly;  		
       
  1515 		}
       
  1516 	
       
  1517 	_LIT8(KVarPageScan, "PageScan");
       
  1518 	if (FindVar(bufPtr, KVarPageScan, result))
       
  1519 		{
       
  1520 		if (result)
       
  1521 			scanStatus |= EPageScanOnly;
       
  1522 		else
       
  1523 			scanStatus &= ~EPageScanOnly;
       
  1524 		}
       
  1525 	aDevice.SetScanEnable(static_cast<THCIScanEnable>(scanStatus));
       
  1526 	
       
  1527 	
       
  1528 	// Get default limited discovery status
       
  1529 	_LIT8(KVarLimitedDiscovery, "LimitedDiscovery");
       
  1530 	if (FindVar(bufPtr, KVarLimitedDiscovery, result))
       
  1531 		{
       
  1532 		aDevice.SetLimitedDiscoverable(result);	
       
  1533 		}	
       
  1534 	
       
  1535 	
       
  1536 	// Get default device class
       
  1537 	_LIT8(KVarDeviceClass, "DeviceClass");
       
  1538 	if (FindVar(bufPtr, KVarDeviceClass, result))
       
  1539 		{
       
  1540 		aDevice.SetDeviceClass(result);	
       
  1541 		}	
       
  1542 			
       
  1543 	
       
  1544 	// Get default AFH channel assessment only mode
       
  1545 	_LIT8(KAFHChannelAssessmentMode, "AFHChannelAssessmentMode");
       
  1546 	if (FindVar(bufPtr, KAFHChannelAssessmentMode, result))
       
  1547 		{
       
  1548 		aDevice.SetAFHChannelAssessmentMode(result);
       
  1549 		}
       
  1550 			
       
  1551 	
       
  1552 	// Get default accept paired only mode
       
  1553 	_LIT8(KAcceptPairedOnlyMode, "AcceptPairedOnlyMode");
       
  1554 	if (FindVar(bufPtr, KAcceptPairedOnlyMode, result))
       
  1555 		{
       
  1556 		aDevice.SetAcceptPairedOnlyMode(result);
       
  1557 		}
       
  1558 
       
  1559 
       
  1560 	CleanupStack::PopAndDestroy(4, &fileSession); // deviceinfo, bufPtr, file, fileSession
       
  1561 	}
       
  1562 
       
  1563 TBool CBTRegistry::FindVar(const TDesC8& aPtr, const TDesC8 &aVarName, TPtrC8 &aResult) const
       
  1564 	{
       
  1565 	LOG_FUNC
       
  1566 	// Find the variable name
       
  1567 	TInt start=aPtr.Find(aVarName);
       
  1568 	if (start == KErrNotFound)
       
  1569 		{
       
  1570 		return EFalse;
       
  1571 		}
       
  1572 	
       
  1573 	// Now find the end of the value string (end of line or end of file)
       
  1574 	TPtrC8 value(aPtr.Mid(start));
       
  1575 	_LIT8(KEol, "\n");
       
  1576 	TInt length = value.Find(KEol);
       
  1577 	if (length != KErrNotFound)
       
  1578 		{
       
  1579 		if (value[length-1] == '\r')
       
  1580 			{
       
  1581 			length--;
       
  1582 			}
       
  1583 		}
       
  1584 	else
       
  1585 		{
       
  1586 		length = value.Length();
       
  1587 		}
       
  1588 		
       
  1589 	// Now find the start of the value to be parsed
       
  1590 	TLex8 lex(aPtr.Mid(start, length));
       
  1591 	TChar next = lex.Get();
       
  1592 	while (next != '=' && next != NULL)	
       
  1593 		{		
       
  1594 		next = lex.Get(); // Step through until we find a '=' character or EOS
       
  1595 		}
       
  1596 	
       
  1597 	if (next == NULL)
       
  1598 		{
       
  1599 		return EFalse;	// End of string was found before '=' so there's no valid value.
       
  1600 		}
       
  1601 		
       
  1602 	lex.SkipSpace();	// Will now be at the start of the value
       
  1603 	
       
  1604 	// Now copy the variable value into the result
       
  1605 	aResult.Set(lex.Remainder());
       
  1606 	
       
  1607 	return ETrue;
       
  1608 	}
       
  1609 
       
  1610 
       
  1611 TBool CBTRegistry::FindVar(const TDesC8& aPtr, const TDesC8 &aVarName, TInt &aResult) const
       
  1612 	{
       
  1613 	LOG_FUNC
       
  1614 	TPtrC8 ptr(NULL,0);
       
  1615 	
       
  1616 	if (FindVar(aPtr, aVarName,ptr))
       
  1617 		{
       
  1618 		TLex8 lex(ptr);
       
  1619 		if (lex.Val(aResult) == KErrNone)
       
  1620 			{
       
  1621 			return(ETrue);			
       
  1622 			}
       
  1623 		}
       
  1624 		
       
  1625 	return(EFalse);
       
  1626 	}
       
  1627 
       
  1628 
       
  1629 TBTRegistryDatabaseSecure::TBTRegistryDatabaseSecure()
       
  1630 	{
       
  1631 	LOG_FUNC
       
  1632 	iBuf.Append(RFs::GetSystemDrive() + 'a'); //Gets the system drive and convert it from enum to a char
       
  1633 	iBuf.Append(':');
       
  1634 	iBuf.Append(KBTRegistryDatabaseSecure);		
       
  1635 	}
       
  1636 		
       
  1637 const TDesC& TBTRegistryDatabaseSecure::operator()() const
       
  1638 	{
       
  1639 	LOG_FUNC
       
  1640 	return iBuf;
       
  1641 	}
       
  1642