bluetooth/btsdp/database/rsdpdatabase.cpp
changeset 0 29b1cd4cb562
child 51 20ac952a623c
equal deleted inserted replaced
-1:000000000000 0:29b1cd4cb562
       
     1 // Copyright (c) 2000-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 //
       
    15 
       
    16 #include <bluetooth/logger.h>
       
    17 #include <btsdp.h>
       
    18 #include "ipcinternals.h"
       
    19 #include "DataEncoder.h"
       
    20 #include "EncoderVisitor.h"
       
    21 #include <e32math.h>
       
    22 #include <utf.h>
       
    23 #include <es_sock.h>
       
    24 
       
    25 #ifdef __FLOG_ACTIVE
       
    26 _LIT8(KLogComponent, LOG_COMPONENT_SDPDATABASE);
       
    27 #endif
       
    28 
       
    29 static TInt StartServer()
       
    30 //
       
    31 // Start the server process or thread
       
    32 //
       
    33 	{
       
    34 	LOG_STATIC_FUNC
       
    35 
       
    36 	const TUidType serverUid(KNullUid,KNullUid,KSdpServerUid3);
       
    37 	
       
    38 #ifdef __SDPSERVER_NO_PROCESSES__
       
    39 	//
       
    40 	// In EKA1 WINS the server is a DLL, the exported entrypoint returns a TInt
       
    41 	// which represents the real entry-point for the server thread
       
    42 	//
       
    43 	RLibrary lib;
       
    44 	TInt r=lib.Load(KSdpServerImg,serverUid);
       
    45 	if (r!=KErrNone)
       
    46 		return r;
       
    47 	TLibraryFunction ordinal1=lib.Lookup(1);
       
    48 	TThreadFunction serverFunc=reinterpret_cast<TThreadFunction>(ordinal1());
       
    49 	//
       
    50 	// To deal with the unique thread (+semaphore!) naming in EPOC, and that we may
       
    51 	// be trying to restart a server that has just exited we attempt to create a
       
    52 	// unique thread name for the server.
       
    53 	// This uses Math::Random() to generate a 32-bit random number for the name
       
    54 	//
       
    55 	TName name(KSdpServerName);
       
    56 	_LIT(KHexString, "0x");
       
    57  	name.Append(KHexString());
       
    58 	name.AppendNum(Math::Random(),EHex);
       
    59 	RThread server;
       
    60 	r=server.Create(name,serverFunc,
       
    61 					KSdpServerStackSize,
       
    62 					NULL,&lib,NULL,
       
    63 					KSdpServerInitHeapSize,KSdpServerMaxHeapSize,EOwnerProcess);
       
    64 	lib.Close();	// if successful, server thread has handle to library now
       
    65 #else
       
    66 	//
       
    67 	// EPOC and EKA2 is easy, we just create a new server process. Simultaneous
       
    68 	// launching of two such processes should be detected when the second one
       
    69 	// attempts to create the server object, failing with KErrAlreadyExists.
       
    70 	//
       
    71 	RProcess server;
       
    72 	TInt r=server.Create(KSdpServerImg,KNullDesC,serverUid);
       
    73 #endif
       
    74 
       
    75 	LOG(KSdpServerImg);
       
    76 	LOG1(_L("c\tSdp Server created, code %d"), r);
       
    77 	if (r!=KErrNone)
       
    78 		return r;
       
    79 
       
    80 	TRequestStatus status;
       
    81 	// this is a variant of RProcess::Logon which completes either when the process 
       
    82 	// terminates or when the new process calls "RProcess::Rendezvous();"
       
    83     server.Rendezvous(status);        
       
    84     if (status!=KRequestPending)
       
    85 		{
       
    86 		server.Kill(0);                // abort startup 
       
    87 		}
       
    88     else 
       
    89 		{
       
    90 		server.Resume();        // Rendezvous OK - start the server 
       
    91 		LOG(_L("c\tSdp Server Resumed"));
       
    92 		}
       
    93     User::WaitForRequest(status);                // wait for start or death 
       
    94 	LOG1(_L("c\tSdp Server started, code %d (0=>success)"), status.Int());
       
    95     server.Close(); 
       
    96 	LOG(_L("c\tSdp Server Closed"));
       
    97     return status.Int(); 
       
    98 	}
       
    99 	
       
   100 
       
   101 //==================================
       
   102 // RSdp
       
   103 //==================================
       
   104 
       
   105 EXPORT_C RSdp::RSdp()
       
   106 /** Default constructor. */
       
   107 	{
       
   108 	LOG_FUNC
       
   109 	}
       
   110 
       
   111 EXPORT_C TInt RSdp::Connect()
       
   112 /** Connects a client process to the database.
       
   113 
       
   114 The connection should be closed after use with RHandleBase::Close().
       
   115 
       
   116 @return System-wide error code */
       
   117 	{
       
   118 	LOG_FUNC
       
   119 	TInt retry=2;
       
   120 	for (;;)
       
   121 		{
       
   122 		TInt r=CreateSession(KSdpServerName,TVersion(0,0,0));	//gives MessageSlots of -1
       
   123 																//this uses global pool rather
       
   124 																//than local pool
       
   125 		if (r!=KErrNotFound && r!=KErrServerTerminated)
       
   126 			return r;
       
   127 		if (--retry==0)
       
   128 			return r;
       
   129 		r=StartServer();
       
   130 		if (r!=KErrNone && r!=KErrAlreadyExists)
       
   131 			return r;
       
   132 		}
       
   133 	}
       
   134 
       
   135 EXPORT_C TVersion RSdp::Version() const
       
   136 /** Gets the version of the database server.
       
   137 
       
   138 @return Version information */
       
   139 	{
       
   140 	LOG_FUNC
       
   141 	return TVersion(KSdpServerMajorVersionNumber, 
       
   142 					KSdpServerMinorVersionNumber, 
       
   143 					KSdpServerBuildVersionNumber);
       
   144 	}
       
   145 
       
   146 EXPORT_C void RSdp::ResourceCountMarkStart()
       
   147 /** Starts the counter to keep track of open subsessions. 
       
   148 
       
   149 This should be used by clients to do resource leakage debugging checks. */
       
   150 	{
       
   151 	LOG_FUNC
       
   152 	SendReceive(ESdpResourceCountMarkStart, TIpcArgs(NULL)); //ss//
       
   153 	}
       
   154 
       
   155 EXPORT_C void RSdp::ResourceCountMarkEnd()
       
   156 /** Stops the counter to keep track of open subsessions.
       
   157 
       
   158 This should be used by clients to do resource leakage debugging checks. */
       
   159 	{
       
   160 	LOG_FUNC
       
   161 	SendReceive(ESdpResourceCountMarkEnd, TIpcArgs(NULL)); //ss//
       
   162 	}
       
   163 
       
   164 EXPORT_C TInt RSdp::ResourceCount()
       
   165 /** Gets the number of open subsessions to the database.
       
   166 
       
   167 This should be used by clients to do resource leakage debugging checks.
       
   168 
       
   169 @return Number of open subsessions to the database */
       
   170 	{
       
   171 	LOG_FUNC
       
   172 	TInt count = 0;
       
   173 	TPckgBuf<TInt> pckg(count);
       
   174 	SendReceive(ESdpResourceCount, TIpcArgs(&pckg)); //ss//
       
   175 	return pckg();
       
   176 	}
       
   177 
       
   178 /**
       
   179 @internalTechnology
       
   180 @released
       
   181 */
       
   182 EXPORT_C TInt RSdp::__DbgMarkHeap()
       
   183 	{
       
   184 	LOG_FUNC
       
   185 #ifdef _DEBUG
       
   186 	return SendReceive(ESdpServerDbgMarkHeap);
       
   187 #else
       
   188 	return KErrNone;
       
   189 #endif
       
   190 	}
       
   191 
       
   192 /**
       
   193 @internalTechnology
       
   194 @released
       
   195 */
       
   196 EXPORT_C TInt RSdp::__DbgCheckHeap(TInt aCount)
       
   197 	{
       
   198 	LOG_FUNC
       
   199 #ifdef _DEBUG
       
   200 	return SendReceive(ESdpServerDbgCheckHeap, TIpcArgs(aCount));
       
   201 #else
       
   202 	(void)aCount;
       
   203 	return KErrNone;
       
   204 #endif
       
   205 	}
       
   206 
       
   207 /**
       
   208 @internalTechnology
       
   209 @released
       
   210 */
       
   211 EXPORT_C TInt RSdp::__DbgMarkEnd(TInt aCount)
       
   212 	{
       
   213 	LOG_FUNC
       
   214 #ifdef _DEBUG
       
   215 	return SendReceive(ESdpServerDbgMarkEnd, TIpcArgs(aCount));
       
   216 #else
       
   217 	(void)aCount;
       
   218 	return KErrNone;
       
   219 #endif
       
   220 	}
       
   221 
       
   222 /**
       
   223 @internalTechnology
       
   224 @released
       
   225 */
       
   226 EXPORT_C TInt RSdp::__DbgFailNext(TInt aCount)
       
   227 	{
       
   228 	LOG_FUNC
       
   229 #ifdef _DEBUG
       
   230 	return SendReceive(ESdpServerDbgFailNext, TIpcArgs(aCount));
       
   231 #else
       
   232 	(void)aCount;
       
   233 	return KErrNone;
       
   234 #endif
       
   235 	}
       
   236 
       
   237 //==================================
       
   238 // RSdpDatabase
       
   239 //==================================
       
   240 
       
   241 EXPORT_C TInt RSdpDatabase::Open(RSdp& aSession)
       
   242 /** Opens a SDP database subsession.
       
   243 
       
   244 @param aSession SDP database session
       
   245 @return System-wide error code
       
   246 @capability LocalServices */
       
   247 	{
       
   248 	LOG_FUNC
       
   249 	return CreateSubSession(aSession, ESdpCreateDatabaseSubSession/*, TIpcArgs(&p[0])*/); //ss//
       
   250 	}
       
   251 
       
   252 EXPORT_C RSdpDatabase::RSdpDatabase() :
       
   253 	iBuffer(0)
       
   254 /** Default constructor.
       
   255 
       
   256 @capability LocalServices */
       
   257 	{
       
   258 	LOG_FUNC
       
   259 	}
       
   260 
       
   261 EXPORT_C void RSdpDatabase::Close()
       
   262 /** Closes the SDP database subsession.
       
   263 
       
   264 Any records that have been added during this session will be removed when the session is closed.
       
   265 @capability LocalServices */
       
   266 	{
       
   267 	LOG_FUNC
       
   268 	//delete resources
       
   269 	delete iBuffer;
       
   270 	iBuffer = NULL;
       
   271 
       
   272 	RSubSessionBase::CloseSubSession(ESdpCloseSubSession);
       
   273 	}
       
   274 
       
   275 
       
   276 EXPORT_C void RSdpDatabase::CreateServiceRecordL(const TUUID& aUUID, TSdpServRecordHandle& aHandle)
       
   277 /** Creates a new service record, with a single service class, in the SDP database. 
       
   278 
       
   279 
       
   280 @param aUUID The service class UUID for the service record
       
   281 @param aHandle On return, the service record handle of the new record
       
   282 @capability LocalServices */
       
   283 	{
       
   284 	LOG_FUNC
       
   285 	if (SubSessionHandle())
       
   286 		{
       
   287 		CSdpAttrValueDES* list = CSdpAttrValueDES::NewDESL(NULL);
       
   288 		CleanupStack::PushL(list);
       
   289 		MSdpElementBuilder* bldr = list;
       
   290 
       
   291 		bldr
       
   292 			->StartListL()
       
   293 				->BuildUUIDL(aUUID)
       
   294 			->EndListL();
       
   295 		CreateServiceRecordL(*list, aHandle);
       
   296 		CleanupStack::PopAndDestroy(); //list
       
   297 		}
       
   298 	else
       
   299 		{
       
   300 		//Client has a bad handle therefore panic
       
   301 		User::Panic(_L("SDP-Subsession"), KErrBadHandle);
       
   302 		}
       
   303 	}
       
   304 
       
   305 EXPORT_C void RSdpDatabase::CreateServiceRecordL(CSdpAttrValueDES& aUUIDList,
       
   306 												 TSdpServRecordHandle& aHandle)
       
   307 /** Creates a new service record, with multiple service classes, in the SDP database.
       
   308 
       
   309 @param aUUIDList The service class attribute of the new record. This should 
       
   310 consist of a list of UUIDs of the service classes to which the record belongs. 
       
   311 The UUIDs should be ordered from the most derived service class to the base 
       
   312 one.
       
   313 @param aHandle On return, the service record handle of the new record
       
   314 @capability LocalServices */
       
   315 	{
       
   316 	LOG_FUNC
       
   317 	if (SubSessionHandle())
       
   318 		{
       
   319 		delete iBuffer;
       
   320 		iBuffer = 0;
       
   321 		TUint size = TElementEncoder::EncodedSize(ETypeDES, aUUIDList.DataSize());
       
   322 		iBuffer = HBufC8::NewL(size);
       
   323 		TPtr8 ptr = iBuffer->Des();
       
   324 
       
   325 		TElementEncoder ee(ptr);
       
   326 		CAttrEncoderVisitor::EncodeAttributeL(ee, aUUIDList);
       
   327 
       
   328 		TSdpServRecordHandlePckgBuf pckg;
       
   329 		User::LeaveIfError(SendReceive(ESdpDatabaseCreateServiceRecord, TIpcArgs(iBuffer, &pckg))); //ss//
       
   330 		aHandle = pckg(); //return handle in handle reference
       
   331 		}
       
   332 	else
       
   333 		{
       
   334 		//Client has a bad handle therefore panic
       
   335 		User::Panic(_L("SDP-Subsession"), KErrBadHandle);
       
   336 		}
       
   337 	}
       
   338 
       
   339 
       
   340 EXPORT_C void RSdpDatabase::UpdateAttributeL(TSdpServRecordHandle aHandle, 
       
   341 											 TSdpAttributeID aAttrID, 
       
   342 											 CSdpAttrValue& aAttrValue)
       
   343 /** Updates a service record attribute (value encapsulated in a CSdpAttrValue).
       
   344 
       
   345 If the attribute does not exist, it is created. If it already exists, the 
       
   346 current definition is removed and the new value inserted. 
       
   347 
       
   348 No check is made that the attribute value is suitable for the service class 
       
   349 to which the record belongs. It is up to the user to ensure that the semantics 
       
   350 of the attribute defined by the service class are respected.
       
   351 
       
   352 @param aHandle The service record handle to update
       
   353 @param aAttrID The attribute ID to update
       
   354 @param aAttrValue The attribute value
       
   355 @capability LocalServices */
       
   356 	{
       
   357 	LOG_FUNC
       
   358 	if (SubSessionHandle())
       
   359 		{
       
   360 		TSdpAttributeIDPckgBuf idPckg;
       
   361 		TSdpServRecordHandlePckgBuf handlePckg;
       
   362 		handlePckg() = aHandle; //put record handle into package
       
   363 		idPckg() = aAttrID; //put attr ID into package
       
   364 
       
   365 		delete iBuffer;
       
   366 		iBuffer = 0;
       
   367 		TUint size = TElementEncoder::EncodedSize(aAttrValue.Type(), aAttrValue.DataSize());
       
   368 		iBuffer = HBufC8::NewL(size);
       
   369 		TPtr8 ptr = iBuffer->Des();
       
   370 
       
   371 		TElementEncoder ee(ptr);
       
   372 		CAttrEncoderVisitor::EncodeAttributeL(ee, aAttrValue);
       
   373 		
       
   374 		User::LeaveIfError(SendReceive(ESdpDatabaseUpdateAttribute, TIpcArgs(&handlePckg, &idPckg, iBuffer))); //ss//
       
   375 		}
       
   376 	else
       
   377 		{
       
   378 		//Client has a bad handle therefore panic
       
   379 		User::Panic(_L("SDP-Subsession"), KErrBadHandle);
       
   380 		}
       
   381 	}
       
   382 
       
   383 EXPORT_C void RSdpDatabase::UpdateAttributeL(TSdpServRecordHandle aHandle, 
       
   384 											 TSdpAttributeID aAttrID, 
       
   385 											 TUint aUintValue)
       
   386 /** Updates a service record attribute (integer value).
       
   387 
       
   388 If the attribute does not exist, it is created. If it already exists, the 
       
   389 current definition is removed and the new value inserted. 
       
   390 
       
   391 No check is made that the attribute value is suitable for the service class 
       
   392 to which the record belongs. It is up to the user to ensure that the semantics 
       
   393 of the attribute defined by the service class are respected.
       
   394 
       
   395 @param aHandle The service record handle to update
       
   396 @param aAttrID The attribute ID to update
       
   397 @param aUintValue The attribute value
       
   398 @capability LocalServices */
       
   399 	{
       
   400 	LOG_FUNC
       
   401 	if (SubSessionHandle())
       
   402 		{
       
   403 		TBuf8<4> buf;
       
   404 		buf.SetLength(4);
       
   405 		BigEndian::Put32(&buf[0], aUintValue);
       
   406 		CSdpAttrValueUint* attrValueUint = CSdpAttrValueUint::NewUintL(buf);
       
   407 		CleanupStack::PushL(attrValueUint);
       
   408 		UpdateAttributeL(aHandle, aAttrID, *attrValueUint);
       
   409 		CleanupStack::PopAndDestroy(); //attrValueUint
       
   410 		}
       
   411 	else
       
   412 		{
       
   413 		//Client has a bad handle therefore panic
       
   414 		User::Panic(_L("SDP-Subsession"), KErrBadHandle);
       
   415 		}
       
   416 	}
       
   417 
       
   418 EXPORT_C void RSdpDatabase::UpdateAttributeL(TSdpServRecordHandle aHandle, 
       
   419 											 TSdpAttributeID aAttrID, 
       
   420 											 const TDesC16& aDesCValue)
       
   421 /** Updates a service record attribute (wide descriptor value).
       
   422 
       
   423 If the attribute does not exist, it is created. If it already exists, the 
       
   424 current definition is removed and the new value inserted. 
       
   425 
       
   426 No check is made that the attribute value is suitable for the service class 
       
   427 to which the record belongs. It is up to the user to ensure that the semantics 
       
   428 of the attribute defined by the service class are respected.
       
   429 
       
   430 @param aHandle The service record handle to update
       
   431 @param aAttrID The attribute ID to update
       
   432 @param aDesCValue The attribute value
       
   433 @capability LocalServices */
       
   434 /** Updates a service record attribute (narrow descriptor value).
       
   435 
       
   436 If the attribute does not exist, it is created. If it already exists, the 
       
   437 current value is removed and the new value inserted. 
       
   438 
       
   439 No check is made that the attribute value is suitable for the service class 
       
   440 to which the record belongs. It is up to the user to ensure that the semantics 
       
   441 of the attribute defined by the service class are respected.
       
   442 
       
   443 @param aHandle The service record handle to update
       
   444 @param aAttrID The attribute ID to update
       
   445 @param aDesCValue The attribute value
       
   446 @capability LocalServices */
       
   447 	{
       
   448 	LOG_FUNC
       
   449 	if (SubSessionHandle())
       
   450 		{
       
   451 		 //The '5' below is max ratio of number of UTF_8 chars to number of unicode chars .
       
   452 		HBufC8* buf = HBufC8::NewLC(5*aDesCValue.Length());
       
   453 		TPtr8 ptr = buf->Des();
       
   454 		CnvUtfConverter::ConvertFromUnicodeToUtf8(ptr, aDesCValue);
       
   455 		UpdateAttributeL(aHandle, aAttrID, ptr);
       
   456 		CleanupStack::PopAndDestroy(); //buf
       
   457 		}
       
   458 	else
       
   459 		{
       
   460 		//Client has a bad handle therefore panic
       
   461 		User::Panic(_L("SDP-Subsession"), KErrBadHandle);
       
   462 		}
       
   463 	}
       
   464 
       
   465 EXPORT_C void RSdpDatabase::UpdateAttributeL(TSdpServRecordHandle aHandle, 
       
   466 											 TSdpAttributeID aAttrID, 
       
   467 											 const TDesC8& aDesCValue)
       
   468 /** Updates a service record attribute (wide descriptor value).
       
   469 
       
   470 If the attribute does not exist, it is created. If it already exists, the 
       
   471 current value is removed and the new value inserted. 
       
   472 
       
   473 No check is made that the attribute value is suitable for the service class 
       
   474 to which the record belongs. It is up to the user to ensure that the semantics 
       
   475 of the attribute defined by the service class are respected.
       
   476 
       
   477 @param aHandle The service record handle to update
       
   478 @param aAttrID The attribute ID to update
       
   479 @param aDesCValue The attribute value
       
   480 @capability LocalServices */
       
   481 /** Updates a service record attribute (narrow descriptor value).
       
   482 
       
   483 If the attribute does not exist, it is created. If it already exists, the 
       
   484 current definition is removed and the new value inserted. 
       
   485 
       
   486 No check is made that the attribute value is suitable for the service class 
       
   487 to which the record belongs. It is up to the user to ensure that the semantics 
       
   488 of the attribute defined by the service class are respected.
       
   489 
       
   490 @param aHandle The service record handle to update
       
   491 @param aAttrID The attribute ID to update
       
   492 @param aDesCValue The attribute value
       
   493 @capability LocalServices */
       
   494 	{
       
   495 	LOG_FUNC
       
   496 	if (SubSessionHandle())
       
   497 		{
       
   498 		CSdpAttrValueString* attrValueString = CSdpAttrValueString::NewStringL(aDesCValue);
       
   499 		CleanupStack::PushL(attrValueString);
       
   500 		UpdateAttributeL(aHandle, aAttrID, *attrValueString);
       
   501 		CleanupStack::PopAndDestroy(); //attrValueString
       
   502 		}
       
   503 	else
       
   504 		{
       
   505 		//Client has a bad handle therefore panic
       
   506 		User::Panic(_L("SDP-Subsession"), KErrBadHandle);
       
   507 		}
       
   508 	}
       
   509 
       
   510 /** Delete an attribute from a service record. 
       
   511 
       
   512 @param aHandle The service record from which to delete the attribute
       
   513 @param aAttrID The ID of the attribute
       
   514 @capability LocalServices
       
   515 @deprecated Use non-leaving version instead
       
   516 @see RSdpDatabase::DeleteAttribute
       
   517 */
       
   518 EXPORT_C void RSdpDatabase::DeleteAttributeL(TSdpServRecordHandle aHandle, TSdpAttributeID aAttrID)
       
   519 	{
       
   520 	LOG_FUNC
       
   521 	if (SubSessionHandle())
       
   522 		{
       
   523 		TPckg<TSdpAttributeID> idPckg(aAttrID);
       
   524 		TPckg<TSdpServRecordHandle> handlePckg(aHandle);
       
   525 		User::LeaveIfError(SendReceive(ESdpDatabaseDeleteAttribute, TIpcArgs(&handlePckg, &idPckg))); 
       
   526 		}
       
   527 	else
       
   528 		{
       
   529 		//Client has a bad handle therefore panic
       
   530 		User::Panic(_L("SDP-Subsession"), KErrBadHandle);
       
   531 		}
       
   532 	}
       
   533 
       
   534 /** Delete an attribute from a service record. 
       
   535 
       
   536 @param aHandle The service record from which to delete the attribute
       
   537 @param aAttrID The ID of the attribute
       
   538 @capability LocalServices 
       
   539 */
       
   540 EXPORT_C void RSdpDatabase::DeleteAttribute(TSdpServRecordHandle aHandle, TSdpAttributeID aAttrID)
       
   541 	{
       
   542 	LOG_FUNC
       
   543 	if (SubSessionHandle())
       
   544 		{
       
   545 		TPckg<TSdpAttributeID> idPckg(aAttrID);
       
   546 		TPckg<TSdpServRecordHandle> handlePckg(aHandle);
       
   547 
       
   548 		SendReceive(ESdpDatabaseDeleteAttribute, TIpcArgs(&handlePckg, &idPckg));
       
   549 		}
       
   550 	else
       
   551 		{
       
   552 		//Client has a bad handle therefore panic
       
   553 		User::Panic(_L("SDP-Subsession"), KErrBadHandle);
       
   554 		}
       
   555 	}
       
   556 
       
   557 /** Deletes a service record.
       
   558 
       
   559 @param aHandle Handle of the service record to delete
       
   560 @capability LocalServices 
       
   561 @deprecated Use non-leaving version instead
       
   562 @see RSdpDatabase::DeleteRecord
       
   563 */
       
   564 EXPORT_C void RSdpDatabase::DeleteRecordL(TSdpServRecordHandle aHandle)
       
   565 	{
       
   566 	LOG_FUNC
       
   567 	if (SubSessionHandle())
       
   568 		{
       
   569 		TPckg<TSdpServRecordHandle> handlePckg(aHandle);
       
   570 
       
   571 		User::LeaveIfError(SendReceive(ESdpDatabaseDeleteServiceRecord, TIpcArgs(&handlePckg))); 
       
   572 		}
       
   573 	else
       
   574 		{
       
   575 		//Client has a bad handle therefore panic
       
   576 		User::Panic(_L("SDP-Subsession"), KErrBadHandle);
       
   577 		}
       
   578 	}
       
   579 
       
   580 /** Deletes a service record.
       
   581 
       
   582 @param aHandle Handle of the service record to delete
       
   583 @capability LocalServices 
       
   584 */
       
   585 EXPORT_C void RSdpDatabase::DeleteRecord(TSdpServRecordHandle aHandle)
       
   586 	{
       
   587 	LOG_FUNC
       
   588 	if (SubSessionHandle())
       
   589 		{
       
   590 		TPckg<TSdpServRecordHandle> handlePckg(aHandle);
       
   591 
       
   592 		SendReceive(ESdpDatabaseDeleteServiceRecord, TIpcArgs(&handlePckg));
       
   593 		}
       
   594 	else
       
   595 		{
       
   596 		//Client has a bad handle therefore panic
       
   597 		User::Panic(_L("SDP-Subsession"), KErrBadHandle);
       
   598 		}
       
   599 	}
       
   600