|
1 // Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies). |
|
2 // All rights reserved. |
|
3 // This component and the accompanying materials are made available |
|
4 // under the terms of "Eclipse Public License v1.0" |
|
5 // which accompanies this distribution, and is available |
|
6 // at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
7 // |
|
8 // Initial Contributors: |
|
9 // Nokia Corporation - initial contribution. |
|
10 // |
|
11 // Contributors: |
|
12 // |
|
13 // Description: |
|
14 // Implementation of the registrar class |
|
15 // |
|
16 // |
|
17 |
|
18 /** |
|
19 @internalComponent |
|
20 @file |
|
21 */ |
|
22 |
|
23 #include <barsc2.h> // CResourceFile |
|
24 #include <barsread2.h> // RResourceReader |
|
25 #include <bautils.h> |
|
26 #include <e32uid.h> |
|
27 #include <startup.hrh> // for EStartupStateNonCritical |
|
28 |
|
29 #include "ecompanics.h" |
|
30 #include "EComDebug.h" |
|
31 #include <ecom/ecom.h> |
|
32 #include <ecom/ecomerrorcodes.h> |
|
33 #include <ecom/ecomresolverparams.h> |
|
34 #include "TestUtilities.h" // For __FILE__LINE__ |
|
35 #include "Registrar.h" |
|
36 #include "Discoverer.h" |
|
37 #include "BackupNotifier.h" |
|
38 #include "RegistryData.h" |
|
39 #include "EComUidCodes.h" |
|
40 #include "RegistrarObserver.h" |
|
41 #include "DriveInfo.h" |
|
42 #include "ParseImplementationData.h" |
|
43 #include "EComInternalErrorCodes.h" |
|
44 |
|
45 const TInt KMinBuffAllocSize = 1; |
|
46 |
|
47 |
|
48 #define UNUSED_VAR(a) a = a |
|
49 |
|
50 |
|
51 CRegistrar* CRegistrar::NewL(CRegistryData& aRegistry, MRegistrarObserver& aRegistrarObserver, RFs& aFs) |
|
52 { |
|
53 CRegistrar* self = new(ELeave) CRegistrar(aRegistry,aRegistrarObserver,aFs); |
|
54 CleanupStack::PushL(self); |
|
55 self->ConstructL(); |
|
56 CleanupStack::Pop(self); |
|
57 return self; |
|
58 } |
|
59 |
|
60 // Default d'tor |
|
61 |
|
62 CRegistrar::~CRegistrar() |
|
63 { |
|
64 delete iBackupNotifier; |
|
65 delete iDiscoverer; |
|
66 delete iCachedDriveInfo; |
|
67 } |
|
68 |
|
69 // Default c'tor |
|
70 |
|
71 CRegistrar::CRegistrar(CRegistryData& aRegistry, MRegistrarObserver& aRegistrarObserver, RFs& aFs) |
|
72 : CBase(), iRegistry(aRegistry), iRegistrarObserver(aRegistrarObserver), iFs(aFs), iState(EReg_Undefined) |
|
73 { |
|
74 } |
|
75 |
|
76 |
|
77 void CRegistrar::ConstructL() |
|
78 { |
|
79 iCachedDriveInfo = CEComCachedDriveInfo::NewL(iFs); |
|
80 |
|
81 // Instantiate the discoverer |
|
82 iDiscoverer = CDiscoverer::NewL(*this, iFs); |
|
83 InitialiseEvent(); |
|
84 } |
|
85 |
|
86 |
|
87 TInt CRegistrar::Disable(TUid aImplementationUid) |
|
88 { |
|
89 return iRegistry.SetEnabledState(aImplementationUid, EFalse); |
|
90 } |
|
91 |
|
92 |
|
93 TInt CRegistrar::Enable(TUid aImplementationUid) |
|
94 { |
|
95 return iRegistry.SetEnabledState(aImplementationUid, ETrue); |
|
96 } |
|
97 |
|
98 |
|
99 TInt CRegistrar::Resume() |
|
100 { |
|
101 return iDiscoverer->Resume(); |
|
102 } |
|
103 |
|
104 |
|
105 TInt CRegistrar::Suspend() |
|
106 { |
|
107 return iDiscoverer->Suspend(); |
|
108 } |
|
109 |
|
110 |
|
111 void CRegistrar::DriveRemovedL(TDriveUnit aDrive) |
|
112 { |
|
113 iRegistry.TemporaryUninstallL(aDrive); |
|
114 } |
|
115 |
|
116 |
|
117 void CRegistrar::DriveReinstatedL(TDriveUnit aDrive) |
|
118 { |
|
119 iRegistry.UndoTemporaryUninstallL(aDrive); |
|
120 } |
|
121 |
|
122 TBool CRegistrar::IsAnyDllRegisteredWithDriveL(const TDriveUnit aDrive)const |
|
123 { |
|
124 return iRegistry.IsAnyDllRegisteredWithDriveL(aDrive); |
|
125 } |
|
126 |
|
127 void CRegistrar::RegisterDiscoveryL(const TDriveName& aDrive,CPluginBase*& aDirEntry, TBool aAnyDllDiscovered) |
|
128 { |
|
129 TBool found = EFalse; |
|
130 TBool update = EFalse; |
|
131 TInt registryDriveIndex = KErrNotFound; |
|
132 |
|
133 // Find the appropriate drive entry |
|
134 TChar driveLetter = User::UpperCase(aDrive[0]) - 'A'; |
|
135 TDriveUnit driveUnit = EDriveA + driveLetter; |
|
136 CRegistryData::CDriveData* drive =NULL; |
|
137 |
|
138 // Get the drive data in the registry. |
|
139 registryDriveIndex = iRegistry.FindDriveL(driveUnit, drive); |
|
140 if(registryDriveIndex == KErrNotFound) |
|
141 { |
|
142 User::Leave(KEComErrDriveNotFound); |
|
143 } |
|
144 |
|
145 |
|
146 // Get the registry to return enough data so that the Add and Update routines |
|
147 // can be optimised to avoid rescanning the registry data. |
|
148 // This means that registryDriveIndex MUST remain valid until after |
|
149 // the ParseRegistrationDataL call below. |
|
150 |
|
151 // IsRegisteredWithDate will be called if the this drive is NOT |
|
152 // under its initial discovery. If any Dll is discovered in the drive, then |
|
153 // this drive is NOT in its initial discovery. |
|
154 |
|
155 // In read-only drive with SPI enable, aAnyDllDiscovered will be always false. |
|
156 // If language downgrade path has been changed, IsRegisteredWithDate will be |
|
157 // called to check whether current localised file need to be updated. |
|
158 if((aAnyDllDiscovered) || (iRegistry.HasLanguageChanged())) |
|
159 { |
|
160 found = iRegistry.IsRegisteredWithDate(aDirEntry->iDllThirdUid, aDirEntry->iDllModifiedTime, update, drive); |
|
161 } |
|
162 |
|
163 if(!found || update || iRegistry.HasLanguageChanged()) |
|
164 { |
|
165 if(found && !update && iRegistry.HasLanguageChanged()) |
|
166 { |
|
167 // If we got here because the language has changed |
|
168 // ensure the existing registry data is updated rather than a new entry added |
|
169 update = ETrue; |
|
170 } |
|
171 ParseRegistrationDataL(aDirEntry,driveUnit, update, registryDriveIndex, drive); |
|
172 } |
|
173 } |
|
174 |
|
175 |
|
176 void CRegistrar::DiscoveriesBegin() |
|
177 { |
|
178 // We are about to receive registrations so inform the registry that its index |
|
179 // is about to be invalid |
|
180 iRegistry.DiscoveriesBeginning(); |
|
181 } |
|
182 |
|
183 |
|
184 void CRegistrar::DiscoveriesComplete(TBool aSuccessful, TPluginProcessingTypeIdentifier aProcessingType) |
|
185 { |
|
186 |
|
187 TBool doesRegChanged = EFalse; |
|
188 |
|
189 // Successfully completed, if registry data has been changed, update |
|
190 TRAPD(error,iRegistry.DiscoveriesCompleteL(aSuccessful, aProcessingType,doesRegChanged)); |
|
191 UNUSED_VAR(error); |
|
192 // Notify if the registry data has been changed. |
|
193 if(doesRegChanged) |
|
194 { |
|
195 // Notify that we have updated the registry |
|
196 iRegistrarObserver.Notification(KErrNone); |
|
197 } |
|
198 } |
|
199 |
|
200 void CRegistrar::SetDiscoveryFlagL(const TDriveUnit& aDriveUnit) |
|
201 { |
|
202 //set the drive flag to indicate it has changes. |
|
203 iRegistry.SetDiscoveryFlagL(aDriveUnit); |
|
204 } |
|
205 |
|
206 TBool CRegistrar::NotifiedWithErrorCode(TInt aError) |
|
207 { |
|
208 // Test the safe error codes |
|
209 return (aError == KErrNotReady || // Drive removed? |
|
210 aError == KErrPathNotFound); // Directory deleted? |
|
211 } |
|
212 |
|
213 void CRegistrar::ParseRegistrationDataL(CPluginBase*& aEntry, |
|
214 const TDriveUnit& aDrive, |
|
215 TBool aUpdate, |
|
216 TInt aRegistryDriveIndex, |
|
217 CRegistryData::CDriveData* aDriveData) |
|
218 { |
|
219 // Ok we intend installing this item so |
|
220 // create the Interface Implementation Collection entry first |
|
221 CRegistryData::CDllData* dll = CRegistryData::CDllData::NewLC(*(aEntry->iDllName),aEntry->iDllModifiedTime,aEntry->iDllSecondUid,aEntry->iDllThirdUid,aDriveData); |
|
222 |
|
223 #ifdef ECOM_TRACE |
|
224 static int counter = 0; counter++; |
|
225 TFileName fullFileName(aDrive.Name()); |
|
226 fullFileName.Append(_L("\\sys\\bin\\")); |
|
227 fullFileName.Append(*(aEntry->iDllName)); |
|
228 __ECOM_TRACE2("ECOM: Plugin discovered (%04d) %S", counter, &fullFileName); |
|
229 #endif |
|
230 |
|
231 // update resource ext info |
|
232 HBufC* resourceExt = aEntry->RscFileExt(); |
|
233 if(resourceExt) |
|
234 dll->SetResourceExtL(*resourceExt); |
|
235 |
|
236 // Don't automatically leave during the parse of the implementation |
|
237 // collection's registration data. |
|
238 // If we did then there would be a cascade of leaves which stop the |
|
239 // entire registration process for all discoveries remaining on the list. |
|
240 // Check to see if there is a problem specifically with the registration data |
|
241 // OR if its a general problem. In the latter case leave. |
|
242 TInt error=KErrNone; |
|
243 |
|
244 TRAP(error, ParseL(aEntry,*dll)); |
|
245 if (error==KErrNoMemory) |
|
246 User::LeaveNoMemory(); |
|
247 if(error == KErrNone) |
|
248 { |
|
249 if(aUpdate) |
|
250 { |
|
251 iRegistry.UpdateDllDataL(aDrive, aRegistryDriveIndex, dll); |
|
252 } |
|
253 else |
|
254 { |
|
255 iRegistry.AddDllDataL(aDrive, aRegistryDriveIndex, dll); |
|
256 } |
|
257 // Remove dll from CleanupStack as ownership has been passed in one of |
|
258 // the two functions above |
|
259 CleanupStack::Pop(dll); |
|
260 } |
|
261 else |
|
262 { |
|
263 // This interface implementation collection |
|
264 // cannot be registered correctly. |
|
265 CleanupStack::PopAndDestroy(dll); |
|
266 } |
|
267 } |
|
268 |
|
269 void CRegistrar::GetResourceFormatVersionL(RResourceReader& aReader, TInt& aResourceFormatVersion) |
|
270 { |
|
271 aResourceFormatVersion = 1; |
|
272 TUid dllUid(KNullUid); |
|
273 TUid uid = {aReader.ReadInt32L()}; |
|
274 if(uid==KUidEComResourceFormatV2) |
|
275 { |
|
276 aResourceFormatVersion = 2; |
|
277 dllUid.iUid = aReader.ReadInt32L(); |
|
278 } |
|
279 else if(uid==KUidEComResourceFormatV3) |
|
280 { |
|
281 aResourceFormatVersion = 3; |
|
282 dllUid.iUid = aReader.ReadInt32L(); |
|
283 } |
|
284 else |
|
285 dllUid = uid; |
|
286 } |
|
287 |
|
288 |
|
289 void CRegistrar::ParseL(CPluginBase*& aEntry,CRegistryData::CDllData& aDll) |
|
290 { |
|
291 // Read the resource file starting at offset:0 section size:0 |
|
292 CResourceFile* regFile =aEntry->RscFile(); |
|
293 // Note : There may be an issue here with resource reading when the |
|
294 // file is not in the ROM. The solution would be to call |
|
295 // regFile.ConfirmSignatureL(regFile.SignatureL()); |
|
296 // However for 6.2 interface implementation collections will ALL |
|
297 // be within the ROM. and future development will move to an |
|
298 // XML parsed solution @ build time. |
|
299 // IF this situation changes, place the fix here. |
|
300 RResourceReader theReader; |
|
301 theReader.OpenLC(regFile, KMinBuffAllocSize); |
|
302 TInt resourceFormatVersion = 0; |
|
303 GetResourceFormatVersionL(theReader,resourceFormatVersion); |
|
304 |
|
305 TDriveUnit drive(aDll.iParent->iDrive); |
|
306 TBool romBased = iCachedDriveInfo->DriveIsReadOnlyInternalL(drive); |
|
307 const TInt numInterfaces = theReader.ReadInt16L(); |
|
308 if (resourceFormatVersion == 3 && numInterfaces > KMaxInterfacesInResV3) |
|
309 { |
|
310 User::Leave(KErrNotSupported); |
|
311 } |
|
312 for(TInt iface = 0; iface < numInterfaces; ++iface) |
|
313 { |
|
314 // Read the interface uid |
|
315 const TUid interfaceUid = {theReader.ReadInt32L()}; |
|
316 CRegistryData::CInterfaceData* interfaceList = CRegistryData::CInterfaceData::NewLC(interfaceUid,&aDll); |
|
317 aDll.AddL(interfaceList); |
|
318 CleanupStack::Pop(interfaceList); // Now owned by aDll |
|
319 const TInt numImplementations = theReader.ReadInt16L(); |
|
320 if (resourceFormatVersion == 3 && numImplementations > KMaxImplementationsForEachInterfacesInResV3) |
|
321 { |
|
322 User::Leave(KErrNotSupported); |
|
323 } |
|
324 for(TInt index = 0; index < numImplementations; ++index) |
|
325 { |
|
326 TUid implementationUid; |
|
327 TInt versionNo; |
|
328 TInt infoFormat; |
|
329 TBool romOnly; |
|
330 RExtendedInterfacesArray* extendedInterfaces = NULL; |
|
331 HBufC* name = NULL; |
|
332 HBufC8* defaultData = NULL; |
|
333 HBufC8* opaqueData = NULL; |
|
334 CParseImplementationData* parseImplementationData = CParseImplementationData::NewLC(resourceFormatVersion); |
|
335 parseImplementationData->ParseL(theReader, |
|
336 infoFormat, |
|
337 implementationUid, |
|
338 versionNo, |
|
339 name, |
|
340 defaultData, |
|
341 opaqueData, |
|
342 extendedInterfaces, |
|
343 romOnly); |
|
344 CleanupStack::PopAndDestroy(parseImplementationData); |
|
345 |
|
346 CleanupStack::PushL(TCleanupItem(CloseAndDeleteArray, extendedInterfaces)); |
|
347 CleanupStack::PushL(name); |
|
348 CleanupStack::PushL(defaultData); |
|
349 CleanupStack::PushL(opaqueData); |
|
350 if (romOnly && !(romBased)) |
|
351 { |
|
352 // pop and destroy opaquedata, defaultdata,name and extendedInterfaces |
|
353 CleanupStack::PopAndDestroy(4,extendedInterfaces); |
|
354 } |
|
355 else |
|
356 { |
|
357 CRegistryData::CImplementationData* implData = CRegistryData::CImplementationData::NewL(interfaceList, |
|
358 implementationUid, |
|
359 versionNo, |
|
360 name, |
|
361 defaultData, |
|
362 opaqueData, |
|
363 drive, |
|
364 romOnly, |
|
365 romBased, |
|
366 extendedInterfaces); |
|
367 CleanupStack::Pop(4,extendedInterfaces); // opaqueData,defaultData,name,extendedInterfaces owned by implData |
|
368 CleanupStack::PushL(implData); |
|
369 interfaceList->AddL(implData); // Now owned by interfaceList |
|
370 CleanupStack::Pop(implData); |
|
371 } |
|
372 } |
|
373 } |
|
374 CleanupStack::PopAndDestroy(&theReader); |
|
375 } |
|
376 |
|
377 |
|
378 CRegistrar::TRegistrarState CRegistrar::State()const |
|
379 { |
|
380 return iState; |
|
381 } |
|
382 |
|
383 void CRegistrar::ProcessSSAEventL(TStartupStateIdentifier aKnownState) |
|
384 { |
|
385 iDiscoverer->ProcessSSAEventL(aKnownState); |
|
386 if(aKnownState == EStartupStateNonCritical && iState == EReg_StartupInProgess) |
|
387 { |
|
388 __ECOM_TRACE("ECOM: CRegistrar::ProcessSSAEventL(): EStartupStateNonCritical is reached."); |
|
389 |
|
390 iState = EReg_StartupComplete; |
|
391 iBackupNotifier = CBackupNotifier::NewL(*this); |
|
392 } |
|
393 } |
|
394 void CRegistrar::InitialiseEvent() |
|
395 { |
|
396 iState = EReg_StartupInProgess; |
|
397 } |
|
398 |
|
399 void CRegistrar::LanguageChangedL(TBool& aLanguageChanged) |
|
400 { |
|
401 iRegistry.LanguageChangedL(aLanguageChanged); |
|
402 } |
|
403 |
|
404 void CRegistrar::InstallSwiEventCallBack(const TCallBackWithArg& aCallBack) |
|
405 { |
|
406 iDiscoverer->SetSwiChangeCallBack(aCallBack); |
|
407 } |
|
408 |
|
409 void CRegistrar::InstallBurEventCallBack(const TCallBackWithArg& aCallBack) |
|
410 { |
|
411 iDiscoverer->SetBurChangeCallBack(aCallBack); |
|
412 } |