|
1 /* |
|
2 * Copyright (c) 2009 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "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 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 #include "CdlCustomisation.h" |
|
18 #include "CCdlEngine.h" |
|
19 #include <f32file.h> |
|
20 |
|
21 const TInt KCustomisationStackGranularity = 2; |
|
22 |
|
23 const TUint32 KCdlInstanceFlagIsComplete = 0x1; |
|
24 |
|
25 // |
|
26 // CCdlInstance |
|
27 // |
|
28 |
|
29 EXPORT_C CCdlInstance* CCdlInstance::NewL(const TCdlRef& aRef, |
|
30 const SCdlInterface* aInterfaceParams, |
|
31 const CCdlInstance* aSubLayer, |
|
32 CCdlEngine* aEngine, |
|
33 TInt* aLastApi) |
|
34 { |
|
35 CCdlInstance* self = NewLC(aRef, aInterfaceParams, aSubLayer, aEngine, aLastApi); |
|
36 CleanupStack::Pop(self); |
|
37 return self; |
|
38 } |
|
39 |
|
40 EXPORT_C CCdlInstance* CCdlInstance::NewLC(const TCdlRef& aRef, |
|
41 const SCdlInterface* aInterfaceParams, |
|
42 const CCdlInstance* aSubLayer, |
|
43 CCdlEngine* aEngine, |
|
44 TInt* aLastApi) |
|
45 { |
|
46 // get/create the CDL engine, if necessary |
|
47 TBool pushed = EFalse; |
|
48 if (!aEngine) |
|
49 aEngine = CCdlEngine::InstanceLC(pushed); |
|
50 // get the last API ref, if necessary |
|
51 if (!aLastApi) |
|
52 aLastApi = aEngine->LastApiRefL(aInterfaceParams->iUid); |
|
53 // CCdlDllInstance is the only appropriate concrete implementation of CCdlInstance, so create one. |
|
54 // Note, when other imlementation types become available, there will need to be a descision here about |
|
55 // what implementation type is required |
|
56 CCdlDllInstance* self = new(ELeave) CCdlDllInstance(aRef, aSubLayer, aEngine, aLastApi); |
|
57 // engine will be owned by the instance if it was created |
|
58 if (pushed) |
|
59 CleanupStack::Pop(aEngine); |
|
60 // finish construction. Again, this may depend on implementation type. |
|
61 CleanupStack::PushL(self); |
|
62 self->ConstructL(aInterfaceParams->iFlags & KCdlFlagRomOnly, aInterfaceParams->iApiSize); |
|
63 return self; |
|
64 } |
|
65 |
|
66 CCdlInstance::CCdlInstance(CCdlEngine* aEngine, TInt* aLastApi) |
|
67 : CCdlEngineRef(aEngine), iLastApi(*aLastApi) |
|
68 { |
|
69 } |
|
70 |
|
71 EXPORT_C TAny* CCdlInstance::GetData(TInt aCdlApiId) const |
|
72 { |
|
73 iLastApi = aCdlApiId; |
|
74 ((CCdlEngine*)Engine())->SetLastApiId(aCdlApiId); |
|
75 return Implementor(aCdlApiId)->Implementation(aCdlApiId); |
|
76 } |
|
77 |
|
78 EXPORT_C TCdlEngineFunc* CCdlInstance::GetFunction(TInt aCdlApiId) const |
|
79 { |
|
80 iLastApi = aCdlApiId; |
|
81 ((CCdlEngine*)Engine())->SetLastApiId(aCdlApiId); |
|
82 const CCdlInstance* inst = this; |
|
83 TCdlEngineFunc* func = 0; |
|
84 do |
|
85 { |
|
86 if (aCdlApiId < inst->Interface().iApiSize) |
|
87 func = (TCdlEngineFunc*)(inst->Implementation(aCdlApiId)); |
|
88 inst = inst->iSubLayer; |
|
89 } while (!func && inst); |
|
90 __ASSERT_ALWAYS(func, Panic(ECdlEngPanic_NoImplementation)); |
|
91 return func; |
|
92 } |
|
93 |
|
94 const CCdlInstance* CCdlInstance::Implementor(TInt aCdlApiId) const |
|
95 { |
|
96 if (aCdlApiId < Interface().iApiSize && Implementation(aCdlApiId)) |
|
97 return this; |
|
98 __ASSERT_ALWAYS(iSubLayer, Panic(ECdlEngPanic_NoImplementation)); |
|
99 return iSubLayer->Implementor(aCdlApiId); |
|
100 } |
|
101 |
|
102 EXPORT_C const TCdlRef& CCdlInstance::Ref() const |
|
103 { |
|
104 return iRef; |
|
105 } |
|
106 |
|
107 EXPORT_C const CCdlInstance* CCdlInstance::SubLayer() const |
|
108 { |
|
109 return iSubLayer; |
|
110 } |
|
111 |
|
112 EXPORT_C const TCdlRef& CCdlInstance::LastAccessedRef() const |
|
113 { |
|
114 return Implementor(iLastApi)->Ref(); |
|
115 } |
|
116 |
|
117 EXPORT_C void CCdlInstance::FileNameRelativeToLastAccessedInstance(TFileName& aFileName) const |
|
118 { |
|
119 TParse parse; |
|
120 parse.Set(aFileName, LastAccessedRef().iName, NULL); |
|
121 aFileName = parse.FullName(); |
|
122 } |
|
123 |
|
124 EXPORT_C TBool CCdlInstance::operator==(const CCdlInstance& aOther) const |
|
125 { |
|
126 return iRef.iId == aOther.iRef.iId && CdlEngine::CompareNames(*iRef.iName, *aOther.iRef.iName) == 0; |
|
127 } |
|
128 |
|
129 TAny* CCdlInstance::Extension(TInt /*aId*/) const |
|
130 { |
|
131 return NULL; |
|
132 } |
|
133 |
|
134 |
|
135 // |
|
136 // CCdlDllInstance |
|
137 // |
|
138 |
|
139 CCdlDllInstance::CCdlDllInstance(const TCdlRef& aRef, const CCdlInstance* aSubLayer, CCdlEngine* aEngine, TInt* aLastApi) |
|
140 : CCdlInstance(aEngine, aLastApi) |
|
141 { |
|
142 iRef = aRef; |
|
143 iSubLayer = aSubLayer; |
|
144 __ASSERT_ALWAYS(!iSubLayer || iSubLayer->Ref().iUid == aRef.iUid, Panic(ECdlEngPanic_IncompatibleSubLayer)); |
|
145 } |
|
146 |
|
147 CCdlDllInstance::~CCdlDllInstance() |
|
148 { |
|
149 iLib.Close(); |
|
150 } |
|
151 |
|
152 void CCdlDllInstance::ConstructL(TBool aRomOnly, TInt aApiSize) |
|
153 { |
|
154 CCdlLibManager* libMan = Engine()->LibMan(); |
|
155 |
|
156 |
|
157 // get the filename pointer, so that it can have drive name added if necessary |
|
158 const TDesC* name = iRef.iName; |
|
159 TFileName tempName; |
|
160 // first look if the library is already loaded |
|
161 RCdlLibrary* lib = libMan->FindLib(*name); |
|
162 if (lib) |
|
163 { |
|
164 // get the name from the library, it will be sure to have the drive letter present |
|
165 name = lib->FullName(); |
|
166 } |
|
167 else |
|
168 { |
|
169 // library is not loaded |
|
170 if ((*name)[1] != ':') // test if the filename is missing a drive letter |
|
171 { |
|
172 // get the drive for this plugin |
|
173 TDriveUnit drive; |
|
174 User::LeaveIfError(Engine()->PluginDrive(*name, drive)); |
|
175 // build the new filename and set the pointer to it |
|
176 tempName = drive.Name(); |
|
177 tempName.Append(*name); |
|
178 name = &tempName; |
|
179 } |
|
180 } |
|
181 |
|
182 // for CDL/ECom, test the ROM status before loading. .DLL loading |
|
183 // tests ROM status during load. |
|
184 #ifdef RD_SECURE_BIN_RES |
|
185 if (RCdlLibrary::CheckIfNotRomOnly(aRomOnly, *name)) |
|
186 { |
|
187 User::Leave(KErrAccessDenied); |
|
188 } |
|
189 #endif |
|
190 |
|
191 // get the library |
|
192 iLib = libMan->LoadL(*name, lib, aRomOnly); |
|
193 lib = iLib.Lib(); |
|
194 iRef.iName = lib->FullName(); |
|
195 |
|
196 // get the customisation data for this instance |
|
197 const SCdlCustomisation* cust = lib->CustomisationL(iRef.iUid, iRef.iId); |
|
198 |
|
199 // get the table of pointers |
|
200 iApi = (TAny**)(cust->iImpl); |
|
201 |
|
202 // get the interface |
|
203 iInterface = cust->iInterface; |
|
204 |
|
205 // find out if this implementation is complete |
|
206 SetIsCompleteFlag(aApiSize); |
|
207 |
|
208 // Check that instances with no sub-layer are fully implemented |
|
209 if (!iSubLayer && !IsComplete()) |
|
210 User::Leave(KErrCorrupt); |
|
211 } |
|
212 |
|
213 void CCdlDllInstance::SetIsCompleteFlag(TInt aRequiredApiSize) |
|
214 { |
|
215 if (iInterface->iApiSize >= aRequiredApiSize) |
|
216 { |
|
217 iFlags |= KCdlInstanceFlagIsComplete; |
|
218 TAny** pApi = iApi; |
|
219 TAny** end = iApi + iInterface->iApiSize; |
|
220 for (; pApi != end; ++pApi) |
|
221 { |
|
222 if (!*pApi) |
|
223 { |
|
224 iFlags &= ~KCdlInstanceFlagIsComplete; |
|
225 break; |
|
226 } |
|
227 } |
|
228 } |
|
229 else |
|
230 { |
|
231 iFlags &= ~KCdlInstanceFlagIsComplete; |
|
232 } |
|
233 } |
|
234 |
|
235 const RCdlLibRef& CCdlDllInstance::Lib() const |
|
236 { |
|
237 return iLib; |
|
238 } |
|
239 |
|
240 TBool CCdlDllInstance::IsComplete() const |
|
241 { |
|
242 return iFlags & KCdlInstanceFlagIsComplete; |
|
243 } |
|
244 |
|
245 TAny* CCdlDllInstance::Implementation(TInt aCdlApiId) const |
|
246 { |
|
247 return iApi[aCdlApiId]; |
|
248 } |
|
249 |
|
250 const SCdlInterface& CCdlDllInstance::Interface() const |
|
251 { |
|
252 return *iInterface; |
|
253 } |
|
254 |
|
255 |
|
256 // |
|
257 // CCdlInstanceProxy |
|
258 // |
|
259 |
|
260 CCdlInstanceProxy::CCdlInstanceProxy(CCdlEngine* aEngine, TInt* aLastApi) |
|
261 : CCdlInstance(aEngine, aLastApi) |
|
262 { |
|
263 } |
|
264 |
|
265 void CCdlInstanceProxy::Set(const CCdlInstance& aInst) |
|
266 { |
|
267 iInst = &aInst; |
|
268 iRef = iInst->Ref(); |
|
269 iSubLayer = iInst->SubLayer(); |
|
270 } |
|
271 |
|
272 TBool CCdlInstanceProxy::IsComplete() const |
|
273 { |
|
274 __ASSERT_ALWAYS(iInst, Panic(ECdlEngPanic_ProxyNotInitialised)); |
|
275 return iInst->IsComplete(); |
|
276 } |
|
277 |
|
278 TAny* CCdlInstanceProxy::Implementation(TInt aCdlApiId) const |
|
279 { |
|
280 __ASSERT_ALWAYS(iInst, Panic(ECdlEngPanic_ProxyNotInitialised)); |
|
281 return iInst->Implementation(aCdlApiId); |
|
282 } |
|
283 |
|
284 const SCdlInterface& CCdlInstanceProxy::Interface() const |
|
285 { |
|
286 __ASSERT_ALWAYS(iInst, Panic(ECdlEngPanic_ProxyNotInitialised)); |
|
287 return iInst->Interface(); |
|
288 } |
|
289 |
|
290 |
|
291 // |
|
292 // CCdlCustomisationStack |
|
293 // |
|
294 |
|
295 CCdlCustomisationStack* CCdlCustomisationStack::NewLC(TUid aCdlUid, CCdlEngine* aEngine) |
|
296 { |
|
297 CCdlCustomisationStack* self = new(ELeave) CCdlCustomisationStack(aCdlUid, aEngine); |
|
298 CleanupStack::PushL(self); |
|
299 self->ConstructL(); |
|
300 return self; |
|
301 } |
|
302 |
|
303 CCdlCustomisationStack::~CCdlCustomisationStack() |
|
304 { |
|
305 delete iTopProxy; |
|
306 iStack.ResetAndDestroy(); |
|
307 } |
|
308 |
|
309 const CCdlInstance* CCdlCustomisationStack::LastAccessedInstance() const |
|
310 { |
|
311 __ASSERT_ALWAYS(iTop, Panic(ECdlEngPanic_NoInstanceLoaded)); |
|
312 return iTop->Implementor(iLastApiId); |
|
313 } |
|
314 |
|
315 CCdlCustomisationStack::CCdlCustomisationStack(TUid aUid, CCdlEngine* aEngine) |
|
316 : iUid(aUid), iStack(KCustomisationStackGranularity), |
|
317 iGlobalCustomisationEnabled(ETrue), iEngine(aEngine) |
|
318 { |
|
319 } |
|
320 |
|
321 void CCdlCustomisationStack::ConstructL() |
|
322 { |
|
323 iTopProxy = new(ELeave) CCdlInstanceProxy(iEngine, &iLastApiId); |
|
324 iTopProxy->ReleaseRef(); // we don't want a reference to the engine owned by engine |
|
325 } |
|
326 |
|
327 void CCdlCustomisationStack::RequireCustomisationL(const SCdlInterface* aInterfaceParams) |
|
328 { |
|
329 if (!iInterfaceParams) |
|
330 iInterfaceParams = aInterfaceParams; |
|
331 else if (CompareInterfaces(aInterfaceParams, iInterfaceParams) > 0) |
|
332 User::Leave(KErrNotSupported); |
|
333 } |
|
334 |
|
335 void CCdlCustomisationStack::ClearOverrides() |
|
336 { |
|
337 if (iTop) |
|
338 { |
|
339 Delete(1, iStack.Count()-1); // remove everything but the base |
|
340 iTop = iStack[0]; |
|
341 iTopProxy->Set(*iTop); |
|
342 } |
|
343 } |
|
344 |
|
345 void CCdlCustomisationStack::LoadCustomisationL(const TCdlRef& aRef) |
|
346 { |
|
347 CCdlInstance* cust = NewInstanceLC(aRef); |
|
348 if (InstanceCanBeBase(cust)) |
|
349 { // this customisation is sufficient to form a new base and doesn't change ROM-only flag |
|
350 NewBaseL(cust); |
|
351 CleanupStack::Pop(cust); |
|
352 } |
|
353 else if (!iTop) |
|
354 { // there must be an existing base before this customisation can be used |
|
355 User::Leave(KErrCorrupt); |
|
356 } |
|
357 else if (*cust == *iTop) |
|
358 { // don't layer the same customisation over itself - no point |
|
359 CleanupStack::PopAndDestroy(cust); |
|
360 } |
|
361 else |
|
362 { // this is a partial customisation |
|
363 PushCustL(cust); |
|
364 CleanupStack::Pop(cust); |
|
365 } |
|
366 } |
|
367 |
|
368 CCdlInstance* CCdlCustomisationStack::NewInstanceLC(const TCdlRef& aRef) |
|
369 { |
|
370 // these temporary params are only used when no interface has been set |
|
371 SCdlInterface tempParams = |
|
372 { |
|
373 0, // iMajorEngVer |
|
374 0, // iMinorEngVer |
|
375 0, // iName |
|
376 {aRef.iUid.iUid}, // iUid |
|
377 0, // iMajorVer |
|
378 0, // iMinorVer |
|
379 0, // iFlags |
|
380 0 // iApiSize |
|
381 }; |
|
382 const SCdlInterface* iface = iInterfaceParams ? iInterfaceParams : &tempParams; |
|
383 return CCdlInstance::NewLC(aRef, iface, iTop, iEngine, &iLastApiId); |
|
384 } |
|
385 |
|
386 const CCdlInstance& CCdlCustomisationStack::Top() const |
|
387 { |
|
388 return *iTopProxy; |
|
389 } |
|
390 |
|
391 TInt* CCdlCustomisationStack::LastApiRef() const |
|
392 { |
|
393 return &iLastApiId; |
|
394 } |
|
395 |
|
396 void CCdlCustomisationStack::NewBaseL(CCdlInstance* aBase) |
|
397 { |
|
398 PushCustL(aBase); |
|
399 iInterfaceParams = &aBase->Interface(); |
|
400 Delete(0, iStack.Count()-1); // remove everything but the new base |
|
401 } |
|
402 |
|
403 void CCdlCustomisationStack::PushCustL(CCdlInstance* aCust) |
|
404 { |
|
405 iStack.AppendL(aCust); |
|
406 aCust->ReleaseRef(); // we don't want a reference to the engine owned by engine |
|
407 iTop = aCust; |
|
408 iTopProxy->Set(*iTop); |
|
409 } |
|
410 |
|
411 void CCdlCustomisationStack::Delete(TInt aPos, TInt aCount) |
|
412 { |
|
413 for (TInt ii=0; ii<aCount; ii++) |
|
414 delete iStack[aPos+ii]; |
|
415 iStack.Delete(aPos, aCount); |
|
416 } |
|
417 |
|
418 TBool CCdlCustomisationStack::IsCustomisationStarted(const SCdlInterface* aInterfaceParams) const |
|
419 { |
|
420 TBool apiIsSupported = (CompareInterfaces(iInterfaceParams, aInterfaceParams) >= 0); |
|
421 return iTop && apiIsSupported; |
|
422 } |
|
423 |
|
424 // this returns 0 for same, >0 for aLeft better than aRight and <0 otherwise |
|
425 TInt CCdlCustomisationStack::CompareInterfaces(const SCdlInterface* aLeft, const SCdlInterface* aRight) |
|
426 { |
|
427 // first, pointer checks |
|
428 if (!aLeft && !aRight) |
|
429 return 0; |
|
430 else if (!aRight) |
|
431 return 1; |
|
432 else if (!aLeft) |
|
433 return -1; |
|
434 // next, ROM only flag checks |
|
435 else if ((aLeft->iFlags&KCdlFlagRomOnly) && !(aRight->iFlags&KCdlFlagRomOnly)) |
|
436 return 1; |
|
437 else if (!(aLeft->iFlags&KCdlFlagRomOnly) && (aRight->iFlags&KCdlFlagRomOnly)) |
|
438 return -1; |
|
439 // finally, API size check |
|
440 return aLeft->iApiSize - aRight->iApiSize; |
|
441 } |
|
442 |
|
443 TBool CCdlCustomisationStack::InstanceCanBeBase(CCdlInstance* aInst) const |
|
444 { |
|
445 return |
|
446 CompareInterfaces(&aInst->Interface(), iInterfaceParams) >= 0 && |
|
447 aInst->IsComplete() && |
|
448 ( // check that ROM only flag does not change |
|
449 !iInterfaceParams || |
|
450 (aInst->Interface().iFlags&KCdlFlagRomOnly) == (iInterfaceParams->iFlags&KCdlFlagRomOnly) |
|
451 ); |
|
452 } |