kernel/eka/kernel/sproperty.cpp
changeset 0 a41df078684a
child 39 2bb754abd467
equal deleted inserted replaced
-1:000000000000 0:a41df078684a
       
     1 // Copyright (c) 2002-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 the License "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 // \e32\kernel\sproperty.cpp
       
    15 // 
       
    16 //
       
    17 
       
    18 #include <kernel/kern_priv.h>
       
    19 #include "execs.h"
       
    20 
       
    21 #define __PS_ASSERT(aCond) \
       
    22 	__ASSERT_DEBUG( (aCond), ( \
       
    23 						Kern::Printf("Assertion '" #aCond "' failed;\nFile: '" \
       
    24 						__FILE__ "' Line: %d\n", __LINE__), \
       
    25 						Kern::Fault("Pub&Sub", 0)) )
       
    26 
       
    27 inline DProcess* CurProcess()
       
    28 	{
       
    29 	return TheCurrentThread->iOwningProcess;
       
    30 	}
       
    31 
       
    32 class TProperty 
       
    33 	{
       
    34 public:
       
    35 	static TInt Init();
       
    36 
       
    37 	static TInt Attach(TUint aCategory, TUint aKey, TProperty** aProp);
       
    38 	static TInt Open(TUint aCategory, TUint aKey, TProperty** aProp);
       
    39 	void Close();
       
    40 
       
    41 	TInt Define(const TPropertyInfo*, DProcess*);
       
    42 	TInt Delete(DProcess*);
       
    43 
       
    44 	TInt Subscribe(TPropertySubsRequest* aSubs, DProcess*);
       
    45 	void Cancel(TPropertySubsRequest* aSubs);
       
    46 
       
    47 	TInt GetI(TInt* aValue, DProcess*);
       
    48 	TInt GetB(TUint8* aBuf, TInt* aSize, DProcess*, TBool aUser); 
       
    49 	TInt SetI(TInt aValue, DProcess*);
       
    50 	TInt SetB(const TUint8*, TInt aSize, DProcess*, TBool aUser);
       
    51 
       
    52 	static TInt FindGetI(TUint aCategory, TUint aKey, TInt* aValue, DProcess*);
       
    53 	static TInt FindSetI(TUint aCategory, TUint aKey, TInt aValue, DProcess*);
       
    54 
       
    55 	// Called with system or feature locked
       
    56 	TBool IsDefined()
       
    57 		{
       
    58 		return iType != RProperty::ETypeLimit;
       
    59 		}
       
    60 
       
    61 	// Called with system or feature locked
       
    62 	RProperty::TType Type()
       
    63 		{
       
    64 		return (RProperty::TType) iType;
       
    65 		}
       
    66 
       
    67 	// Called with system or feature locked
       
    68 	TInt BufSize()
       
    69 		{
       
    70 		__PS_ASSERT(iType == RProperty::EByteArray || iType == RProperty::ELargeByteArray);
       
    71 		return iBuf ? iBuf->iBufSize : 0;
       
    72 		}
       
    73 
       
    74 
       
    75 	// The property attributes.
       
    76 	// Meaningful for defined properties only (ie. iType != RProperty::ETypeLimit)
       
    77 	// Constant while the property is defined
       
    78 	TUint32	Owner()
       
    79 		{ return iOwner; }
       
    80 
       
    81 	/// Ensure pages in the source buffer are paged in and lock them
       
    82 	static TInt LockSourcePages(const TUint8* aBuf, TInt aSize);
       
    83 
       
    84 	/// Unlock source pages again
       
    85 	static void UnlockSourcePages();
       
    86 
       
    87 #ifdef _DEBUG
       
    88 	static TBool IsLocked()
       
    89 		// used in assertions only
       
    90 		{ return FeatureLock->iCleanup.iThread == TheCurrentThread; }
       
    91 #endif
       
    92 
       
    93 public:
       
    94 	const TUint		iCategory;
       
    95 	const TUint		iKey;
       
    96 
       
    97 private:
       
    98 	// Acquire the feature lock
       
    99 	// Called in CS
       
   100 	static void Lock()
       
   101 		{
       
   102 		Kern::MutexWait(*FeatureLock);
       
   103 		}
       
   104 
       
   105 	// Release the feature lock
       
   106 	// Called in CS
       
   107 	static void Unlock()
       
   108 		{
       
   109 		Kern::MutexSignal(*FeatureLock);
       
   110 		}
       
   111 
       
   112 	static void CompleteRequest(TPropertySubsRequest*, TInt aReason);	
       
   113 	static void CompleteQue(SDblQue* aQue, TInt aReason);	
       
   114 	static void CompleteDfc(TAny* aQue);
       
   115 
       
   116 	static TUint Hash(TUint aCategory, TUint aKey);
       
   117 	static TProperty** Lookup(TUint aCategory, TUint aKey);
       
   118 	static TInt LookupOrCreate(TUint aCategory, TUint aKey, TProperty**);
       
   119 
       
   120 	TAny* operator new(TUint aSize) __NO_THROW
       
   121 		{ return Kern::AllocZ(aSize); }
       
   122 
       
   123 	TProperty(TUint aCategory, TUint aKey);
       
   124 
       
   125 	void SetNotDefined()
       
   126 		{ iType = RProperty::ETypeLimit; }
       
   127 
       
   128 	inline void Use();
       
   129 	void Release();
       
   130 
       
   131 	void CompleteByDfc();
       
   132 
       
   133 #ifndef __REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
       
   134 	TBool DoCheckDeleteRights(DProcess* aProcess, const char* aDiagnostic);
       
   135 	TBool DoCheckDefineRights(DProcess* aProcess, const char* aDiagnostic);
       
   136 	TBool DoCheckGetRights(DProcess* aProcess, const char* aDiagnostic);
       
   137 	TBool DoCheckSetRights(DProcess* aProcess, const char* aDiagnostic);
       
   138 #endif //__REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
       
   139 	TBool DoCheckDeleteRights(DProcess* aProcess);
       
   140 	TBool DoCheckDefineRights(DProcess* aProcess);
       
   141 	TBool DoCheckGetRights(DProcess* aProcess);
       
   142 	TBool DoCheckSetRights(DProcess* aProcess);
       
   143 
       
   144 #ifndef __REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
       
   145 	inline TBool CheckDeleteRights(DProcess* aProcess, const char* aDiagnostic=0)
       
   146 		{
       
   147 		return DoCheckDeleteRights(aProcess, aDiagnostic);
       
   148 		}
       
   149 
       
   150 	inline TBool CheckDefineRights(DProcess* aProcess, const char* aDiagnostic=0)
       
   151 		{
       
   152 		return DoCheckDefineRights(aProcess, aDiagnostic);
       
   153 		}
       
   154 
       
   155 	inline TBool CheckGetRights(DProcess* aProcess, const char* aDiagnostic=0)
       
   156 		{
       
   157 		return DoCheckGetRights(aProcess, aDiagnostic);
       
   158 		}
       
   159 
       
   160 	inline TBool CheckSetRights(DProcess* aProcess, const char* aDiagnostic=0)
       
   161 		{
       
   162 		return DoCheckSetRights(aProcess, aDiagnostic);
       
   163 		}
       
   164 
       
   165 #else //__REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
       
   166 	// Only available to NULL arguments
       
   167 	inline TBool CheckDeleteRights(DProcess* aProcess, OnlyCreateWithNull /*aDiagnostic*/=NULL)
       
   168 		{
       
   169 		return DoCheckDeleteRights(aProcess);
       
   170 		}
       
   171 
       
   172 	inline TBool CheckDefineRights(DProcess* aProcess, OnlyCreateWithNull /*aDiagnostic*/=NULL)
       
   173 		{
       
   174 		return DoCheckDefineRights(aProcess);
       
   175 		}
       
   176 
       
   177 	inline TBool CheckGetRights(DProcess* aProcess, OnlyCreateWithNull /*aDiagnostic*/=NULL)
       
   178 		{
       
   179 		return DoCheckGetRights(aProcess);
       
   180 		}
       
   181 
       
   182 	inline TBool CheckSetRights(DProcess* aProcess, OnlyCreateWithNull /*aDiagnostic*/=NULL)
       
   183 		{
       
   184 		return DoCheckSetRights(aProcess);
       
   185 		}
       
   186 
       
   187 #endif // !__REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
       
   188 
       
   189 	enum { KCompletionDfcPriority = 2 };
       
   190 	static TDfc		CompletionDfc;
       
   191 	// subscriptions to be completed by the DFC
       
   192 	static SDblQue	CompletionQue;		// protected by the system lock
       
   193 
       
   194 	static DMutex*	FeatureLock;			///< Order KMutexOrdPubSub
       
   195 
       
   196 	// hash table collision lists
       
   197 	enum { KHashTableLimit = 32 };	// must be power of 2
       
   198 	static TProperty*	Table[KHashTableLimit];	// protected by the feature lock
       
   199 	
       
   200 #ifdef __DEMAND_PAGING__
       
   201 	static DMutex*	PagingLockMutex;		///< Mutex used to protect demand paging lock, order KMutexOrdPubSub2
       
   202 	static DDemandPagingLock* PagingLock; 	///< Locks user memory when copying large properties
       
   203 #endif
       
   204 	
       
   205 	// iType == RProperty::ETypeLimit means not defined
       
   206 	TUint8	iType;	// updates require the system lock AND the feature lock 
       
   207 					// reads require only one of them
       
   208 	// The property attributes.
       
   209 	// Meaningful for defined properties only (ie. iType != RProperty::ETypeLimit)
       
   210 	// Constant while the property is defined
       
   211 	TUint8	iAttr;
       
   212 	TCompiledSecurityPolicy iReadPolicy;
       
   213 	TCompiledSecurityPolicy iWritePolicy;
       
   214 	TUint32	iOwner;
       
   215 
       
   216 	TUint		iRefCount;	// protected by the feature lock
       
   217 	TProperty*	iNext;		// hash table collision list link -
       
   218 							//		protected by the feature lock
       
   219 
       
   220 	class TBuf
       
   221 		{ // Viraiable-size buffer for  byte array property values
       
   222 	public:
       
   223 		static TBuf* New(TInt aSize);
       
   224 
       
   225 		TUint16	iBufSize;		// buffer size - constant
       
   226 		TUint16	iSize;			// actual property size - protected by the system lock
       
   227 		TUint8	iBytes[1];		// byte array - protected by the system lock
       
   228 		};
       
   229 
       
   230 	// The property value
       
   231 	// Meaningful for defined properties only (ie. iType != RProperty::ETypeLimit)
       
   232 	union	// the value (ie. iValue or iBuf->iBytes) is protected by the system lock
       
   233 		{ 
       
   234 		TBuf*	iBuf;   // pointer updates of a defined property (eg. buffer 
       
   235 						//   reallocation) require the system AND the feature locks;
       
   236 						// pointer reads (eg to get/set byte values) require any of them
       
   237 		TInt	iValue;
       
   238 		};
       
   239 
       
   240 	// Called with system or feature locked
       
   241 	TInt Size()
       
   242 		{
       
   243 		__PS_ASSERT(iType == RProperty::EByteArray || iType == RProperty::ELargeByteArray);
       
   244 		return iBuf ? iBuf->iSize : 0;
       
   245 		}
       
   246 
       
   247 	// Called with system or feature locked
       
   248 	TUint8* Buf()
       
   249 		{
       
   250 		__PS_ASSERT(iType == RProperty::EByteArray || iType == RProperty::ELargeByteArray);
       
   251 		return iBuf ? iBuf->iBytes : NULL;
       
   252 		}
       
   253 
       
   254 	// Called with system or feature locked
       
   255 	void SetSize(TInt aSize)
       
   256 		{
       
   257 		__PS_ASSERT(TUint(aSize) <= TUint(BufSize()));
       
   258 		if (iBuf)
       
   259 			iBuf->iSize = TUint16(aSize);
       
   260 		}
       
   261 
       
   262 	TInt _GetB(TUint8* aBuf, TInt* aSize, DProcess* aProcess, TBool aUser);
       
   263 	TInt _SetB(const TUint8*, TInt aSize, DProcess*, TBool aUser, TBuf** aNewBufHdr);
       
   264 
       
   265 	SDblQue	iPendingQue;	// pending subscriptions - protected by the system lock
       
   266 	};
       
   267 
       
   268 
       
   269 TDfc		TProperty::CompletionDfc(TProperty::CompleteDfc, &TProperty::CompletionQue, KCompletionDfcPriority);
       
   270 SDblQue		TProperty::CompletionQue;
       
   271 DMutex*		TProperty::FeatureLock;	
       
   272 TProperty*	TProperty::Table[KHashTableLimit];
       
   273 
       
   274 #ifdef __DEMAND_PAGING__
       
   275 DMutex*		TProperty::PagingLockMutex;
       
   276 DDemandPagingLock* TProperty::PagingLock;
       
   277 _LIT(KPubSubMutexName2, "PropertyPagingLockMutex");
       
   278 #endif
       
   279 
       
   280 TInt PubSubPropertyInit()
       
   281 	{ return TProperty::Init(); }
       
   282 
       
   283 _LIT(KPubSubMutexName, "PropertyLock");
       
   284 
       
   285 TInt TProperty::Init()
       
   286 	{ // static
       
   287 	TInt r = Kern::MutexCreate(FeatureLock, KPubSubMutexName, KMutexOrdPubSub);
       
   288 	if (r != KErrNone)
       
   289 		return r;
       
   290 	CompletionDfc.SetDfcQ(K::SvMsgQ);
       
   291 	
       
   292 #ifdef __DEMAND_PAGING__	
       
   293 	r = Kern::MutexCreate(PagingLockMutex, KPubSubMutexName2, KMutexOrdPubSub2);
       
   294 	if (r != KErrNone)
       
   295 		return r;
       
   296 	PagingLock = new DDemandPagingLock();
       
   297 	if (!PagingLock)
       
   298 		return KErrNoMemory;
       
   299 	r = PagingLock->Alloc(RProperty::KMaxLargePropertySize);
       
   300 	if (r != KErrNone)
       
   301 		return r;
       
   302 #endif
       
   303 	
       
   304 	return KErrNone;
       
   305 	}
       
   306 
       
   307 TProperty::TProperty(TUint aCategory, TUint aKey) : iCategory(aCategory), iKey(aKey)
       
   308 	{ SetNotDefined(); }
       
   309 
       
   310 TUint TProperty::Hash(TUint aCategory, TUint aKey)
       
   311 	{ // a naive hash function 
       
   312 	TUint code = (aCategory ^ aKey) & (KHashTableLimit - 1);
       
   313 	__PS_ASSERT(code < KHashTableLimit);	// KHashTableLimit must be a power of 2
       
   314 	return code;
       
   315 	}
       
   316 
       
   317 // Called feature locked.
       
   318 TProperty** TProperty::Lookup(TUint aCategory, TUint aKey)
       
   319 	{ // static
       
   320 	TProperty** propP = &Table[Hash(aCategory, aKey)];
       
   321 	for (;;)
       
   322 		{
       
   323 		TProperty* prop = *propP;
       
   324 		if (!prop) break;
       
   325 		if ((prop->iCategory == aCategory) && (prop->iKey == aKey)) break;
       
   326 		propP = &prop->iNext;
       
   327 		}
       
   328 	return propP;
       
   329 	}
       
   330 
       
   331 // Called feature locked.
       
   332 TInt TProperty::LookupOrCreate(TUint aCategory, TUint aKey, TProperty** aProp)
       
   333 	{ // static
       
   334 	TProperty** propP = Lookup(aCategory, aKey);
       
   335 	TProperty* prop = *propP;
       
   336 	if (!prop)
       
   337 		{
       
   338 		prop = new TProperty(aCategory, aKey);
       
   339 		if (!prop)
       
   340 			{
       
   341 			return KErrNoMemory;
       
   342 			}
       
   343 		*propP = prop;			
       
   344 		}
       
   345 	*aProp = prop;
       
   346 	return KErrNone;
       
   347 	}
       
   348 
       
   349 #ifndef __REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
       
   350 TBool TProperty::DoCheckDefineRights(DProcess* aProcess, const char* aDiagnostic)
       
   351 	{
       
   352 	TUint32 cat=iCategory;
       
   353 	if(cat==aProcess->iS.iSecureId)
       
   354 		return ETrue;
       
   355 	if(cat<(TUint32)KUidSecurityThresholdCategoryValue)
       
   356 		return aProcess->HasCapability(ECapabilityWriteDeviceData, aDiagnostic);
       
   357 	PlatSec::SecureIdCheckFail(aProcess, cat, aDiagnostic);
       
   358 	return EFalse;
       
   359 	}
       
   360 #endif // !__REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
       
   361 
       
   362 TBool TProperty::DoCheckDefineRights(DProcess* aProcess)
       
   363 	{
       
   364 #ifndef __REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
       
   365 	return DoCheckDefineRights(aProcess, NULL);
       
   366 #else //__REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
       
   367 	TUint32 cat=iCategory;
       
   368 	if(cat==aProcess->iS.iSecureId)
       
   369 		return ETrue;
       
   370 	if(cat<(TUint32)KUidSecurityThresholdCategoryValue)
       
   371 		return aProcess->HasCapability(ECapabilityWriteDeviceData);
       
   372 	return EFalse;
       
   373 #endif // !__REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
       
   374 	}
       
   375 
       
   376 #ifndef __REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
       
   377 // Called feature locked
       
   378 TBool TProperty::DoCheckDeleteRights(DProcess* aProcess, const char* aDiagnostic)
       
   379 	{
       
   380 	__ASSERT_MUTEX(FeatureLock);
       
   381 	if(aProcess->iS.iSecureId == Owner())
       
   382 		{
       
   383 		return ETrue;
       
   384 		}
       
   385 	PlatSec::SecureIdCheckFail(aProcess, Owner(), aDiagnostic);
       
   386 	return EFalse;
       
   387 	}
       
   388 #endif // !__REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
       
   389 
       
   390 TBool TProperty::DoCheckDeleteRights(DProcess* aProcess)
       
   391 	{
       
   392 #ifndef __REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
       
   393 	return DoCheckDeleteRights(aProcess, NULL);
       
   394 #else //__REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
       
   395 	__ASSERT_MUTEX(FeatureLock);
       
   396 	if(aProcess->iS.iSecureId == Owner())
       
   397 		{
       
   398 		return ETrue;
       
   399 		}
       
   400 	return EFalse;
       
   401 #endif // !__REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
       
   402 	}
       
   403 
       
   404 #ifndef __REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
       
   405 // Called system locked
       
   406 TBool TProperty::DoCheckGetRights(DProcess* aProcess, const char* aDiagnostic)
       
   407 	{
       
   408 	return iReadPolicy.CheckPolicy(aProcess, aDiagnostic);
       
   409 	}
       
   410 #endif // !__REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
       
   411 
       
   412 TBool TProperty::DoCheckGetRights(DProcess* aProcess)
       
   413 	{
       
   414 #ifndef __REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
       
   415 	return DoCheckGetRights(aProcess, NULL);
       
   416 #else //__REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
       
   417 	return iReadPolicy.CheckPolicy(aProcess);
       
   418 #endif // !__REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
       
   419 	}
       
   420 
       
   421 #ifndef __REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
       
   422 // Called system locked
       
   423 TBool TProperty::DoCheckSetRights(DProcess* aProcess, const char* aDiagnostic)
       
   424 	{
       
   425 	return iWritePolicy.CheckPolicy(aProcess, aDiagnostic);
       
   426 	}
       
   427 #endif // !__REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
       
   428 
       
   429 TBool TProperty::DoCheckSetRights(DProcess* aProcess)
       
   430 	{
       
   431 #ifndef __REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
       
   432 	return DoCheckSetRights(aProcess, NULL);
       
   433 #else //__REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
       
   434 	return iWritePolicy.CheckPolicy(aProcess);
       
   435 #endif // !__REMOVE_PLATSEC_DIAGNOSTIC_STRINGS__
       
   436 	}
       
   437 
       
   438 // Called in CS
       
   439 TProperty::TBuf* TProperty::TBuf::New(TInt aSize)
       
   440 	{ // static
       
   441 	__ASSERT_CRITICAL;
       
   442 	TBuf* buf = (TBuf*) Kern::Alloc(_FOFF(TBuf, iBytes) + aSize);
       
   443 	if (!buf)
       
   444 		{
       
   445 		return NULL;
       
   446 		}
       
   447 	buf->iBufSize = TUint16(aSize);
       
   448 	buf->iSize = 0;
       
   449 	return buf;
       
   450 	}
       
   451 
       
   452 // Called in CS
       
   453 TInt TProperty::Define(const TPropertyInfo* aInfo, DProcess* aProcess)
       
   454 	{
       
   455 	__ASSERT_CRITICAL;
       
   456 	if (aProcess && !CheckDefineRights(aProcess,__PLATSEC_DIAGNOSTIC_STRING("Checked whilst trying to Define a Publish and Subscribe Property")))
       
   457 		{
       
   458 		return KErrPermissionDenied;
       
   459 		}
       
   460 	TCompiledSecurityPolicy readPolicy;
       
   461 	TInt r = readPolicy.Set((aInfo->iReadPolicy));
       
   462 	if(r != KErrNone)
       
   463 		{
       
   464 		return r;
       
   465 		}
       
   466 	TCompiledSecurityPolicy writePolicy;
       
   467 	r = writePolicy.Set((aInfo->iWritePolicy));
       
   468 	if(r != KErrNone)
       
   469 		{
       
   470 		return r;
       
   471 		}
       
   472 	if ((aInfo->iType < 0) || (RProperty::ETypeLimit <= aInfo->iType) ||
       
   473 		((aInfo->iType == RProperty::EInt) && aInfo->iSize) ||
       
   474 		(aInfo->iAttr != 0))
       
   475 		{
       
   476 		return KErrArgument;
       
   477 		}
       
   478 	if ((aInfo->iType == RProperty::EByteArray && aInfo->iSize > RProperty::KMaxPropertySize))
       
   479 		{
       
   480 		return KErrTooBig;
       
   481 		}
       
   482 	Lock();
       
   483 	if (IsDefined())
       
   484 		{
       
   485 		Unlock();
       
   486 		return KErrAlreadyExists;
       
   487 		}
       
   488 	if (aInfo->iSize)
       
   489 		{
       
   490 		__PS_ASSERT((aInfo->iType == RProperty::EByteArray) || (aInfo->iType == RProperty::ELargeByteArray));
       
   491 		__PS_ASSERT(iBuf == NULL);
       
   492 		iBuf = TBuf::New(aInfo->iSize);
       
   493 		}
       
   494 
       
   495 	iReadPolicy = readPolicy;
       
   496 	iWritePolicy = writePolicy;
       
   497 	iOwner = CurProcess()->iS.iSecureId;
       
   498 	iAttr = 0;
       
   499 
       
   500 	// We need to check all pending requests for read access rights and 
       
   501 	// complete those that havn't.
       
   502 	// We have the following constraints:
       
   503 	//	- we don't want to hold the system lock iterating through 'iPendingQue' list.
       
   504 	//	- as soon as the system lock is released new entries can be added by 
       
   505 	//    'Subscribe()' and existing entries can be removed by 'Cancel()'.
       
   506 	//	- we don't want to complete a request holding the feature lock
       
   507 	// To deal with these issues we move all  'iPendingQue' entries to one of 
       
   508 	// two temporary queues:
       
   509 	//	'localPendingQue' for entries that will remain pending
       
   510 	//	'localCompletionQue' for entries that will be completed
       
   511 	// We move entries one by one dropping and reacquiring the system lock on each 
       
   512 	// iteration; we get (move) always the first 'iPendingQue' entry until the 
       
   513 	// queue becomes empty.
       
   514 	//
       
   515 	SDblQue localPendingQue;	// protected by the system lock
       
   516 	SDblQue localCompletionQue;	// protected by the system lock
       
   517 	NKern::LockSystem();
       
   518 	while (!iPendingQue.IsEmpty())
       
   519 		{
       
   520 		TPropertySubsRequest* subs = (TPropertySubsRequest*) iPendingQue.GetFirst();
       
   521 		DProcess* process = subs->iProcess;
       
   522 		subs->iProcess = NULL;
       
   523 		if (process && !CheckGetRights(process, __PLATSEC_DIAGNOSTIC_STRING("Checked whilst trying to Subscribe to a Publish and Subscribe Property")))
       
   524 			{ // Check fails - will complete the subscription with an error
       
   525 			localCompletionQue.Add(subs);
       
   526 			}
       
   527 		else
       
   528 			{ // Check OK - will leave in the pending queue 
       
   529 			localPendingQue.Add(subs);
       
   530 			}
       
   531 		NKern::FlashSystem();	// preemption point
       
   532 		}
       
   533 	iPendingQue.MoveFrom(&localPendingQue);
       
   534 	iType = (TUint8) aInfo->iType;
       
   535 	NKern::UnlockSystem();
       
   536 	// Now the property can be accessed by other threads.
       
   537 	Use();
       
   538 	Unlock();
       
   539 	// Now we can complete requests.
       
   540 	CompleteQue(&localCompletionQue, KErrPermissionDenied);
       
   541 	return KErrNone;
       
   542 	}
       
   543 
       
   544 // Called in CS
       
   545 TInt TProperty::Attach(TUint aCategory, TUint aKey, TProperty** aProp)
       
   546 	{ //static 
       
   547 	Lock();
       
   548 	TProperty* prop;
       
   549 	// Attach can create a non defined property.
       
   550 	TInt r = LookupOrCreate(aCategory, aKey, &prop);
       
   551 	if (r != KErrNone) 
       
   552 		{
       
   553 		Unlock();
       
   554 		return r;
       
   555 		}
       
   556 	prop->Use();
       
   557 	*aProp = prop;
       
   558 	Unlock();
       
   559 	return KErrNone;
       
   560 	}
       
   561 
       
   562 // Called in CS
       
   563 TInt TProperty::Open(TUint aCategory, TUint aKey, TProperty** aProp)
       
   564 	{ //static 
       
   565 	Lock();
       
   566 	TProperty* prop = *Lookup(aCategory, aKey);
       
   567 	if (!prop) 
       
   568 		{
       
   569 		Unlock();
       
   570 		return KErrNotFound;
       
   571 		}
       
   572 	prop->Use();
       
   573 	*aProp = prop;
       
   574 	Unlock();
       
   575 	return KErrNone;
       
   576 	}
       
   577 
       
   578 // Called in CS
       
   579 void TProperty::Close()
       
   580 	{
       
   581 	Lock();
       
   582 	Release();
       
   583 	// '*this' may do not exist any more
       
   584 	Unlock();
       
   585 	}
       
   586 
       
   587 // Called in CS
       
   588 TInt TProperty::Delete(DProcess* aProcess)
       
   589 	{
       
   590 	Lock();
       
   591 	if (!IsDefined())
       
   592 		{
       
   593 		Unlock();
       
   594 		return KErrNotFound;
       
   595 		}
       
   596 	if (aProcess && !CheckDeleteRights(aProcess,__PLATSEC_DIAGNOSTIC_STRING("Checked whilst trying to Delete a Publish and Subscribe Property")))
       
   597 		{
       
   598 		Unlock();
       
   599 		return KErrPermissionDenied;
       
   600 		}
       
   601 	NKern::LockSystem();
       
   602 	// Remember that iType is the tag of iBuf and iValue union
       
   603 	TBuf* buf = (iType != RProperty::EInt) ? iBuf : NULL;
       
   604 	SetNotDefined();
       
   605 	// Down from here nobody can access the property value
       
   606 
       
   607 	// We don't want to complete requests holding the feature lock. 
       
   608 	SDblQue localQue;
       
   609 	localQue.MoveFrom(&iPendingQue);
       
   610 
       
   611 	NKern::UnlockSystem();
       
   612 
       
   613 	iBuf = NULL;
       
   614 	iValue = 0;
       
   615 	delete buf;
       
   616 	Release();
       
   617 	// '*this' may do not exist any more
       
   618 	Unlock();
       
   619 	 // Now we can complete.
       
   620 	CompleteQue(&localQue, KErrNotFound);
       
   621 	return KErrNone;
       
   622 	}
       
   623 
       
   624 // Enter feature locked.
       
   625 // Return feature locked.
       
   626 inline void TProperty::Use()
       
   627 	{
       
   628 	__ASSERT_MUTEX(FeatureLock);
       
   629 	++iRefCount;
       
   630 	}
       
   631 
       
   632 // Enter feature locked.
       
   633 // Return feature locked.
       
   634 void TProperty::Release()
       
   635 	{
       
   636 	__ASSERT_MUTEX(FeatureLock);
       
   637 	__PS_ASSERT(iRefCount);
       
   638 	if (--iRefCount == 0)
       
   639 		{
       
   640 		__PS_ASSERT(!IsDefined()); // property must not be defined.
       
   641 		// Lookup to find the previous element in the simply linked collision list.
       
   642 		TProperty** propP = Lookup(iCategory, iKey);
       
   643 		*propP = iNext;
       
   644 		delete this;
       
   645 		}
       
   646 	}
       
   647 
       
   648 // Enter system locked.
       
   649 // Return system unlocked.
       
   650 TInt TProperty::Subscribe(TPropertySubsRequest* aSubs, DProcess* aProcess)
       
   651 	{
       
   652 	__ASSERT_SYSTEM_LOCK;
       
   653 	if (aSubs->iNext)
       
   654 		{ // already pending - will Panic
       
   655 		NKern::UnlockSystem();
       
   656 		return KErrInUse;
       
   657 		}
       
   658 	TBool defined = IsDefined();
       
   659 	if (defined)
       
   660 		{ // property is defined - check access now
       
   661 		aSubs->iProcess = NULL;	
       
   662 		if (aProcess && !CheckGetRights(aProcess,__PLATSEC_DIAGNOSTIC_STRING("Checked whilst trying to Subscribe to a Publish and Subscribe Property")))
       
   663 			{
       
   664 			NKern::ThreadEnterCS();
       
   665 			CompleteRequest(aSubs, KErrPermissionDenied);
       
   666 			NKern::ThreadLeaveCS();
       
   667 			return KErrNone;
       
   668 			}
       
   669 		}	
       
   670 	else
       
   671 		{ // will check when defined
       
   672 		aSubs->iProcess = aProcess;
       
   673 		}
       
   674 	iPendingQue.Add(aSubs);
       
   675 	NKern::UnlockSystem();
       
   676 	return KErrNone;
       
   677 	}
       
   678 
       
   679 // Enter system locked.
       
   680 // Return system unlocked.
       
   681 void TProperty::Cancel(TPropertySubsRequest* aSubs)
       
   682 	{
       
   683 	__ASSERT_SYSTEM_LOCK;
       
   684 	if (!aSubs->iNext)
       
   685 		{ // not pending - silently return
       
   686 		NKern::UnlockSystem();	
       
   687 		return;
       
   688 		}
       
   689 	aSubs->Deque();
       
   690 	aSubs->iNext = NULL;
       
   691 	aSubs->iProcess = NULL;
       
   692 	NKern::ThreadEnterCS();
       
   693 	CompleteRequest(aSubs, KErrCancel);
       
   694 	NKern::ThreadLeaveCS();
       
   695 	}
       
   696 
       
   697 // Enter system locked.
       
   698 // Return system unlocked.
       
   699 // Called in CS or a DFC context
       
   700 void TProperty::CompleteRequest(TPropertySubsRequest* aSubs, TInt aResult)
       
   701 	{ // static
       
   702 	__ASSERT_SYSTEM_LOCK;
       
   703 	__ASSERT_CRITICAL;
       
   704 	TPropertyCompleteFn	fn = aSubs->iCompleteFn;
       
   705 	TAny* ptr = aSubs->iPtr;
       
   706 	NKern::UnlockSystem();
       
   707 	(*fn)(ptr, aResult);
       
   708 	}
       
   709 
       
   710 // Called in CS or a DFC context
       
   711 void TProperty::CompleteQue(SDblQue* aQue, TInt aReason)
       
   712 	{ // static
       
   713 	__ASSERT_CRITICAL;
       
   714 	NKern::LockSystem();
       
   715 	while (!aQue->IsEmpty())
       
   716 		{ 
       
   717 		TPropertySubsRequest* subs = (TPropertySubsRequest*) aQue->First();
       
   718 		subs->Deque();
       
   719 		subs->iNext = NULL;
       
   720 		CompleteRequest(subs, aReason);
       
   721 		NKern::LockSystem();
       
   722 		}	 
       
   723 	NKern::UnlockSystem();
       
   724 	}
       
   725 
       
   726 // Executed in DFC context
       
   727 void TProperty::CompleteDfc(TAny* aQue)
       
   728 	{ // static
       
   729 	CompleteQue((SDblQue*) aQue, KErrNone);
       
   730 	}
       
   731 
       
   732 // Enter system locked.
       
   733 // Return system unlocked.
       
   734 void TProperty::CompleteByDfc()
       
   735 	{
       
   736 	__ASSERT_SYSTEM_LOCK;
       
   737 	// Append elements from the pending queue to the completion queue
       
   738 	if (!iPendingQue.IsEmpty())
       
   739 		{
       
   740 		CompletionQue.MoveFrom(&iPendingQue);
       
   741 		CompletionDfc.Enque(SYSTEM_LOCK);
       
   742 		}
       
   743 	else 
       
   744 		{
       
   745 		NKern::UnlockSystem();
       
   746 		}
       
   747 	}
       
   748 	
       
   749 // Enter system locked.
       
   750 // Return system unlocked.
       
   751 TInt TProperty::GetI(TInt* aValue, DProcess* aProcess)
       
   752 	{
       
   753 	__ASSERT_SYSTEM_LOCK;
       
   754 	if (!IsDefined())
       
   755 		{
       
   756 		NKern::UnlockSystem();
       
   757 		return KErrNotFound;
       
   758 		}
       
   759 	if (aProcess && !CheckGetRights(aProcess,__PLATSEC_DIAGNOSTIC_STRING("Checked whilst trying to Get a Publish and Subscribe Property")))
       
   760 		{
       
   761 		NKern::UnlockSystem();
       
   762 		return KErrPermissionDenied;
       
   763 		}
       
   764 	if (iType != RProperty::EInt)
       
   765 		{
       
   766 		NKern::UnlockSystem();
       
   767 		return KErrArgument;
       
   768 		}
       
   769 	*aValue = iValue;
       
   770 	NKern::UnlockSystem();
       
   771 	return KErrNone;
       
   772 	}
       
   773 
       
   774 TInt TProperty::FindGetI(TUint aCategory, TUint aKey, TInt* aValue, DProcess* aProcess)
       
   775 	{
       
   776 	Lock();
       
   777 	TProperty* prop = *TProperty::Lookup(aCategory, aKey);
       
   778 	TInt r;
       
   779 	if (!prop) 
       
   780 		r = KErrNotFound;
       
   781 	else
       
   782 		{
       
   783 		NKern::LockSystem();
       
   784 		r = prop->GetI(aValue, aProcess);
       
   785 		}
       
   786 	Unlock();
       
   787 	return r;
       
   788 	}
       
   789 
       
   790 TInt TProperty::FindSetI(TUint aCategory, TUint aKey, TInt aValue, DProcess* aProcess)
       
   791 	{
       
   792 	Lock();
       
   793 	TProperty* prop = *TProperty::Lookup(aCategory, aKey);
       
   794 	TInt r;
       
   795 	if (!prop) 
       
   796 		r = KErrNotFound;
       
   797 	else
       
   798 		{
       
   799 		NKern::LockSystem();
       
   800 		r = prop->SetI(aValue, aProcess);
       
   801 		}
       
   802 	Unlock();
       
   803 	return r;
       
   804 	}
       
   805 
       
   806 #ifdef __EPOC32__
       
   807 extern "C" { extern void kumemput_no_paging_assert(TAny* /*aAddr*/, const TAny* /*aKernAddr*/, TInt /*aLength*/); }
       
   808 #else
       
   809 inline void kumemput_no_paging_assert(TAny* aAddr, const TAny* aKernAddr, TInt aLength)
       
   810 	{kumemput(aAddr,aKernAddr,aLength);}
       
   811 #endif
       
   812 
       
   813 // Enter system locked.
       
   814 // Return system unlocked.
       
   815 TInt TProperty::_GetB(TUint8* aBuf, TInt* aSize, DProcess* aProcess, TBool aUser)
       
   816 	{
       
   817 	if (!IsDefined())
       
   818 		{
       
   819 		NKern::UnlockSystem();
       
   820 		return KErrNotFound;
       
   821 		}
       
   822 	if (aProcess && !CheckGetRights(aProcess,__PLATSEC_DIAGNOSTIC_STRING("Checked whilst trying to Get a Publish and Subscribe Property")))
       
   823 		{
       
   824 		NKern::UnlockSystem();
       
   825 		return KErrPermissionDenied;
       
   826 		}
       
   827 	if (iType == RProperty::EInt)
       
   828 		{
       
   829 		NKern::UnlockSystem();
       
   830 		return KErrArgument;
       
   831 		}
       
   832 	if (iType == RProperty::ELargeByteArray)
       
   833 		{
       
   834 		// copy with system lock released
       
   835 		__ASSERT_MUTEX(FeatureLock);
       
   836 		NKern::UnlockSystem();
       
   837 		}
       
   838 	TInt bufSize = *aSize;
       
   839 	TInt size = Size();
       
   840 	TInt r = KErrNone;
       
   841 	if (bufSize < size) 
       
   842 		{
       
   843 		size = bufSize;
       
   844 		r = KErrOverflow;
       
   845 		}
       
   846 	TUint8* buf = Buf();
       
   847 	if (aUser)
       
   848 		{ // Don't use 'r' to preserve possible KErrOverflow condition
       
   849 		XTRAPD(res, XT_DEFAULT, kumemput_no_paging_assert(aBuf, buf, size));
       
   850 		if (res != KErrNone)
       
   851 			r = KErrBadDescriptor;
       
   852 		}
       
   853 	else
       
   854 		{ 
       
   855 		memcpy(aBuf, buf, size); 
       
   856 		}
       
   857 	*aSize = size;
       
   858 	if (iType != RProperty::ELargeByteArray)
       
   859 		{
       
   860 		NKern::UnlockSystem();
       
   861 		}
       
   862 	return r;
       
   863 	}
       
   864 
       
   865 // Enter system locked.
       
   866 // Return system unlocked.
       
   867 TInt TProperty::GetB(TUint8* aBuf, TInt* aSize, DProcess* aProcess, TBool aUser)
       
   868 	{
       
   869 	__ASSERT_SYSTEM_LOCK;
       
   870 	if (iType != RProperty::ELargeByteArray)
       
   871 		return _GetB(aBuf,aSize,aProcess,aUser);
       
   872 
       
   873 	// Acquire feature lock for accessing large properties
       
   874 	NKern::ThreadEnterCS();
       
   875 	FeatureLock->Wait();	// returns with system lock still held
       
   876 	TInt r = _GetB(aBuf,aSize,aProcess,aUser);
       
   877 	Unlock();
       
   878 	NKern::ThreadLeaveCS();
       
   879 	return r;
       
   880 	}
       
   881 
       
   882 // Enter system locked.
       
   883 // Return system unlocked.
       
   884 TInt TProperty::SetI(TInt aValue, DProcess* aProcess)
       
   885 	{
       
   886 	__ASSERT_SYSTEM_LOCK;
       
   887 	if (!IsDefined())
       
   888 		{
       
   889 		NKern::UnlockSystem();
       
   890 		return KErrNotFound;
       
   891 		}
       
   892 	if (aProcess && !CheckSetRights(aProcess, __PLATSEC_DIAGNOSTIC_STRING("Checked whilst trying to Set a Publish and Subscribe Property")))
       
   893 		{
       
   894 		NKern::UnlockSystem();
       
   895 		return KErrPermissionDenied;
       
   896 		}
       
   897 	if (iType != RProperty::EInt)
       
   898 		{
       
   899 		NKern::UnlockSystem();
       
   900 		return KErrArgument;
       
   901 		}
       
   902 	iValue = aValue;
       
   903 	CompleteByDfc();
       
   904 	return KErrNone;
       
   905 	}
       
   906 
       
   907 
       
   908 #ifdef __EPOC32__
       
   909 extern "C" { extern void kumemget_no_paging_assert(TAny* /*aKernAddr*/, const TAny* /*aAddr*/, TInt /*aLength*/); }
       
   910 #else
       
   911 inline void kumemget_no_paging_assert(TAny* aKernAddr, const TAny* aAddr, TInt aLength)
       
   912 	{kumemget(aKernAddr,aAddr,aLength);}
       
   913 #endif
       
   914 
       
   915 // Enter with system locked.
       
   916 // Return system unlocked.
       
   917 TInt TProperty::_SetB(const TUint8* aBuf, TInt aSize, DProcess* aProcess, TBool aUser, TBuf** aNewBuf)
       
   918 	{
       
   919 	if (!IsDefined())
       
   920 		{
       
   921 		NKern::UnlockSystem();
       
   922 		return KErrNotFound;
       
   923 		}
       
   924 	if (aProcess && !CheckSetRights(aProcess, __PLATSEC_DIAGNOSTIC_STRING("Checked whilst trying to Set a Publish and Subscribe Property")))
       
   925 		{
       
   926 		NKern::UnlockSystem();
       
   927 		return KErrPermissionDenied;
       
   928 		}
       
   929 	if (iType == RProperty::EInt)
       
   930 		{
       
   931 		NKern::UnlockSystem();
       
   932 		return KErrArgument;
       
   933 		}
       
   934 	else if (iType == RProperty::EByteArray)
       
   935 		{
       
   936 		if (aSize > RProperty::KMaxPropertySize)
       
   937 			{
       
   938 			NKern::UnlockSystem();
       
   939 			return KErrTooBig;
       
   940 			}
       
   941 		}
       
   942 	else if (iType == RProperty::ELargeByteArray)
       
   943 		{
       
   944 		__ASSERT_MUTEX(FeatureLock);
       
   945 		NKern::UnlockSystem();
       
   946 		if (aSize > RProperty::KMaxLargePropertySize)
       
   947 			{
       
   948 			return KErrTooBig;
       
   949 			}
       
   950 		}
       
   951 	if (aSize > BufSize())
       
   952 		{
       
   953 		if (aNewBuf == NULL || *aNewBuf == NULL)
       
   954 			{
       
   955 			if (iType != RProperty::ELargeByteArray)
       
   956 				{
       
   957 				NKern::UnlockSystem();
       
   958 				}
       
   959 			return KErrOverflow;
       
   960 			}
       
   961 		// New buffer is provided by the caller - switch on it
       
   962 		TBuf* oldBuf = iBuf;
       
   963 		iBuf = *aNewBuf;
       
   964 		// Caller will deallocate the old buffer out of the system lock context
       
   965 		*aNewBuf = oldBuf;
       
   966 		}
       
   967 	if (aUser)
       
   968 		{
       
   969 		__NK_ASSERT_DEBUG(iType==RProperty::ELargeByteArray);
       
   970 		XTRAPD(r, XT_DEFAULT, kumemget_no_paging_assert(Buf(), aBuf, aSize));
       
   971 		if (r != KErrNone)
       
   972 			return KErrBadDescriptor;
       
   973 		}
       
   974 	else
       
   975 		{
       
   976 		memcpy(Buf(), aBuf, aSize); 
       
   977 		}
       
   978 	SetSize(aSize);
       
   979 	if (iType == RProperty::ELargeByteArray)
       
   980 		{
       
   981 		NKern::LockSystem();
       
   982 		}
       
   983 	CompleteByDfc();
       
   984 	return KErrNone;
       
   985 	}
       
   986 
       
   987 // Enter system locked.
       
   988 // Return system unlocked.
       
   989 TInt TProperty::SetB(const TUint8* aBuf, TInt aSize, DProcess* aProcess, TBool aUser)
       
   990 	{ // static
       
   991 	__ASSERT_SYSTEM_LOCK;
       
   992 	TBuf* nBuf = 0;
       
   993 	if (iType != RProperty::ELargeByteArray)
       
   994 		{
       
   995 		// Try to set without buffer reallocation (ie. "RT") first
       
   996 		TInt r = _SetB(aBuf, aSize, aProcess, aUser, NULL);
       
   997 		if (r != KErrOverflow)
       
   998 			return r;
       
   999 
       
  1000 		// Needs buffer reallocation
       
  1001 		NKern::ThreadEnterCS();
       
  1002 		// Allocate a new buffer
       
  1003 		nBuf = TBuf::New(aSize);
       
  1004 		if (!nBuf)
       
  1005 			{
       
  1006 			NKern::ThreadLeaveCS();
       
  1007 			return KErrNoMemory;
       
  1008 			}
       
  1009 		NKern::LockSystem();
       
  1010 		
       
  1011 		r = _SetB(aBuf, aSize, aProcess, aUser, &nBuf);
       
  1012 		// May be the old buffer (or NULL), may be the new one (if wasn't used)
       
  1013 		delete nBuf;
       
  1014 		NKern::ThreadLeaveCS();
       
  1015 		return r;
       
  1016 		}
       
  1017 	
       
  1018 	NKern::ThreadEnterCS();
       
  1019 
       
  1020 	// Large property - need feature lock
       
  1021 	FeatureLock->Wait();
       
  1022 	TInt r = _SetB(aBuf, aSize, aProcess, aUser, &nBuf);
       
  1023 	if (r == KErrOverflow)
       
  1024 		{
       
  1025 		// Allocate a new buffer
       
  1026 		nBuf = TBuf::New(aSize);
       
  1027 		if (!nBuf)
       
  1028 			r = KErrNoMemory;
       
  1029 		else
       
  1030 			{
       
  1031 			NKern::LockSystem();
       
  1032 			r = _SetB(aBuf, aSize, aProcess, aUser, &nBuf);
       
  1033 			}
       
  1034 		}
       
  1035 	Unlock();
       
  1036 	// May be the old buffer (or NULL), may be the new one (if wasn't used)
       
  1037 	delete nBuf;
       
  1038 	NKern::ThreadLeaveCS();
       
  1039 	return r;
       
  1040 	}
       
  1041 
       
  1042 #ifdef __DEMAND_PAGING__
       
  1043 
       
  1044 TInt TProperty::LockSourcePages(const TUint8* aBuf, TInt aSize)
       
  1045 	{
       
  1046 	// When copying from user RAM we must lock the source data in case it is demand paged, otherwise
       
  1047 	// we could get a mutex ordering voliation when waiting on the demand paging mutex
       
  1048 	__ASSERT_CRITICAL;
       
  1049 	Kern::MutexWait(*PagingLockMutex);
       
  1050 	TInt r = PagingLock->Lock(TheCurrentThread, (TLinAddr)aBuf, aSize);
       
  1051 	if(r>=0)
       
  1052 		return KErrNone;
       
  1053 	Kern::MutexSignal(*PagingLockMutex);
       
  1054 	return r;
       
  1055 	}
       
  1056 
       
  1057 void TProperty::UnlockSourcePages()
       
  1058 	{
       
  1059 	__ASSERT_CRITICAL;
       
  1060 	PagingLock->Unlock();
       
  1061 	Kern::MutexSignal(*PagingLockMutex);
       
  1062 	}
       
  1063 
       
  1064 #else
       
  1065 
       
  1066 TInt TProperty::LockSourcePages(const TUint8*, TInt)
       
  1067 	{
       
  1068 	return KErrNone;
       
  1069 	}
       
  1070 
       
  1071 void TProperty::UnlockSourcePages()
       
  1072 	{
       
  1073 	}
       
  1074 
       
  1075 #endif
       
  1076 
       
  1077 //
       
  1078 // User Interface
       
  1079 //
       
  1080 	
       
  1081 class DPropertyRef : public DObject
       
  1082 	{
       
  1083 public:
       
  1084 
       
  1085 	static TInt Define(TUint aCategory, TUint aKey, const TPropertyInfo*);
       
  1086 	static TInt Delete(TUint aCategory, TUint aKey);
       
  1087 	static TInt Attach(TUint aCategory, TUint aKey, TOwnerType aType);
       
  1088 
       
  1089 	static TInt FindGetI(TUint aCategory, TUint aKey, TInt* aValue);
       
  1090 	static TInt FindSetI(TUint aCategory, TUint aKey, TInt aValue);
       
  1091 
       
  1092 	DPropertyRef();
       
  1093 	~DPropertyRef();
       
  1094 
       
  1095 	TInt Subscribe(TRequestStatus* aStatus);
       
  1096 	inline void Cancel();
       
  1097 
       
  1098 	inline TInt GetI(TInt* aValue);
       
  1099 	inline TInt GetB(TUint8* aBuf, TInt* aSize, TBool aUser);
       
  1100 	inline TInt SetI(TInt aValue);
       
  1101 	TInt SetB(const TUint8* aBuf, TInt aSize, TBool aUser);
       
  1102 
       
  1103 	inline RProperty::TType Type()
       
  1104 		{ return iProp->Type(); }
       
  1105 private:
       
  1106 
       
  1107 	static void CompleteFn(TAny* aPtr, TInt aReason);
       
  1108 
       
  1109 	TProperty*				iProp;
       
  1110 	TClientRequest*			iRequest;
       
  1111 	DThread*				iClient;
       
  1112 	TPropertySubsRequest	iSubs;
       
  1113 	};
       
  1114 
       
  1115 DPropertyRef::DPropertyRef() : iSubs(CompleteFn, this)
       
  1116 	{
       
  1117 	}
       
  1118 
       
  1119 // Called in CS
       
  1120 TInt DPropertyRef::Define(TUint aCategory, TUint aKey, const TPropertyInfo* aInfo)
       
  1121 	{ // static
       
  1122 	__ASSERT_CRITICAL;
       
  1123 	TProperty* prop;
       
  1124 	TInt r = TProperty::Attach(aCategory, aKey, &prop);
       
  1125 	if (r != KErrNone)
       
  1126 		{
       
  1127 		return r;
       
  1128 		}
       
  1129 	r = prop->Define(aInfo, CurProcess());
       
  1130 	prop->Close();
       
  1131 	return r;
       
  1132 	}
       
  1133 
       
  1134 // Called in CS
       
  1135 TInt DPropertyRef::Delete(TUint aCategory, TUint aKey)
       
  1136 	{ // static
       
  1137 	__ASSERT_CRITICAL;
       
  1138 	TProperty* prop;
       
  1139 	TInt r = TProperty::Open(aCategory, aKey, &prop);
       
  1140 	if (r != KErrNone)
       
  1141 		{
       
  1142 		return r;
       
  1143 		}
       
  1144 	r = prop->Delete(CurProcess());
       
  1145 	prop->Close();
       
  1146 	return r;
       
  1147 	}
       
  1148 
       
  1149 // Called in CS
       
  1150 TInt DPropertyRef::Attach(TUint aCategory, TUint aKey, TOwnerType aType)
       
  1151 	{ // static
       
  1152 	__ASSERT_CRITICAL;
       
  1153 	DPropertyRef* ref = new DPropertyRef();
       
  1154 	if (ref == NULL)
       
  1155 		{
       
  1156 		return KErrNoMemory;
       
  1157 		}
       
  1158 	TInt r = Kern::CreateClientRequest(ref->iRequest);
       
  1159 	if (r != KErrNone)
       
  1160 		{
       
  1161 		ref->Close(NULL);
       
  1162 		return r;
       
  1163 		}
       
  1164 	r = TProperty::Attach(aCategory, aKey, &ref->iProp);
       
  1165 	if (r != KErrNone)
       
  1166 		{
       
  1167 		ref->Close(NULL);
       
  1168 		return r;
       
  1169 		}
       
  1170 	r = K::AddObject(ref, EPropertyRef);
       
  1171 	if (r != KErrNone)
       
  1172 		{
       
  1173 		ref->Close(NULL);
       
  1174 		return r;
       
  1175 		}
       
  1176 	r = K::MakeHandle(aType, ref);
       
  1177 	if (r < 0)
       
  1178 		{ // error
       
  1179 		ref->Close(NULL);
       
  1180 		}
       
  1181 	return r;
       
  1182 	}
       
  1183 
       
  1184 // Enter system locked.
       
  1185 // Return system unlocked.
       
  1186 TInt DPropertyRef::Subscribe(TRequestStatus* aStatus)
       
  1187 	{
       
  1188 	__ASSERT_SYSTEM_LOCK;
       
  1189 	if (iRequest->SetStatus(aStatus) != KErrNone)
       
  1190 		{ // already pending - will Panic
       
  1191 		NKern::UnlockSystem();
       
  1192 		return KErrInUse;
       
  1193 		}
       
  1194 	iClient = TheCurrentThread;
       
  1195 	iClient->Open();
       
  1196 	return iProp->Subscribe(&iSubs, CurProcess());
       
  1197 	}
       
  1198 
       
  1199 // Called in CS or a DFC context
       
  1200 void DPropertyRef::CompleteFn(TAny* ptr, TInt aReason)
       
  1201 	{ // static
       
  1202 	__ASSERT_CRITICAL;
       
  1203 	DPropertyRef* self = (DPropertyRef*) ptr;
       
  1204 	// Local 'client' variable is necessary because after we call Kern::QueueRequestComplete the
       
  1205 	// structure may be reused for another subscription
       
  1206 	DThread* client = self->iClient;
       
  1207 	__PS_ASSERT(client);
       
  1208 	self->iClient = NULL;
       
  1209 	Kern::QueueRequestComplete(client, self->iRequest, aReason);
       
  1210 	client->Close(NULL);
       
  1211 	}
       
  1212 
       
  1213 // Enter system locked.
       
  1214 // Return system unlocked.
       
  1215 inline void DPropertyRef::Cancel()
       
  1216 	{
       
  1217 	__ASSERT_SYSTEM_LOCK;
       
  1218 	iProp->Cancel(&iSubs);
       
  1219 	}
       
  1220 
       
  1221 // Enter system locked.
       
  1222 // Return system unlocked.
       
  1223 inline TInt DPropertyRef::GetI(TInt* aValue)
       
  1224 	{
       
  1225 	return iProp->GetI(aValue, CurProcess());
       
  1226 	}
       
  1227 
       
  1228 // Enter system locked.
       
  1229 // Return system unlocked.
       
  1230 inline TInt DPropertyRef::GetB(TUint8* aBuf, TInt* aSize, TBool aUser)
       
  1231 	{
       
  1232 	return iProp->GetB(aBuf, aSize, CurProcess(), aUser);
       
  1233 	}
       
  1234 
       
  1235 // Enter system locked.
       
  1236 // Return system unlocked.
       
  1237 inline TInt DPropertyRef::SetI(TInt aValue)
       
  1238 	{
       
  1239 	return iProp->SetI(aValue, CurProcess());
       
  1240 	}
       
  1241 
       
  1242 // Called in CS
       
  1243 inline TInt DPropertyRef::FindGetI(TUint aCategory, TUint aKey, TInt* aValue)
       
  1244 	{
       
  1245 	return TProperty::FindGetI(aCategory, aKey, aValue, CurProcess());
       
  1246 	}
       
  1247 
       
  1248 // Called in CS
       
  1249 inline TInt DPropertyRef::FindSetI(TUint aCategory, TUint aKey, TInt aValue)
       
  1250 	{
       
  1251 	return TProperty::FindSetI(aCategory, aKey, aValue, CurProcess());
       
  1252 	}
       
  1253 
       
  1254 
       
  1255 // Enter system locked.
       
  1256 // Return system unlocked.
       
  1257 TInt DPropertyRef::SetB(const TUint8* aBuf, TInt aSize, TBool aUser)
       
  1258 	{
       
  1259 	TBool open = 
       
  1260 		(iProp->Type() == RProperty::EByteArray) && (iProp->BufSize() < aSize);
       
  1261 	if (open)
       
  1262 		{
       
  1263 		// The buffer extension will release the system lock. 
       
  1264 		// We need to increment the DObject count to protect our-self against 
       
  1265 		// a concurrent DPropertyRef deletion by DObject::Close().
       
  1266 		if (Open() != KErrNone)
       
  1267 			{ // Too late - destruction in progress ....
       
  1268 			NKern::UnlockSystem();
       
  1269 			return KErrNotFound;
       
  1270 			}
       
  1271 		}
       
  1272 	TInt r = iProp->SetB(aBuf, aSize, CurProcess(), aUser);
       
  1273 	if (open)
       
  1274 		{
       
  1275 		Close(NULL);
       
  1276 		}
       
  1277 	return r;
       
  1278 	}
       
  1279 
       
  1280 //
       
  1281 // User interface entry points
       
  1282 //
       
  1283 
       
  1284 // Called in CS
       
  1285 DPropertyRef::~DPropertyRef()
       
  1286 	{
       
  1287 	__ASSERT_CRITICAL;
       
  1288 	if (iProp)
       
  1289 		{
       
  1290 		NKern::LockSystem();
       
  1291 		Cancel();
       
  1292 		iProp->Close();
       
  1293 		iProp = NULL;
       
  1294 		}
       
  1295 	Kern::DestroyClientRequest(iRequest);
       
  1296 	}
       
  1297 
       
  1298 TInt ExecHandler::PropertyDefine(TUint aCategory, TUint aKey, TPropertyInfo* aInfo)
       
  1299 	{
       
  1300 	TPropertyInfo info;
       
  1301 	kumemget(&info, aInfo, sizeof(info));
       
  1302 	if (aCategory == KMaxTUint)
       
  1303 		aCategory = TUint(Kern::CurrentProcess().iS.iSecureId);
       
  1304 	NKern::ThreadEnterCS();
       
  1305 	TInt r = DPropertyRef::Define(aCategory, aKey, &info);
       
  1306 	NKern::ThreadLeaveCS();
       
  1307 	return r;
       
  1308 	}
       
  1309 
       
  1310 TInt ExecHandler::PropertyDelete(TUint aCategory, TUint aKey)
       
  1311 	{
       
  1312 	if (aCategory == KMaxTUint)
       
  1313 		aCategory = TUint(Kern::CurrentProcess().iS.iSecureId);
       
  1314 	NKern::ThreadEnterCS();
       
  1315 	TInt r = DPropertyRef::Delete(aCategory, aKey);
       
  1316 	NKern::ThreadLeaveCS();
       
  1317 	return r;
       
  1318 	}
       
  1319 
       
  1320 TInt ExecHandler::PropertyAttach(TUint aCategory, TUint aKey, TOwnerType aType)
       
  1321 	{
       
  1322 	NKern::ThreadEnterCS();
       
  1323 	TInt r = DPropertyRef::Attach(aCategory, aKey, aType);
       
  1324 	NKern::ThreadLeaveCS();
       
  1325 	return r;
       
  1326 	}
       
  1327 
       
  1328 // Enter system locked.
       
  1329 // Return system unlocked.
       
  1330 void ExecHandler::PropertySubscribe(DPropertyRef* aRef, TRequestStatus* aStatus)
       
  1331 	{
       
  1332 	TInt r = aRef->Subscribe(aStatus);
       
  1333 	if (r != KErrNone)
       
  1334 		{
       
  1335 		__PS_ASSERT(r == KErrInUse);
       
  1336 		K::PanicKernExec(ERequestAlreadyPending);
       
  1337 		}
       
  1338 	}
       
  1339 
       
  1340 // Enter system locked.
       
  1341 // Return system unlocked.
       
  1342 void ExecHandler::PropertyCancel(DPropertyRef* aRef)
       
  1343 	{
       
  1344 	aRef->Cancel();
       
  1345 	}
       
  1346 
       
  1347 // Enter system locked.
       
  1348 // Return system unlocked.
       
  1349 TInt ExecHandler::PropertyGetI(DPropertyRef* aRef, TInt* aValue)
       
  1350 	{
       
  1351 	TInt value;
       
  1352 	TInt r = aRef->GetI(&value);
       
  1353 	if (r != KErrNone)
       
  1354 		{
       
  1355 		return r;
       
  1356 		}
       
  1357 	kumemput32(aValue, &value, sizeof(value));
       
  1358 	return KErrNone;
       
  1359 	}
       
  1360 
       
  1361 
       
  1362 // Enter system locked.
       
  1363 // Return system unlocked.
       
  1364 TInt ExecHandler::PropertyGetB(DPropertyRef* aRef, TUint8* aBuf, TInt aSize)
       
  1365 	{
       
  1366 	TInt r;
       
  1367 
       
  1368 	if(aRef->Type()!=RProperty::ELargeByteArray)
       
  1369 		{
       
  1370 		// Use intermediate kernel buffer for small properties
       
  1371 		TUint8 sbuf[RProperty::KMaxPropertySize];
       
  1372 		if(aSize > (TInt)sizeof(sbuf))
       
  1373 			aSize = sizeof(sbuf);
       
  1374 		r = aRef->GetB(sbuf, &aSize, EFalse);
       
  1375 		if(r==KErrNone || r==KErrOverflow)
       
  1376 			kumemput(aBuf,sbuf,aSize);
       
  1377 		}
       
  1378 	else
       
  1379 		{
       
  1380 		// For large properties we must pin user memory to prevent demand paging.
       
  1381 		aRef->CheckedOpen();
       
  1382 		NKern::ThreadEnterCS();
       
  1383 		NKern::UnlockSystem();
       
  1384 
       
  1385 		if(aSize>RProperty::KMaxLargePropertySize)
       
  1386 			aSize = RProperty::KMaxLargePropertySize;
       
  1387 		r = TProperty::LockSourcePages(aBuf, aSize);
       
  1388 		if(r>=0)
       
  1389 			{
       
  1390 			NKern::LockSystem();
       
  1391 			r = aRef->GetB(aBuf, &aSize, ETrue);
       
  1392 			TProperty::UnlockSourcePages();
       
  1393 			}
       
  1394 
       
  1395 		aRef->Close(0);
       
  1396 		NKern::ThreadLeaveCS();
       
  1397 		}
       
  1398 
       
  1399 	if (r == KErrBadDescriptor)
       
  1400 		{
       
  1401 		K::PanicKernExec(ECausedException);
       
  1402 		}
       
  1403 	else if (r != KErrNone)
       
  1404 		{
       
  1405 		return r;
       
  1406 		}
       
  1407 	return aSize;
       
  1408 	}
       
  1409 
       
  1410 // Enter system locked.
       
  1411 // Return system unlocked.
       
  1412 TInt ExecHandler::PropertySetI(DPropertyRef* aRef, TInt aValue)
       
  1413 	{
       
  1414 	return aRef->SetI(aValue);
       
  1415 	}
       
  1416 
       
  1417 // Enter and return system unlocked.
       
  1418 TInt ExecHandler::PropertySetB(TInt aPropertyRefHandle, const TUint8* aBuf, TInt aSize)
       
  1419 	{
       
  1420 	// If property small enough then copy it to local buffer
       
  1421 	TBool user = ETrue;
       
  1422 	TUint8 sbuf[RProperty::KMaxPropertySize];
       
  1423 	if(aSize<=RProperty::KMaxPropertySize)
       
  1424 		{
       
  1425 		kumemget(sbuf,aBuf,aSize);
       
  1426 		aBuf = sbuf;
       
  1427 		user = EFalse;
       
  1428 		}
       
  1429 	
       
  1430 	NKern::ThreadEnterCS();
       
  1431 
       
  1432 	TInt r = KErrNone;
       
  1433 	if (user)
       
  1434 		r = TProperty::LockSourcePages(aBuf, aSize);
       
  1435 	
       
  1436 	// Set the property
       
  1437 	if(r>=0)
       
  1438 		{
       
  1439 		NKern::LockSystem();
       
  1440 		DPropertyRef* propertyRef = (DPropertyRef*)TheCurrentThread->ObjectFromHandle(aPropertyRefHandle,EPropertyRef);
       
  1441 		if (propertyRef)
       
  1442 			{
       
  1443 			r = propertyRef->SetB(aBuf, aSize, user);
       
  1444 			// unlocks system lock
       
  1445 			}
       
  1446 		else
       
  1447 			{
       
  1448 			r = KErrBadHandle;
       
  1449 			NKern::UnlockSystem();
       
  1450 			}
       
  1451 
       
  1452 		if (user)
       
  1453 			TProperty::UnlockSourcePages();
       
  1454 		}
       
  1455 	
       
  1456 	NKern::ThreadLeaveCS();
       
  1457 	
       
  1458 	if (r == KErrBadDescriptor)
       
  1459 		K::PanicKernExec(ECausedException);
       
  1460 	if (r == KErrBadHandle)
       
  1461 		K::PanicKernExec(EBadHandle);
       
  1462 	return r;
       
  1463 	}
       
  1464 
       
  1465 TInt ExecHandler::PropertyFindGetI(TUint aCategory, TUint aKey, TInt* aValue)
       
  1466 	{
       
  1467 	TInt value;
       
  1468 	NKern::ThreadEnterCS();
       
  1469 	TInt r = DPropertyRef::FindGetI(aCategory, aKey, &value);
       
  1470 	NKern::ThreadLeaveCS();
       
  1471 	if (r != KErrNone)
       
  1472 		{
       
  1473 		return r;
       
  1474 		}
       
  1475 	kumemput32(aValue, &value, sizeof(value));
       
  1476 	return KErrNone;
       
  1477 	}
       
  1478 
       
  1479 TInt ExecHandler::PropertyFindGetB(TUint aCategory, TUint aKey, TUint8* aBuf, 
       
  1480 								   TInt aSize)
       
  1481 	{
       
  1482 	NKern::ThreadEnterCS();
       
  1483 
       
  1484 	TProperty* prop;
       
  1485 	TInt r = TProperty::Open(aCategory, aKey, &prop);
       
  1486 	if (r == KErrNone)
       
  1487 		{
       
  1488 		if(prop->Type()!=RProperty::ELargeByteArray)
       
  1489 			{
       
  1490 			// Use intermediate kernel buffer for small properties
       
  1491 			TUint8 sbuf[RProperty::KMaxPropertySize];
       
  1492 			if(aSize > (TInt)sizeof(sbuf))
       
  1493 				aSize = sizeof(sbuf);
       
  1494 			NKern::LockSystem();
       
  1495 			r = prop->GetB(sbuf, &aSize, CurProcess(), EFalse);
       
  1496 			if(r==KErrNone || r==KErrOverflow)
       
  1497 				kumemput(aBuf,sbuf,aSize);
       
  1498 			}
       
  1499 		else
       
  1500 			{
       
  1501 			// For large properties we must pin the use memory to prevent demand paging.
       
  1502 			if(aSize>RProperty::KMaxLargePropertySize)
       
  1503 				aSize = RProperty::KMaxLargePropertySize;
       
  1504 			r = TProperty::LockSourcePages(aBuf, aSize);
       
  1505 			if(r>=0)
       
  1506 				{
       
  1507 				NKern::LockSystem();
       
  1508 				r = prop->GetB(aBuf, &aSize, CurProcess(), ETrue);
       
  1509 				TProperty::UnlockSourcePages();
       
  1510 				}
       
  1511 			}
       
  1512 		prop->Close();
       
  1513 		}
       
  1514 
       
  1515 	NKern::ThreadLeaveCS();
       
  1516 
       
  1517 	if (r == KErrBadDescriptor)
       
  1518 		{
       
  1519 		K::PanicKernExec(ECausedException);
       
  1520 		}
       
  1521 	else if (r != KErrNone)
       
  1522 		{
       
  1523 		return r;
       
  1524 		}
       
  1525 	return aSize;
       
  1526 	}
       
  1527 
       
  1528 TInt ExecHandler::PropertyFindSetI(TUint aCategory, TUint aKey, TInt aValue)
       
  1529 	{
       
  1530 	NKern::ThreadEnterCS();
       
  1531 	TInt r = DPropertyRef::FindSetI(aCategory, aKey, aValue);
       
  1532 	NKern::ThreadLeaveCS();
       
  1533 	return r;
       
  1534 	}
       
  1535 
       
  1536 TInt ExecHandler::PropertyFindSetB(TUint aCategory, TUint aKey, TUint8* aBuf, 
       
  1537 								   TInt aSize)
       
  1538 	{
       
  1539 	// If property small enough then copy it to local buffer
       
  1540 	TBool user = ETrue;
       
  1541 	TUint8 sbuf[RProperty::KMaxPropertySize];
       
  1542 	if(aSize<=RProperty::KMaxPropertySize)
       
  1543 		{
       
  1544 		kumemget(sbuf,aBuf,aSize);
       
  1545 		aBuf = sbuf;
       
  1546 		user = EFalse;
       
  1547 		}
       
  1548 
       
  1549 	NKern::ThreadEnterCS();
       
  1550 
       
  1551 	TInt r = KErrNone;
       
  1552 	if (user)
       
  1553 		r = TProperty::LockSourcePages(aBuf, aSize);
       
  1554 	
       
  1555 	// Find and open property
       
  1556 	if(r>=0)
       
  1557 		{
       
  1558 		TProperty* prop;
       
  1559 		r = TProperty::Open(aCategory, aKey, &prop);
       
  1560 		if (r == KErrNone)
       
  1561 			{
       
  1562 			// Set the property
       
  1563 			NKern::LockSystem();
       
  1564 			r = prop->SetB(aBuf, aSize, CurProcess(), user);
       
  1565 			prop->Close();
       
  1566 			}
       
  1567 		
       
  1568 		if (user)
       
  1569 			TProperty::UnlockSourcePages();
       
  1570 		}
       
  1571 
       
  1572 	NKern::ThreadLeaveCS();
       
  1573 	if (r == KErrBadDescriptor)
       
  1574 		K::PanicKernExec(ECausedException);
       
  1575 	return r;
       
  1576 	}
       
  1577 
       
  1578 /** Attaches to a property.
       
  1579 
       
  1580 	This performs the same action as RPropertyRef::Open(). However, if the property does
       
  1581 	not exist then it is created first.
       
  1582 	
       
  1583   	@param aCategory The property category.
       
  1584 	@param aKey The property sub-key.
       
  1585 	
       
  1586 	@return KErrNone, if successful;
       
  1587 	        KErrNoMemory, if insufficient memory.
       
  1588 	
       
  1589 	@pre Calling thread must be in a critical section.
       
  1590 	@pre Property has not been opened.
       
  1591 	@pre Call in a thread context.
       
  1592 	@pre Kernel must be unlocked.
       
  1593 	@pre interrupts enabled
       
  1594 	@pre No fast mutex can be held
       
  1595 
       
  1596 	@post Calling thread is in a critical section.
       
  1597 
       
  1598 	@see RPropertyRef::Open()
       
  1599 */
       
  1600 EXPORT_C TInt RPropertyRef::Attach(TUid aCategory, TInt aKey)
       
  1601 	{
       
  1602 	CHECK_PRECONDITIONS(MASK_THREAD_CRITICAL,"RPropertyRef::Attach");			
       
  1603 	__PS_ASSERT(iProp == NULL);
       
  1604 	return TProperty::Attach(TUint(aCategory.iUid), aKey, &iProp);
       
  1605 	}
       
  1606 	
       
  1607 /** Opens a property.
       
  1608 
       
  1609  	Once opened:
       
  1610  	 - the property can be defined, deleted, and  subscribed to
       
  1611  	 - the property value can be retrieved (read) and published (written)
       
  1612 	using the appropriate member-functions in the appropriate order.
       
  1613 	
       
  1614 	Note that the property must already exist. If it does not exist,
       
  1615 	the function will not create it - it will return an error.
       
  1616 	Use RPropertyRef::Attach() if you need to create the property.
       
  1617 
       
  1618 	@param aCategory The property category.
       
  1619 	@param aKey The property sub-key.
       
  1620 	
       
  1621 	@return	KErrNotFound, if the property does not exist;
       
  1622 			KErrNone, if successful;
       
  1623 			Otherwise, one of the other system-wide error codes.
       
  1624 
       
  1625 	@pre Calling thread must be in a critical section.
       
  1626 	@pre Property has not been opened.
       
  1627 	@pre Call in a thread context.
       
  1628 	@pre Kernel must be unlocked.
       
  1629 	@pre interrupts enabled
       
  1630 	@pre No fast mutex can be held
       
  1631 
       
  1632 	@post Calling thread is in a critical section.
       
  1633 */
       
  1634 EXPORT_C TInt RPropertyRef::Open(TUid aCategory, TInt aKey)
       
  1635 	{
       
  1636 	CHECK_PRECONDITIONS(MASK_THREAD_CRITICAL,"RPropertyRef::Open");			
       
  1637 	__PS_ASSERT(iProp == NULL);
       
  1638 	return TProperty::Open(TUint(aCategory.iUid), aKey, &iProp);
       
  1639 	}
       
  1640 
       
  1641 /** Releases the property.
       
  1642 
       
  1643 	@pre Calling thread must be in a critical section.
       
  1644 	@pre Call in a thread context.
       
  1645 	@pre Kernel must be unlocked.
       
  1646 	@pre interrupts enabled
       
  1647 	@pre No fast mutex can be held
       
  1648 
       
  1649 	@post Calling thread is in a critical section.
       
  1650 */
       
  1651 EXPORT_C void RPropertyRef::Close()
       
  1652 	{
       
  1653 	CHECK_PRECONDITIONS(MASK_THREAD_CRITICAL,"RPropertyRef::Close");			
       
  1654 	if (iProp)
       
  1655 		{
       
  1656 		iProp->Close();
       
  1657 		iProp = NULL;
       
  1658 		}
       
  1659 	}
       
  1660 
       
  1661 /** Defines the attributes and access control for a property.
       
  1662 
       
  1663     This can only be done once for each property.
       
  1664 
       
  1665 	Following defintion, the property has a default value:
       
  1666 	- 0 for integer properties
       
  1667 	- zero-length data for byte-array and text properties.
       
  1668 	
       
  1669 	Pending subscriptions for this property will not be completed
       
  1670 	until a new value is published.
       
  1671 
       
  1672 	@param aAttr		Bits 0-7 define the property type.
       
  1673 						Upper bits contain additional property attributes.
       
  1674 	@param aReadPolicy  Read policy. Defines the set capabilities that a process 
       
  1675 	                    will require before being allowed to retrieve (read) the
       
  1676 	                    property value.
       
  1677 	@param aWritePolicy Write policy. Defines the set capabilities that a process 
       
  1678 	                    will require before being allowed to publish (write) the
       
  1679 	                    property value.
       
  1680 	@param aPreallocate Pre-allocated buffer size for EByteArray or ELargeByteArray 
       
  1681 	                    property types.
       
  1682 	@param aProcess		If defining a property within the 'system services' category, 
       
  1683 	                    as defined by the KUidSystemCategoryValue UId, then this
       
  1684 	                    is the process whose security attributes will be checked
       
  1685 	                    to see whether it has sufficient authority to perform
       
  1686 	                    this define operation.
       
  1687 						If NULL, these security checks will NOT be performed.
       
  1688 
       
  1689 	@return	KErrPermissionDenied, if aProcess doesn't have rights to define this property;
       
  1690 			KErrArgument, if aPreallocate is negative,
       
  1691 			              OR the property type passed to the aAttr argument
       
  1692 			              is greater than or equal to RProperty::ETypeLimit,
       
  1693 			              OR aPreallocate has a non-zero value when the property
       
  1694 			              type is an integer;
       
  1695 			KErrTooBig, if aPreallocate is greater than RProperty::KMaxPropertySize
       
  1696 			            when the property type is RProperty::EByteArray,
       
  1697 			            OR if aPreallocate is greater than RProperty::KMaxLargePropertySize
       
  1698 			            when the property type is RProperty::ELargeByteArray;
       
  1699 			KErrAlreadyExists, if the property has already been defined.
       
  1700 
       
  1701 	@pre Calling thread must be in a critical section.
       
  1702 	@pre Property has been opened.
       
  1703 	@pre Call in a thread context.
       
  1704 	@pre Kernel must be unlocked.
       
  1705 	@pre interrupts enabled
       
  1706 	@pre No fast mutex can be held
       
  1707 
       
  1708 	@post Calling thread is in a critical section.
       
  1709 	
       
  1710 	@see  RProperty::TType
       
  1711 */
       
  1712 EXPORT_C TInt RPropertyRef::Define(TInt aAttr, const TSecurityPolicy& aReadPolicy, const TSecurityPolicy& aWritePolicy, TInt aPreallocate, DProcess* aProcess)
       
  1713 	{
       
  1714 	CHECK_PRECONDITIONS(MASK_THREAD_CRITICAL,"RPropertyRef::Define");			
       
  1715 	__PS_ASSERT(iProp);
       
  1716 	
       
  1717 	if(aPreallocate < 0)
       
  1718 		return KErrArgument;
       
  1719 	if(aPreallocate > RProperty::KMaxLargePropertySize)
       
  1720 		return KErrTooBig;
       
  1721 
       
  1722 	TPropertyInfo info;
       
  1723 	info.iType = (RProperty::TType)(aAttr & RProperty::ETypeMask);
       
  1724 	info.iAttr = (aAttr & ~RProperty::ETypeMask);
       
  1725 	info.iSize = (TUint16) aPreallocate;
       
  1726 	info.iReadPolicy = aReadPolicy;
       
  1727 	info.iWritePolicy = aWritePolicy;
       
  1728 	return iProp->Define(&info, aProcess);
       
  1729 	}
       
  1730 
       
  1731 /** Deletes the property.
       
  1732 
       
  1733 	Any pending subscriptions for this property will be completed with KErrNotFound.
       
  1734 	Any new request will not complete until the property is defined and published again.
       
  1735 
       
  1736 	@param aProcess The process whoes security attributes will be used for security checks.
       
  1737 					If NULL the security checks will not be performed.
       
  1738 
       
  1739 	@return KErrNone, if the delete succeeds;
       
  1740             KErrNotFound, if the property has not been defined;
       
  1741 			KErrPermissionDenied, if aProcess is specified and is not the owner
       
  1742 			of the process.
       
  1743 			
       
  1744 	@pre Calling thread must be in a critical section.
       
  1745 	@pre Property has been opened.
       
  1746 	@pre Call in a thread context.
       
  1747 	@pre Kernel must be unlocked.
       
  1748 	@pre interrupts enabled
       
  1749 	@pre No fast mutex can be held
       
  1750 
       
  1751 	@post Calling thread is in a critical section.
       
  1752 */
       
  1753 	
       
  1754 EXPORT_C TInt RPropertyRef::Delete(DProcess* aProcess)
       
  1755 	{
       
  1756 	CHECK_PRECONDITIONS(MASK_THREAD_CRITICAL,"RPropertyRef::Delete");			
       
  1757 	__PS_ASSERT(iProp);
       
  1758 	return iProp->Delete(aProcess);
       
  1759 	}
       
  1760 
       
  1761 /** Requests notification when the property is changed.
       
  1762 
       
  1763 	If the property has not been defined, the request will not complete until the property
       
  1764 	is defined and published.
       
  1765 
       
  1766 	Only one subscription per TPropertySubsRequest object is allowed.
       
  1767 
       
  1768 	@param aReq Specifies this request.
       
  1769 	@param aProcess The process whoes security attributes will be used for security checks.
       
  1770 					If NULL the security checks will not be performed.
       
  1771 
       
  1772 	@return KErrNone, if the subcribe action succeeds.
       
  1773 
       
  1774 	@pre Property has been opened.
       
  1775 */
       
  1776 EXPORT_C TInt RPropertyRef::Subscribe(TPropertySubsRequest& aReq, DProcess* aProcess)
       
  1777 	{
       
  1778 	__PS_ASSERT(iProp);
       
  1779 	NKern::LockSystem();
       
  1780 	TInt r = iProp->Subscribe(&aReq, aProcess);
       
  1781 	__PS_ASSERT(r != KErrInUse);
       
  1782 	return r;
       
  1783 	}
       
  1784 
       
  1785 /** Cancels a subscription request originally made with RPropertyRef::Subscribe().
       
  1786 
       
  1787 	@param aReq The TPropertySubsRequest object used in the original subscribe request.
       
  1788 
       
  1789 	@pre Property has been opened.
       
  1790 
       
  1791 	@see RPropertyRef::Subscribe()
       
  1792 */
       
  1793 EXPORT_C void RPropertyRef::Cancel(TPropertySubsRequest& aReq)
       
  1794 	{
       
  1795 	__PS_ASSERT(iProp);
       
  1796 	NKern::LockSystem();
       
  1797 	iProp->Cancel(&aReq);
       
  1798 	}
       
  1799 
       
  1800 /** Retrieves (reads) the value of an integer property.
       
  1801 
       
  1802 	@param aValue An integer to hold the returned property value
       
  1803 	@param aProcess The process whose security attributes will be used for security checks.
       
  1804 					If NULL the security checks will not be performed.
       
  1805 
       
  1806 	@return KErrNotFound, if the property has not been defined;
       
  1807 			KErrPermissionDenied, if aProcess does not have the read capabilities;
       
  1808 			KErrArgument, if the property is not of type EInt;
       
  1809 			KErrNone, if the property was read succesfully.
       
  1810 
       
  1811 	@pre Property has been opened.
       
  1812 
       
  1813 	@realtime
       
  1814 */
       
  1815 EXPORT_C TInt RPropertyRef::Get(TInt& aValue, DProcess* aProcess)
       
  1816 	{
       
  1817 	__PS_ASSERT(iProp);
       
  1818 	NKern::LockSystem();
       
  1819 	return iProp->GetI(&aValue, aProcess);
       
  1820 	}
       
  1821 
       
  1822 /** Publishes (writes) the value of an integer property.
       
  1823 
       
  1824 	@param aValue The new value for the property.
       
  1825 	@param aProcess The process whose security attributes will be used for security checks.
       
  1826 					If NULL the security checks will not be performed.
       
  1827 
       
  1828 	@return KErrNotFound, if the property has not been defined;
       
  1829 			KErrPermissionDenied, if aProcess does not have the write capabilities;
       
  1830 			KErrArgument, if the property is not of type EInt;
       
  1831 			KErrNone, if the property was set succesfully.
       
  1832 
       
  1833 	@pre Property has been opened.
       
  1834 
       
  1835 	@realtime
       
  1836 */
       
  1837 EXPORT_C TInt RPropertyRef::Set(TInt aValue, DProcess* aProcess)
       
  1838 	{
       
  1839 	__PS_ASSERT(iProp);
       
  1840 	NKern::LockSystem();
       
  1841 	return iProp->SetI(aValue, aProcess);
       
  1842 	}
       
  1843 	
       
  1844 /** Retrieves (reads) the value of a binary property.
       
  1845 
       
  1846 	@param aDes A descriptor to hold the returned property value.
       
  1847 	@param aProcess The process whose security attributes will be used for security checks.
       
  1848 					If NULL the security checks will not be performed.
       
  1849 
       
  1850 	@return KErrNotFound, if the property has not been defined;
       
  1851 			KErrPermissionDenied, if aProcess does not have the read capabilities;
       
  1852 			KErrArgument, if the property is not of type EByteArray;
       
  1853 			KErrOverflow, if the property is larger than the maximum size of aDes,
       
  1854             in which case aDes is filled with as much of the property value that will fit;
       
  1855 			KErrNone, if the property was read succesfully.
       
  1856 
       
  1857 	@pre Property has been opened.
       
  1858 
       
  1859 	@realtime There are real time guarantees if the property is not large.
       
  1860 */
       
  1861 EXPORT_C TInt RPropertyRef::Get(TDes8& aDes, DProcess* aProcess)
       
  1862 	{
       
  1863 	__PS_ASSERT(iProp);
       
  1864 	TInt size = aDes.MaxSize();
       
  1865 	NKern::LockSystem();
       
  1866 	TInt r = iProp->GetB((TUint8*) aDes.Ptr(), &size, aProcess, EFalse);
       
  1867 	if ((r == KErrNone) || (r == KErrOverflow))
       
  1868 		{
       
  1869 		aDes.SetLength(size);
       
  1870 		}
       
  1871 	return r;
       
  1872 	}
       
  1873 
       
  1874 /** Publishes (writes) the value of a binary property.
       
  1875 
       
  1876 	@param aDes The new value for the property.
       
  1877 	@param aProcess The process whoes security attributes will be used for security checks.
       
  1878 					If NULL the security checks will not be performed.
       
  1879 
       
  1880 	@return KErrNotFound, if the property has not been defined;
       
  1881 			KErrPermissionDenied, if aProcess does not have the write capabilities;
       
  1882 			KErrArgument, if the property is not of type EByteArray;
       
  1883 			KErrTooBig, if the property is larger than KMaxPropertySize;
       
  1884 			KErrNone, if the property was set succesfully.
       
  1885 
       
  1886 	@pre Property has been opened.
       
  1887 
       
  1888 	@realtime There are realtime guarantees if the property is not large
       
  1889 	          and the size is not greater than the previously published value.
       
  1890 */
       
  1891 EXPORT_C TInt RPropertyRef::Set(const TDesC8& aDes, DProcess* aProcess)
       
  1892 	{
       
  1893 	__PS_ASSERT(iProp);
       
  1894 	NKern::LockSystem();
       
  1895 	return iProp->SetB((TUint8*) aDes.Ptr(), aDes.Size(), aProcess, EFalse);
       
  1896 	}
       
  1897 
       
  1898 /** Gets property status information.
       
  1899 	
       
  1900 	@param aStatus property status output.
       
  1901 
       
  1902 	@return ETrue if the property is defined; otherwise, EFalse.
       
  1903 
       
  1904 	@pre System must be locked.
       
  1905 	@pre Property has been opened.
       
  1906 
       
  1907 	@post System is locked.
       
  1908 */
       
  1909 EXPORT_C TBool RPropertyRef::GetStatus(TPropertyStatus& aStatus)
       
  1910 	{
       
  1911 	CHECK_PRECONDITIONS(MASK_SYSTEM_LOCKED,"RPropertyRef::GetStatus");			
       
  1912 	__PS_ASSERT(iProp);
       
  1913 	aStatus.iType			= iProp->Type();
       
  1914 	aStatus.iAttr			= 0;
       
  1915 	aStatus.iOwner			= iProp->Owner();
       
  1916 	return iProp->IsDefined();
       
  1917 	}