|
1 // PropertyAccess.cpp |
|
2 // |
|
3 // Copyright (c) 2010 Accenture. All rights reserved. |
|
4 // This component and the accompanying materials are made available |
|
5 // under the terms of the "Eclipse Public License v1.0" |
|
6 // which accompanies this distribution, and is available |
|
7 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 // |
|
9 // Initial Contributors: |
|
10 // Accenture - Initial contribution |
|
11 // |
|
12 #include <fshell/common.mmh> |
|
13 #include <e32cmn.h> |
|
14 #include <fshell/extrabtrace.h> |
|
15 |
|
16 #include <kernel.h> |
|
17 #include <kern_priv.h> |
|
18 #include "memoryaccess.h" |
|
19 #include "PropertyAccess.h" |
|
20 |
|
21 DPropertyAccess::DPropertyAccess(DThread* aClient) |
|
22 : iClient(aClient) |
|
23 { |
|
24 } |
|
25 |
|
26 TInt DPropertyAccess::HandleProperty(TInt aFunction, TAny* aParams, TAny* aVal) |
|
27 { |
|
28 return DoHandleProperty(iClient, aFunction, aParams, aVal); |
|
29 } |
|
30 |
|
31 TInt DPropertyAccess::DoHandleProperty(DThread* aClient, TInt aFunction, TAny* aParams, TAny* aVal) |
|
32 { |
|
33 if (aFunction == RMemoryAccess::EControlPropertyNotify) |
|
34 { |
|
35 if (iNotifyClientStatus) return KErrAlreadyExists; |
|
36 iNotifyClientStatus = (TRequestStatus*)aVal; |
|
37 iClientNotifyPtr = aParams; |
|
38 return KErrNone; |
|
39 } |
|
40 else if (aFunction == RMemoryAccess::EControlPropertyNotifyCancel) |
|
41 { |
|
42 CancelNotifys(); |
|
43 return KErrNone; |
|
44 } |
|
45 |
|
46 TInt err; |
|
47 TProp clientParams; |
|
48 err = Kern::ThreadRawRead(aClient, aParams, &clientParams, sizeof(TProp)); |
|
49 if (err) |
|
50 { |
|
51 return err; |
|
52 } |
|
53 //Kern::Printf("HandleProperty %d, iDefine=%d iCat=0x%x iKey=%d", aFunction, clientParams.iDefine, clientParams.iCategory, clientParams.iKey); |
|
54 |
|
55 NKern::ThreadEnterCS(); |
|
56 RPropertyRef property; |
|
57 err = property.Open(clientParams.iCategory, clientParams.iKey); |
|
58 //Kern::Printf("HandleProperty Open ret=%d", err); |
|
59 if (!err) |
|
60 { |
|
61 // Check if it exists but isn't defined (and if it isn't, treat it the same as if it didn't exist) |
|
62 TPropertyStatus stat; |
|
63 NKern::LockSystem(); |
|
64 TBool defined = property.GetStatus(stat); |
|
65 NKern::UnlockSystem(); |
|
66 if (!defined) |
|
67 { |
|
68 property.Close(); |
|
69 err = KErrNotFound; |
|
70 } |
|
71 } |
|
72 |
|
73 if (err == KErrNotFound && clientParams.iDefine && (aFunction == RMemoryAccess::EControlSetPropertyDesc || aFunction == RMemoryAccess::EControlSetPropertyInt)) |
|
74 { |
|
75 err = property.Attach(clientParams.iCategory, clientParams.iKey); |
|
76 TInt attr = (aFunction == RMemoryAccess::EControlSetPropertyInt) ? RProperty::EInt : RProperty::EByteArray; |
|
77 _LIT_SECURITY_POLICY_PASS(KPass); |
|
78 if (!err) err = property.Define(attr, KPass, KPass); |
|
79 } |
|
80 NKern::ThreadLeaveCS(); |
|
81 if (err) |
|
82 { |
|
83 return err; |
|
84 } |
|
85 |
|
86 switch (aFunction) |
|
87 { |
|
88 case RMemoryAccess::EControlGetPropertyInt: |
|
89 { |
|
90 TInt val; |
|
91 err = property.Get(val); |
|
92 if (!err) |
|
93 { |
|
94 TPckg<TInt> valBuf(val); |
|
95 err = Kern::ThreadDesWrite(aClient, aVal, valBuf, 0); |
|
96 } |
|
97 break; |
|
98 } |
|
99 case RMemoryAccess::EControlGetPropertyDesc: |
|
100 { |
|
101 err = Kern::ThreadGetDesMaxLength(aClient, aVal); |
|
102 TInt size = err; |
|
103 if (size < 0) break; |
|
104 |
|
105 NKern::ThreadEnterCS(); |
|
106 HBuf8* buf = HBuf8::New(size); |
|
107 if (!buf) |
|
108 { |
|
109 err = KErrNoMemory; |
|
110 NKern::ThreadLeaveCS(); |
|
111 break; |
|
112 } |
|
113 err = property.Get(*buf); |
|
114 if (!err || err == KErrOverflow) |
|
115 { |
|
116 TInt writeerr = Kern::ThreadDesWrite(aClient, aVal, *buf, 0, NULL); |
|
117 if (writeerr) err = writeerr; |
|
118 } |
|
119 delete buf; |
|
120 NKern::ThreadLeaveCS(); |
|
121 if (err == KErrOverflow) |
|
122 { |
|
123 NKern::LockSystem(); |
|
124 TPropertyStatus status; |
|
125 property.GetStatus(status); |
|
126 NKern::UnlockSystem(); |
|
127 |
|
128 clientParams.iActualSize = status.iSize; |
|
129 err = Kern::ThreadRawWrite(aClient, aParams, (TAny*)&clientParams, sizeof(TProp)); |
|
130 } |
|
131 break; |
|
132 } |
|
133 case RMemoryAccess::EControlSetPropertyInt: |
|
134 { |
|
135 err = property.Set((TInt)aVal); |
|
136 break; |
|
137 } |
|
138 case RMemoryAccess::EControlSetPropertyDesc: |
|
139 { |
|
140 err = Kern::ThreadGetDesLength(aClient, aVal); |
|
141 TInt size = err; |
|
142 if (size < 0) break; |
|
143 |
|
144 NKern::ThreadEnterCS(); |
|
145 HBuf8* buf = HBuf8::New(size); |
|
146 if (!buf) |
|
147 { |
|
148 err = KErrNoMemory; |
|
149 NKern::ThreadLeaveCS(); |
|
150 break; |
|
151 } |
|
152 buf->SetLength(size); |
|
153 err = Kern::ThreadDesRead(aClient, aVal, *buf, 0); |
|
154 if (!err) |
|
155 { |
|
156 err = property.Set(*buf); |
|
157 } |
|
158 delete buf; |
|
159 NKern::ThreadLeaveCS(); |
|
160 break; |
|
161 } |
|
162 case RMemoryAccess::EControlDeleteProperty: |
|
163 NKern::ThreadEnterCS(); |
|
164 err = property.Delete(); |
|
165 NKern::ThreadLeaveCS(); |
|
166 break; |
|
167 case RMemoryAccess::EControlSubscribeToProperty: |
|
168 { |
|
169 TBool useBtrace = (TBool)aVal; |
|
170 TNotifyRequest* req = new TNotifyRequest(&PropertyChanged, clientParams.iCategory, clientParams.iKey, this, useBtrace); |
|
171 err = req->iProperty.Attach(clientParams.iCategory, clientParams.iKey); // Allow non-existant properties |
|
172 if (!err) |
|
173 { |
|
174 err = req->iProperty.Subscribe(req->iRequest); |
|
175 if (err) |
|
176 { |
|
177 // Don't think this will ever happen |
|
178 req->iProperty.Close(); |
|
179 req->iRequest.iPtr = NULL; |
|
180 } |
|
181 } |
|
182 if (err) |
|
183 { |
|
184 delete req; |
|
185 } |
|
186 else |
|
187 { |
|
188 iRequests.Add(&req->iLink); |
|
189 } |
|
190 } |
|
191 break; |
|
192 default: |
|
193 break; |
|
194 } |
|
195 |
|
196 NKern::ThreadEnterCS(); |
|
197 property.Close(); |
|
198 NKern::ThreadLeaveCS(); |
|
199 return err; |
|
200 } |
|
201 |
|
202 DPropertyAccess::~DPropertyAccess() |
|
203 { |
|
204 CancelNotifys(); |
|
205 } |
|
206 |
|
207 void DPropertyAccess::CancelNotifys() |
|
208 { |
|
209 for (SDblQueLink* link = iRequests.First(); link != NULL && link != &iRequests.iA;) |
|
210 { |
|
211 TNotifyRequest* request = _LOFF(link, TNotifyRequest, iLink); |
|
212 link=link->iNext; // Do this before anything else because we'll be deleting the TNotifyRequest |
|
213 request->iProperty.Cancel(request->iRequest); |
|
214 request->iProperty.Close(); |
|
215 delete request; |
|
216 } |
|
217 |
|
218 if (iNotifyClientStatus) |
|
219 { |
|
220 Kern::RequestComplete(iClient, iNotifyClientStatus, KErrCancel); |
|
221 } |
|
222 iClientNotifyPtr = NULL; |
|
223 } |
|
224 |
|
225 void DPropertyAccess::PropertyChanged(TAny* aPtr, TInt aReason) |
|
226 { |
|
227 TNotifyRequest* req = static_cast<TNotifyRequest*>(aPtr); |
|
228 req->iPropertyAccess->DoPropertyChanged(*req, aReason); |
|
229 } |
|
230 |
|
231 void DPropertyAccess::DoPropertyChanged(TNotifyRequest& aRequest, TInt aReason) |
|
232 { |
|
233 // First, rerequest |
|
234 if (aReason == KErrNone) |
|
235 { |
|
236 aRequest.iProperty.Subscribe(aRequest.iRequest); |
|
237 } |
|
238 // Then try and notify |
|
239 if (iNotifyClientStatus && !aRequest.iBtrace) |
|
240 { |
|
241 TPropNotifyResult result; |
|
242 result.iCategory = aRequest.iCat.iUid; |
|
243 result.iKey = aRequest.iKey; |
|
244 result.iMissedChanges = iMissedChanges; |
|
245 result.iError = aReason; |
|
246 iMissedChanges = 0; // No need to lock/safeswap because we run in the context of the pubsub DFC |
|
247 TInt err = Kern::ThreadRawWrite(iClient, iClientNotifyPtr, &result, sizeof(TPropNotifyResult)); |
|
248 Kern::RequestComplete(iClient, iNotifyClientStatus, err); |
|
249 } |
|
250 else if (aRequest.iBtrace) |
|
251 { |
|
252 #ifdef FSHELL_TRACE_SUPPORT |
|
253 TUint cat = aRequest.iCat.iUid; |
|
254 TUint key = aRequest.iKey; |
|
255 |
|
256 TInt intVal; |
|
257 TInt err = aRequest.iProperty.Get(intVal); |
|
258 if (err == KErrNone) |
|
259 { |
|
260 BTrace12(ExtraBTrace::EPubSub, ExtraBTrace::EPubSubIntPropertyChanged, cat, key, intVal); |
|
261 } |
|
262 else if (err == KErrArgument) |
|
263 { |
|
264 TBuf8<KMaxBTraceDataArray> buf; // No point using larger buffer, as this is the max we can output over btrace (80 bytes) |
|
265 err = aRequest.iProperty.Get(buf); |
|
266 if (err == KErrNone || err == KErrOverflow) |
|
267 { |
|
268 BTraceN(ExtraBTrace::EPubSub, ExtraBTrace::EPubSubDataPropertyChanged, cat, key, buf.Ptr(), buf.Length()); |
|
269 } |
|
270 } |
|
271 #endif |
|
272 } |
|
273 else |
|
274 { |
|
275 iMissedChanges++; |
|
276 } |
|
277 } |