|
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 } |