commonservices/sysutil/src/sysutil.cpp
changeset 0 4e1aa6a622a0
child 41 c87e5f80c17d
equal deleted inserted replaced
-1:000000000000 0:4e1aa6a622a0
       
     1 // Copyright (c) 2007-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 //
       
    15 
       
    16 
       
    17 
       
    18 // INCLUDE FILES
       
    19 #include "sysutil.h"
       
    20 #include <f32file.h>
       
    21 #include <bsul/ccacheddriveinfo.h>
       
    22 #include "sysutildomaincrkeys.h"	// for disc space
       
    23 #include "sysutilinternalpskeys.h"	// for disc space
       
    24 #include "sysutildebug.h"			// debug helper
       
    25 #include "sysutilpatchdata.h"		// patchable data defining the MMC drive integer identifer
       
    26 #include <baflpan.h>
       
    27 #include <e32property.h>
       
    28 #include <e32capability.h>
       
    29 #include <bsul/inifile.h>
       
    30 #include <bautils.h>
       
    31 #include "sysutilsetup.h"
       
    32 #include "sysutilplugindef.h"
       
    33 
       
    34 // File names of the files which store version and device type information.
       
    35 _LIT( KSWVersionFileName,			"sw.txt" );
       
    36 _LIT( KLangSWVersionFileName,		"langsw.txt" );
       
    37 _LIT( KLangVersionFileName,			"lang.txt" );
       
    38 _LIT( KDeviceAttributesFileName,	"deviceattributes.ini" );
       
    39 _LIT( KPRInformationFileName,       "purpose.txt" );
       
    40 
       
    41 // UID of sysutilsetup.exe.
       
    42 const TUid KSysUtilSetupUid = {0x10285B3B};
       
    43 
       
    44 // Publish and Subscribe keys.
       
    45 const TUid KTestFilePathsUid = {0x10285B40};
       
    46 const TUid KSWVersionUid = {0x10285B3C};
       
    47 const TUid KLangSWVersionUid = {0x10285B3D};
       
    48 const TUid KLangVersionUid = {0x10285B3E};
       
    49 const TUid KDeviceTypeInfoUid = {0x10285B3F};
       
    50 const TUid KPRInformationUid = {0x20027BC4};
       
    51 
       
    52 // Device Type Information attribute UIDs.
       
    53 const TUid KManufacturerNameUid = {0x10286358};
       
    54 const TUid KModelNameUid = {0x10286359};
       
    55 const TUid KModelCodeUid = {0x1028635A};
       
    56 const TUid KRevisionIDUid = {0x1028635B};
       
    57 const TUid KDefaultDeviceNameUid = {0x1028635C};
       
    58 const TUid KUIPlatformNameUid = {0x1028635D};
       
    59 const TUid KUIPlatformVersionMajorUid = {0x1028635E};
       
    60 const TUid KUIPlatformVersionMinorUid = {0x1028635F};
       
    61 const TUid KUIPlatformVersionUid = {0x10286360};
       
    62 const TUid KOSVersionMajorUid = {0x10286361};
       
    63 const TUid KOSVersionMinorUid = {0x10286362};
       
    64 const TUid KOSVersionUid = {0x10286363};
       
    65 
       
    66 // This is the maximum number of Device Type Information attributes that can be 
       
    67 // stored in the Device Type Information Publish and Subscribe property.
       
    68 const TUint16 KAttributeLimit = 450;
       
    69 
       
    70 // Default values that will be used if no plugin is provided, the 
       
    71 // deviceattributes.ini file is missing or if a device attribute is not 
       
    72 // specified by a licensee.
       
    73 _LIT16( KDefaultManufacturer, "Symbian" );
       
    74 _LIT16( KDefaultModelName, "Symbian" );
       
    75 _LIT16( KDefaultModelCode, "Symbian" );
       
    76 _LIT16( KDefaultRevisionID, "00.00" );
       
    77 _LIT16( KDefaultDeviceName, "Symbian" );
       
    78 _LIT16( KDefaultUIPlatform, "Symbian" );
       
    79 _LIT16( KDefaultUIPlatformVersionMajor, "0" );
       
    80 _LIT16( KDefaultUIPlatformVersionMinor, "0" );
       
    81 _LIT16( KDefaultUIPlatformVersion, "0.0" );
       
    82 _LIT16( KDefaultOSVersionMajor, "0" );
       
    83 _LIT16( KDefaultOSVersionMinor, "0" );
       
    84 _LIT16( KDefaultOSVersion, "0.0" );
       
    85 
       
    86 
       
    87 // Security policies for the Publish and Subscribe properties.
       
    88 _LIT_SECURITY_POLICY_C1( KSecurityPolicyNone, ECapability_None );
       
    89 _LIT_SECURITY_POLICY_S1( KSecurityPolicyWriteDeviceData, 0x10285B3B, ECapabilityWriteDeviceData );
       
    90 
       
    91 _LIT( KNewLinePattern, "\\n" );
       
    92 _LIT( KNewline, "\n" );
       
    93 
       
    94 
       
    95 /**
       
    96 Dummy sysutil implementation object - never instantiated.
       
    97 @internalComponent
       
    98 */
       
    99 class CDeviceTypeInformation::TImpl
       
   100 	{
       
   101 	TUint32 iDummy;
       
   102 	};
       
   103 
       
   104 /**
       
   105 Stores a copy of the device type information attributes. For details of the 
       
   106 memory layout see SGL.TS0017.201 BAFL Component Design Document.doc.
       
   107 @internalComponent 
       
   108 */
       
   109 typedef struct _SDeviceAttributes
       
   110 	{
       
   111 	TUint16 Length() const;
       
   112 	TUint16 Count() const;
       
   113 	TInt32 Uid( const TInt aAttributeIndex ) const;
       
   114 	TInt16 Error( const TInt aAttributeIndex ) const;
       
   115 	TInt AttributeLength( const TInt aAttributeIndex ) const;
       
   116 	TUint16* AttributePtr( const TInt aAttributeIndex ) const;
       
   117 	TUint16* iDeviceAttributes;
       
   118 	} SDeviceAttributes;
       
   119 	
       
   120 /**
       
   121 @return TInt16 The number of elements in the memory block.
       
   122 */
       
   123 inline TUint16 SDeviceAttributes::Length() const
       
   124 	{
       
   125 	return iDeviceAttributes[0];
       
   126 	}
       
   127 
       
   128 /**
       
   129 @return TInt16 The number of device type information attributes.
       
   130 */
       
   131 inline TUint16 SDeviceAttributes::Count() const
       
   132 	{
       
   133 	return iDeviceAttributes[1];
       
   134 	}
       
   135 
       
   136 /**
       
   137 Returns the UID which matches the attribute with the given index.
       
   138 
       
   139 @param 	aAttribIndex	The index of the attribute in iDeviceAttributes.
       
   140 @return TInt32 			The UID of the attribute with the given index.
       
   141 */
       
   142 inline TInt32 SDeviceAttributes::Uid( const TInt aAttribIndex ) const
       
   143 	{
       
   144 	return (iDeviceAttributes[2 + (2 * aAttribIndex)] << 16) + iDeviceAttributes[2 + (2 * aAttribIndex) + 1];
       
   145 	}
       
   146 
       
   147 /**
       
   148 Returns an error code associated with the device type information attribute with 
       
   149 the given index. This error code is generated when the attribute is retrieved 
       
   150 from a plugin/deviceattributes.ini. It indicates if a value was successfully 
       
   151 read, no value was provided or if an error occured.
       
   152 
       
   153 @param 	aAttribIndex	The index of the attribute in iDeviceAttributes.
       
   154 @return TInt16 			The error of the attribute with the given index.
       
   155 */
       
   156 inline TInt16 SDeviceAttributes::Error( const TInt aAttribIndex) const
       
   157 	{
       
   158 	return static_cast<TInt16>(iDeviceAttributes[2 + (3 * Count()) + 1 + aAttribIndex]);
       
   159 	}
       
   160 
       
   161 /**
       
   162 Returns the length of the attribute with the given index.
       
   163 
       
   164 @param 	aAttribIndex	The index of the attribute in iDeviceAttributes.
       
   165 @return TInt			The length of the attribute with the given index.
       
   166 */
       
   167 inline TInt SDeviceAttributes::AttributeLength( const TInt aAttribIndex ) const
       
   168 	{
       
   169 	return iDeviceAttributes[2 + (2 * Count()) + aAttribIndex + 1] - iDeviceAttributes[2 + (2 * Count()) + aAttribIndex];
       
   170 	}
       
   171 
       
   172 /**
       
   173 Returns a pointer to the attribute value in iDeviceAttributes with the given 
       
   174 index.
       
   175 
       
   176 @param 	aAttribIndex	The index of the attribute in iDeviceAttributes.
       
   177 @return TUint16*		A pointer to the attribute value with the given index.
       
   178 */
       
   179 inline TUint16* SDeviceAttributes::AttributePtr( const TInt aAttribIndex ) const
       
   180 	{
       
   181 	return iDeviceAttributes + iDeviceAttributes[2 + (2 * Count()) + aAttribIndex];
       
   182 	}
       
   183 
       
   184 // ======== LOCAL FUNCTIONS ======== 
       
   185 
       
   186 /**
       
   187 Returns the total length of all the device type information attribute values stored 
       
   188 in aValues.
       
   189 
       
   190 @param	aKeys	An array which contains a list of device type information attribute
       
   191 				UIDs. The UIDs corrospond to the values in aValues.
       
   192 @param	aValues	An array which contains a list of device type information attribute
       
   193 				values. The values corrospond to the UIDs in aKeys.
       
   194 @return TInt	The total length of all the device type information attribute values 
       
   195 				stored in aValues.
       
   196 @internalComponent
       
   197 */
       
   198 static TInt AttributesTotalLength( RArray<TInt32>&, CDesC16ArraySeg& aValues )
       
   199 	{
       
   200 	TUint attributesTotalLength = 0;
       
   201 	TInt numAttributes = aValues.Count();
       
   202 	for( TInt attributeIndex = 0; attributeIndex < numAttributes; attributeIndex++ )
       
   203 		{
       
   204 		TInt attributeLength = aValues[attributeIndex].Length();
       
   205 		if( attributeLength < CDeviceTypeInformation::KMaxAttributeLength )
       
   206 			{
       
   207 			attributesTotalLength += attributeLength;
       
   208 			}
       
   209 		else
       
   210 			{
       
   211 			attributesTotalLength += CDeviceTypeInformation::KMaxAttributeLength;
       
   212 			}
       
   213 		}
       
   214 	
       
   215 	return attributesTotalLength;
       
   216 	}
       
   217 
       
   218 /**
       
   219 Returns a pointer to some memory which contains the device type information attribute 
       
   220 UIDs and values (these are contained in aKeys and aValues) in a compact format. The 
       
   221 layout of the memory can be found in the Design Document 
       
   222 (SGL.TS0017.201 BAFL Component Design Document.doc). 
       
   223 
       
   224 @param	aKeys		An array which contains a list of device type information 
       
   225 					attribute UIDs. The UIDs corrospond to the values in aValues.
       
   226 @param	aValues		An array which contains a list of device type information 
       
   227 					attribute values. The values corrospond to the UIDs in aKeys.
       
   228 @leave	-			One of the system-wide error codes.
       
   229 @return	TUint16*	A pointer to the memory which contains the device type 
       
   230 					information attribute UIDs and values in a compact format.
       
   231 @internalComponent
       
   232 */
       
   233 static TUint16* CreateDeviceTypeInfoPSDataL( RArray<TInt32>& aKeys, CDesC16ArraySeg& aValues )
       
   234 	{
       
   235 	// See SGL.TS0017.201 BAFL Component Design Document.doc for more information on the
       
   236 	// memory requirements and layout.
       
   237 	TInt memoryElements = 3 + (4 * aKeys.Count()) + AttributesTotalLength( aKeys, aValues );
       
   238 	
       
   239 	// Allocate memory to store the device type information attribute keys and values
       
   240 	TUint16* deviceAttributes = static_cast<TUint16*>( User::AllocL( sizeof(TUint16) * memoryElements ) );
       
   241 	CleanupStack::PushL( deviceAttributes );
       
   242 	
       
   243 	// Store the attributes length and count
       
   244 	deviceAttributes[0] = memoryElements;
       
   245 	deviceAttributes[1] = aKeys.Count();
       
   246 	
       
   247 	// Store the attribute UIDs, offsets of the attributes in the memory, error codes and attribute values.
       
   248 	if( deviceAttributes[1] > 0 )
       
   249 		{
       
   250 		// Set the first offset to point to the start of the attributes
       
   251 		deviceAttributes[2 + (2 * deviceAttributes[1])] = 2 + 1 + (4 * deviceAttributes[1]);
       
   252 		
       
   253 		for( TInt attributeNumber = 0; attributeNumber < deviceAttributes[1]; attributeNumber++ )
       
   254 			{
       
   255 			// Store the UID as two TUint16s
       
   256 			deviceAttributes[2 + (2 * attributeNumber)] = static_cast<TUint16>(aKeys[attributeNumber] >> 16); 
       
   257 			deviceAttributes[2 + (2 * attributeNumber) + 1] = static_cast<TUint16>(aKeys[attributeNumber]); 
       
   258 			
       
   259 			if( KUIPlatformVersionMajorUid.iUid == aKeys[attributeNumber] || KUIPlatformVersionMinorUid.iUid == aKeys[attributeNumber] 
       
   260 				|| KOSVersionMajorUid.iUid == aKeys[attributeNumber] || KOSVersionMinorUid.iUid == aKeys[attributeNumber] )
       
   261 				{
       
   262 				// If the values were present in the INI/plugin (as we have the attribute keys) and the values
       
   263 				// are KNullDesC16 then the values were corrupt.
       
   264 				if( aValues[attributeNumber].Compare( KNullDesC16 ) == 0 )
       
   265 					{
       
   266 					deviceAttributes[2 + (2 * deviceAttributes[1]) + 1 + attributeNumber] = deviceAttributes[2 + (2 * deviceAttributes[1]) + 1 + attributeNumber - 1];
       
   267 					deviceAttributes[2 + (3 * deviceAttributes[1]) + 1 + attributeNumber] = static_cast<TUint16>(KErrCorrupt);
       
   268 					continue;
       
   269 					}
       
   270 				}
       
   271 			
       
   272 			// If the attribute value is too long we need to truncate it and set the error as KErrOverflow.
       
   273 			if( aValues[attributeNumber].Length() > CDeviceTypeInformation::KMaxAttributeLength )
       
   274 				{
       
   275 				deviceAttributes[2 + (2 * deviceAttributes[1]) + 1 + attributeNumber] = deviceAttributes[2 + (2 * deviceAttributes[1]) + attributeNumber] + CDeviceTypeInformation::KMaxAttributeLength;
       
   276 				deviceAttributes[2 + (3 * deviceAttributes[1]) + 1 + attributeNumber] = static_cast<TUint16>(KErrOverflow);
       
   277 				Mem::Copy( deviceAttributes + deviceAttributes[2 + (2 * deviceAttributes[1]) + attributeNumber], aValues[attributeNumber].Ptr(), CDeviceTypeInformation::KMaxAttributeLength * 2 );
       
   278 				}
       
   279 			else
       
   280 				{
       
   281 				deviceAttributes[2 + (2 * deviceAttributes[1]) + 1 + attributeNumber] = deviceAttributes[2 + (2 * deviceAttributes[1]) + attributeNumber] + aValues[attributeNumber].Length();
       
   282 				deviceAttributes[2 + (3 * deviceAttributes[1]) + 1 + attributeNumber] = KErrNone;
       
   283 				Mem::Copy( deviceAttributes + deviceAttributes[2 + (2 * deviceAttributes[1]) + attributeNumber], aValues[attributeNumber].Ptr(), aValues[attributeNumber].Size() );
       
   284 				}
       
   285 			}
       
   286 		}
       
   287 	CleanupStack::Pop( 1 );
       
   288 	
       
   289 	return deviceAttributes;
       
   290 	}
       
   291 
       
   292 /**
       
   293 Helper function which deletes the Version and Device Type Information Publish and 
       
   294 Subscribe properties. This is meant for testing purposes only and requires the 
       
   295 KSysUtilTestModeEnabled constant to be patched to ETrue.
       
   296 
       
   297 @leave	-			One of the system-wide error codes.
       
   298 @internalComponent
       
   299 */
       
   300 EXPORT_C void DeletePSPropertiesL()
       
   301 	{
       
   302 	if( KSysUtilTestModeEnabled )
       
   303 		{
       
   304 		TInt err = RProperty::Delete(KSWVersionUid.iUid);
       
   305 		if(err != KErrNotFound)
       
   306 			{
       
   307 			User::LeaveIfError(err);
       
   308 			}
       
   309 		
       
   310 		err = RProperty::Delete(KLangSWVersionUid.iUid);
       
   311 		if(err != KErrNotFound)
       
   312 			{
       
   313 			User::LeaveIfError(err);
       
   314 			}
       
   315 		
       
   316 		err = RProperty::Delete(KLangVersionUid.iUid);
       
   317 		if(err != KErrNotFound)
       
   318 			{
       
   319 			User::LeaveIfError(err);
       
   320 			}
       
   321 		
       
   322 		err = RProperty::Delete(KDeviceTypeInfoUid.iUid);
       
   323 		if(err != KErrNotFound)
       
   324 			{
       
   325 			User::LeaveIfError(err);
       
   326 			}
       
   327 		
       
   328 		err = RProperty::Delete(KPRInformationUid.iUid);
       
   329         if(err != KErrNotFound)
       
   330             {
       
   331             User::LeaveIfError(err);
       
   332             }
       
   333 		}
       
   334 	}
       
   335 
       
   336 /**
       
   337 Finds and returns the device type information attribute number in aAttr. This 
       
   338 number is used as an index in a populated instance of SDeviceAttributes.
       
   339 
       
   340 @param aAttr A reference to SDeviceAttributes which contains a copy of the device type information attributes.
       
   341 @param aKey The UID of the device type information attribute which needs to be found.
       
   342 @return The attribute index number (position) in aAttr.
       
   343 @return KErrNotFound aKey is not present in aAttr.
       
   344 @internalComponent
       
   345 */
       
   346 static TInt FindAttributeNumber( const SDeviceAttributes& aAttr, const TUid& aKey )
       
   347 	{
       
   348 	TInt bottom = 0;
       
   349 	TInt top = aAttr.Count() - 1;
       
   350 	
       
   351 	while( bottom <= top )
       
   352 		{
       
   353 		TUint middle = bottom + ( top - bottom ) / 2;
       
   354 		if( static_cast<TUint32>(aKey.iUid) < aAttr.Uid( middle ) )
       
   355 			{
       
   356 			top = middle - 1;
       
   357 			}
       
   358 		else if( static_cast<TUint32>(aKey.iUid) > aAttr.Uid( middle ) )
       
   359 			{
       
   360 			bottom = middle + 1;
       
   361 			}
       
   362 		else
       
   363 			{
       
   364 			return middle;
       
   365 			}
       
   366 		}
       
   367 	return KErrNotFound;
       
   368 	}
       
   369 
       
   370 /**
       
   371 Find a value from the patchable data. If that fails try Publish&Subscribe,
       
   372 or if that fails, from Central Repository.
       
   373 
       
   374 @internalComponent
       
   375 @param aPCKey identifies the value to get from P&S.
       
   376 @param aCRKey identifies the value to get from Centrep
       
   377 @param aPatchableData patchable data set at compile time, may have been patched via rom patching
       
   378 @return Disk level threshold
       
   379 */
       
   380 static TInt FindValueL(
       
   381     const TUint aPCKey,
       
   382     const TUint aCRKey,
       
   383     const TInt aPatchableData )
       
   384     {
       
   385     TInt val( 0 );
       
   386     
       
   387     if (aPatchableData != -1)
       
   388     	{
       
   389     	__SYSUTIL_TRACE1("SysUtil: CL treshold value found from patchable data %d",aPatchableData);	
       
   390     	return aPatchableData;
       
   391     	}
       
   392 	
       
   393 	// Patchable data not set, try to get it from P & S Keys.
       
   394 	TInt errorCode = RProperty::Get( KPSUidDiskLevel, aPCKey, val );
       
   395     if ( errorCode != KErrNone )
       
   396         {
       
   397         __SYSUTIL_TRACE1("SysUtil: CL treshold value not found from PS: %d, trying CR",errorCode);
       
   398         
       
   399         CRepository* repository = CRepository::NewLC(KCRUidDiskLevel);
       
   400         User::LeaveIfError(repository->Get(aCRKey,val));
       
   401         CleanupStack::PopAndDestroy( repository );
       
   402         }	
       
   403     	
       
   404 	return val;
       
   405     }
       
   406 
       
   407 /**
       
   408 Find out the critical level treashold (in bytes) for disk drives of type
       
   409 aMediaType. Different media types may have different tresholds. If adding
       
   410 a non-default treshold for some media type, implementation should go here.
       
   411 
       
   412 @internalComponent
       
   413 @param aMediaType identifies the media type of the drive
       
   414 @return Disk level threshold
       
   415 */
       
   416 static TInt64 FindCriticalLevelTresholdL( const TMediaType aMediaType )
       
   417     {
       
   418     if ( aMediaType == EMediaRam ) // RAM drives have different critical level than others
       
   419         {
       
   420         return (TInt64) FindValueL(KRamDiskCriticalThreshold, KRamDiskCriticalLevel, KSysUtilRamDiskCriticalThreshold  );
       
   421         }
       
   422     else // Some other media type
       
   423         {
       
   424         return (TInt64) FindValueL(KOtherDiskCriticalThreshold, KDiskCriticalThreshold, KSysUtilOtherDiskCriticalThreshold );
       
   425         }
       
   426     }
       
   427 
       
   428 /**
       
   429 Retrieves a string containing the location of sysutilplugin.dll. The location  
       
   430 which is retrieved is dependent upon two things. The first is a patchable constant 
       
   431 KSysUtilTestModeEnabled. This must be set to ETrue in order to use the test location instead 
       
   432 of the standard path. This is set to EFalse by default for hardware builds.
       
   433 
       
   434 The second is a Publish and Subscribe property, which has a UID of
       
   435 0x10285B40. If KSysUtilTestModeEnabled is set to ETrue then this property will be defined 
       
   436 and set to ETrue. This means that the test location is being used instead of the 
       
   437 standard location. If the client wishes to switch to the standard location they 
       
   438 can set this property to EFalse.
       
   439 
       
   440 It may be the case that the standard location needs to be used before the property 
       
   441 is defined. If this is needed then the client can define and set the property. 
       
   442 Alternatively, a call can be made to SysUtil::GetSWVersion, 
       
   443 SysUtil::GetLangSWVersion, SysUtil::GetLangVersion or SysUtil::GetDeviceTypeInfoL. 
       
   444 It can then call RProperty::Set with a value of EFalse.
       
   445 
       
   446 @param aLocation	On return contains the location of sysutilplugin.dll.
       
   447 @leave	-			One of the system-wide error codes.
       
   448 @internalComponent
       
   449 */
       
   450 static void GetDllLocationL( TDes& aLocation )
       
   451 	{
       
   452 	_LIT( KDeviceAttributeDll,	"Z:\\sys\\bin\\sysutilplugin.dll" );
       
   453 
       
   454 	if( KSysUtilTestModeEnabled )
       
   455 		{
       
   456 		TBool testPaths = EFalse;
       
   457 		TInt err = RProperty::Get( KUidSystemCategory, KTestFilePathsUid.iUid, testPaths );
       
   458 		if( KErrNone != err )
       
   459             testPaths = EFalse;
       
   460 		
       
   461 		if( testPaths )
       
   462 			{
       
   463 			TDriveUnit systemDrive( static_cast<TUint>(RFs::GetSystemDrive()) );
       
   464 			TParse path;
       
   465 			path.Set( systemDrive.Name(), &KDeviceAttributeDll, NULL );
       
   466 			
       
   467 			aLocation = path.FullName();
       
   468 			__SYSUTIL_TRACE1("DLL Location: %S", &aLocation);
       
   469 			return;
       
   470 			}
       
   471 		}
       
   472 	
       
   473 	__SYSUTIL_TRACE1("DLL Location: %S", &KDeviceAttributeDll);
       
   474 	aLocation = KDeviceAttributeDll;
       
   475 	}
       
   476 
       
   477 /**
       
   478 Retrieves a string containing the path to deviceattributes.ini. The path which 
       
   479 is retrieved is dependent upon two things. The first is a patchable constant 
       
   480 KSysUtilTestModeEnabled. This must be set to ETrue in order to use the test path instead 
       
   481 of the standard path. This is set to EFalse by default for hardware builds.
       
   482 
       
   483 The second is a Publish and Subscribe property, which has a UID of
       
   484 0x10285B40. If KSysUtilTestModeEnabled is set to ETrue then this property will be defined 
       
   485 and set to ETrue. This means that the test path is being used instead of the 
       
   486 standard path. If the client wishes to switch to the standard path they can set 
       
   487 this property to EFalse.
       
   488 
       
   489 It may be the case that the standard path needs to be used before the property 
       
   490 is defined. If this is needed then the client can define and set the property. 
       
   491 Alternatively, a call can be made to SysUtil::GetSWVersion, 
       
   492 SysUtil::GetLangSWVersion, SysUtil::GetLangVersion SysUtil::GetDeviceTypeInfoL or SysUtil::GetPRInformation. 
       
   493 It can then call RProperty::Set with a value of EFalse.
       
   494 
       
   495 @param 	aPath	On return contains the path to deviceattributes.ini.
       
   496 @return	-		One of the system-wide error codes.
       
   497 @internalComponent
       
   498 */
       
   499 static TInt GetFilePath( TDes& aPath )
       
   500 	{
       
   501 	_LIT( KDebugPath, "Z:\\versions\\" );
       
   502 	_LIT( KPath, "Z:\\resource\\versions\\" );
       
   503 
       
   504 	if( KSysUtilTestModeEnabled )
       
   505 		{
       
   506 		TBool testPaths = EFalse;
       
   507 		
       
   508 		TInt err = RProperty::Get( KUidSystemCategory, KTestFilePathsUid.iUid, testPaths );
       
   509 		if( KErrNone != err )
       
   510             testPaths = EFalse;
       
   511 	
       
   512 		if( testPaths )
       
   513 			{
       
   514 			TDriveUnit systemDrive( static_cast<TUint>(RFs::GetSystemDrive()) );
       
   515 			TParse path;
       
   516 			path.Set( systemDrive.Name(), &KDebugPath, NULL );
       
   517 			
       
   518 			aPath = path.DriveAndPath();
       
   519 			__SYSUTIL_TRACE1("File Location: %S", &aPath);
       
   520 			return KErrNone;
       
   521 			}
       
   522 		}
       
   523 	
       
   524 	__SYSUTIL_TRACE1("File Location: %S", &KPath);
       
   525 	aPath = KPath;
       
   526 	return KErrNone;
       
   527 	}
       
   528 
       
   529 /**
       
   530 Fetch text from specified files. The algorithm first reads the file and puts
       
   531 the string into a buffer. Then it searches for these "\n" sequences in
       
   532 the buffer. To search for "\n" in a string the search string is specified as "\\n"
       
   533 with the extra slash in front to mean that we are really searching for "\n" and not
       
   534 the newline character - 0x000A. Once the "\n" is found in the buffer it is replaced
       
   535 with the newline character - 0x000A. So since this input string is unicode, it is
       
   536 actually searching for the byte sequence of 0x005C, 0x006E. These 4 bytes are
       
   537 replaced by the two byte sequence of 0x000A.
       
   538 
       
   539 @internalComponent
       
   540 @param aFilename File name to fetch string from.
       
   541 @param aValue On return, contains the requested version string. If the buffer is
       
   542 insufficient the descriptor is filled to its maximum length. If a buffer is provided
       
   543 that is longer than 64 characters, and the file content is larger than 64 characters,
       
   544 the returned buffer is truncated at 64 characters (see error codes below).
       
   545 @param aRemoveNewLines Replaces new line patterns if set to ETrue
       
   546 @return KErrNone on success.
       
   547 	    KErrTooBig if the maximum length of the descriptor is insufficient
       
   548 to hold the file content, or has been truncated (see above). In both cases new-line processing
       
   549 is done on the buffers if needed. If the file is empty KErrEof is returned, and the length of the
       
   550 buffer is set to zero. If none of these cases apply then one of the Symbian error codes is
       
   551 returned if reading the version string fails.
       
   552 */
       
   553 static TInt GetTextFromFile(
       
   554     const TDesC& aFilename,
       
   555     TDes& aValue,
       
   556     TBool aRemoveNewLines )
       
   557     {
       
   558     RFs fs;
       
   559     TInt err;
       
   560     err = fs.Connect();
       
   561     if (err != KErrNone)
       
   562         return err;
       
   563 
       
   564     RFile file;
       
   565     err = file.Open( fs, aFilename,
       
   566                      EFileRead | EFileStreamText | EFileShareReadersOnly );
       
   567     if (err != KErrNone)
       
   568         {
       
   569         fs.Close();
       
   570         return err;
       
   571         }
       
   572 
       
   573     TBuf8<2> characters;
       
   574     err =  file.Read(characters);
       
   575     
       
   576     if (err == KErrNone || err == KErrTooBig)
       
   577     	{
       
   578 	    // This means that we have an ANSI file (without the header bytes)
       
   579 	    if( characters.Length() == 0 || characters.Length() == 1 )
       
   580 	    	{
       
   581 		    file.Close();
       
   582 		    fs.Close();
       
   583 			return KErrCorrupt;
       
   584 	    	}
       
   585 	    else 
       
   586 	    	{
       
   587 			TUint8 firstByte = characters[0];
       
   588 			TUint8 secondByte = characters[1];
       
   589 			
       
   590 			// Heading byte values for unicode files
       
   591 			const TInt KFFByte = 255;
       
   592 			const TInt KFEByte = 254;
       
   593 			
       
   594 		    // If file isn't unicode KErrCorrupt is returned
       
   595 			if( (firstByte!=KFFByte && secondByte!=KFEByte) && (secondByte!=KFFByte && firstByte!=KFEByte) )
       
   596 				{
       
   597 			    file.Close();
       
   598 			    fs.Close();
       
   599 				return KErrCorrupt;
       
   600 				} 
       
   601 	    	} 
       
   602     	}
       
   603     
       
   604     TFileText tf;
       
   605     tf.Set(file);
       
   606     err = tf.Read(aValue);
       
   607     // If the maximum length of the descriptor is insufficient to hold the record,
       
   608     // the Read() function returns KErrTooBig and the descriptor is filled to its maximum length.
       
   609     //
       
   610     // If Read() is called when the current position is the end of the file (that is, after
       
   611     // the last line delimiter in the file), KErrEof is returned, and the length of the buffer
       
   612     // is set to zero. In this case, this would mean an empty file, as this code always reads
       
   613     // from the beginning of the file.
       
   614     
       
   615     if (err == KErrNone || err == KErrTooBig)
       
   616     	{
       
   617     	if (aValue.Length() > KSysUtilVersionTextLength)
       
   618     		{
       
   619     		// File content is larger than 64 characters. Truncate to 64 characters.
       
   620     		aValue.Delete(KSysUtilVersionTextLength,aValue.Length() - KSysUtilVersionTextLength);
       
   621     		err = KErrTooBig;
       
   622     		}
       
   623     	if (aRemoveNewLines)
       
   624     		{
       
   625     		// Replace new-line patterns with real ones
       
   626             TInt error = aValue.Find(KNewLinePattern);
       
   627             while (error != KErrNotFound)
       
   628                 {
       
   629                 // error is a position
       
   630                 aValue.Replace(error, KNewLinePattern().Length(), KNewline );
       
   631                 error = aValue.Find(KNewLinePattern);
       
   632                 }
       
   633     		}
       
   634     	}
       
   635 
       
   636     file.Close();
       
   637     fs.Close();
       
   638     
       
   639     return err;
       
   640     }
       
   641 
       
   642 /**
       
   643 Launches sysutilsetup.exe which is a helper executable. It should be launched 
       
   644 when the current client does not have the correct capabilities to define Publish 
       
   645 and Subscribe properties.
       
   646 
       
   647 Flags are used to determine which Publish and Subscribe properties are defined 
       
   648 and set. The supported flags can be found in sysutilsetup.h.
       
   649 
       
   650 @param aFlags 			Used to determine which Publish and Subscribe properties 
       
   651 						should be defined and set. See sysutilsetup.h for 
       
   652 						supported flags.
       
   653 @return KErrNotReady	The excutable has panicked or was not found.
       
   654 @return -				Otherwise, one of the other system-wide error codes.
       
   655 @internalComponent
       
   656 */
       
   657 static TInt LaunchSetupExecutable( const TDesC& aFlags )
       
   658 	{
       
   659 	_LIT( KSysUtilSetupExeName, "Z:\\sys\\bin\\sysutilsetup.exe" );
       
   660 	const TUidType KSetupUid( KNullUid, KNullUid, KSysUtilSetupUid );
       
   661 	
       
   662 	RProcess setupProcess;
       
   663 	TInt err = setupProcess.Create( KSysUtilSetupExeName, aFlags, KSetupUid );
       
   664 	if( KErrNone != err )
       
   665 		{
       
   666 		return KErrNotFound == err ? KErrNotReady : err;
       
   667 		}
       
   668 	
       
   669 	TRequestStatus status;
       
   670 	setupProcess.Rendezvous( status );
       
   671 	if( KRequestPending != status.Int() )
       
   672 		{
       
   673 		setupProcess.Kill( 0 );		// Abort startup
       
   674 		}
       
   675 	else
       
   676 		{
       
   677 		setupProcess.Resume();		// Logon OK - start the server
       
   678 		}
       
   679 	
       
   680 	User::WaitForRequest( status );	// Wait for start or death
       
   681 	
       
   682 	// We can't use the 'exit reason' if the server panicked as this
       
   683 	// is the panic 'reason' and may be '0' which cannot be distinguished
       
   684 	// from KErrNone
       
   685 	err = setupProcess.ExitType() == EExitPanic ? KErrNotReady : status.Int();
       
   686 	setupProcess.Close();
       
   687 	
       
   688 	return err;
       
   689 	}
       
   690 
       
   691 /**
       
   692 Retrieves a string containing the version information for the given UID.
       
   693 
       
   694 @param aVersionUid	The UID that corresponds to the version information which is required.
       
   695 @param aValue		On return, contains the version string for the given aVersionUid.
       
   696 @return -			One of the system-wide error codes.
       
   697 @internalComponent
       
   698 */
       
   699 static TInt GetVersionPropertyData( const TUid& aVersionUid, TDes& aValue )
       
   700 	{
       
   701 	// The P&S property contains the version data (max length 64) and the error code
       
   702 	TBuf16<KSysUtilVersionTextLength + 1> temp;
       
   703 	TInt16 err = RProperty::Get( KSysUtilSetupUid, aVersionUid.iUid, temp );
       
   704 	
       
   705 	// If the P&S properties are not set we need to set them
       
   706 	if ( KErrNotFound == err )
       
   707 		{
       
   708 		__SYSUTIL_TRACE("Launching sysutilsetup.exe");
       
   709 		err = LaunchSetupExecutable( KSetVersionPropertiesFlag );
       
   710 		__SYSUTIL_TRACE("sysutilsetup.exe terminated");
       
   711 		if( KErrNone != err )
       
   712 			{
       
   713 			return err;
       
   714 			}
       
   715 		
       
   716 		err = RProperty::Get( KSysUtilSetupUid, aVersionUid.iUid, temp );
       
   717 		if( KErrNone != err )
       
   718 			{
       
   719 			return err;
       
   720 			}
       
   721 		}
       
   722 	
       
   723 	if( aValue.MaxLength() < temp.Length() - 1 )
       
   724 		{
       
   725 		aValue = temp.MidTPtr( 1, aValue.MaxLength() );
       
   726 		return KErrTooBig;
       
   727 		}
       
   728 	aValue = temp.MidTPtr( 1, temp.Length()  - 1 );
       
   729 	
       
   730 	return static_cast<TInt16>( temp[0] );
       
   731 	}
       
   732 
       
   733 /**
       
   734 Retrieves the version information from aFileName and stores it in a Publish and 
       
   735 Subscribe property which has a key of aKey.
       
   736 
       
   737 @param aFileName	The name of the file which contains the version information.
       
   738 @param aKey			The key to be used for the Publish and Subscribe property.
       
   739 @leave -			One of the system-wide error codes.
       
   740 @internalComponent
       
   741 */
       
   742 static void SetVersionPropertyL( const TDesC& aFileName, const TUid& aKey )
       
   743 	{
       
   744 	TFileName filePath;
       
   745 	User::LeaveIfError( GetFilePath( filePath ) );
       
   746 	filePath.Append( aFileName );
       
   747 	
       
   748 	// The P&S property must store the version data (max length 64) and the error code.
       
   749 	TUint16* versionData = static_cast<TUint16*>( User::AllocL( sizeof(TUint16) * (KSysUtilVersionTextLength + 1) ) );
       
   750 	CleanupDeletePushL( versionData );
       
   751 	
       
   752 	// The error code is store in the first TUint16 and the rest is for data.
       
   753 	TPtr16 versionDataPtr( versionData + 1, KSysUtilVersionTextLength );
       
   754 	TInt err = GetTextFromFile( filePath, versionDataPtr, ETrue );
       
   755 	if ( err != KErrNone )
       
   756 		{
       
   757 		__SYSUTIL_TRACE2( "Error: %d, while processing: %S", err, &filePath );
       
   758 		}
       
   759 	
       
   760 	// Store the error code from GetTextFromFile in the first TUint16.
       
   761 	versionData[0] = static_cast<TUint16>( err );
       
   762 	
       
   763 	err = RProperty::Define( aKey.iUid, RProperty::EByteArray, KSecurityPolicyNone, 
       
   764 							 KSecurityPolicyWriteDeviceData, KSysUtilVersionTextLength + 1 );
       
   765 	if ( KErrAlreadyExists != err )
       
   766 		{
       
   767 		User::LeaveIfError( err );
       
   768 		}
       
   769 	
       
   770 	versionDataPtr.Set( versionData, versionDataPtr.Length() + 1, versionDataPtr.Length() + 1 );
       
   771 	User::LeaveIfError( RProperty::Set( KSysUtilSetupUid, aKey.iUid, versionDataPtr ) );
       
   772 	CleanupStack::PopAndDestroy( 1 );
       
   773 	}
       
   774 
       
   775 /**
       
   776 Sets the version information Publish and Subscribe properties.
       
   777 
       
   778 @leave -			One of the system-wide error codes.
       
   779 @internalComponent
       
   780 */
       
   781 EXPORT_C void SetVersionPropertiesL()
       
   782 	{
       
   783 	SetVersionPropertyL( KSWVersionFileName, KSWVersionUid );
       
   784 	SetVersionPropertyL( KLangSWVersionFileName, KLangSWVersionUid );
       
   785 	SetVersionPropertyL( KLangVersionFileName, KLangVersionUid);
       
   786 	SetVersionPropertyL( KPRInformationFileName, KPRInformationUid );
       
   787 	}
       
   788 
       
   789 /**
       
   790 Compares two UIDs.
       
   791 
       
   792 @param 	aLeft	The first of two UIDs to compare.
       
   793 @param	aRight	The second of two UIDs to compare.
       
   794 @return	TInt	Zero if both UIDs are the same. Positive if aLeft is greater 
       
   795 				than aRight. Negative if aLeft is less than aRight.
       
   796 @leave -		One of the system-wide error codes.
       
   797 @internalComponent
       
   798 */
       
   799 static TInt CompareUids( const TInt32& aLeft, const TInt32& aRight )
       
   800 	{
       
   801 	TUint32 left = static_cast<TUint32>(aLeft);
       
   802 	TUint32 right = static_cast<TUint32>(aRight);
       
   803 	if( left == right )
       
   804 		{
       
   805 		return 0;
       
   806 		}
       
   807 	else if ( left < right )
       
   808 		{
       
   809 		return -1;
       
   810 		}
       
   811 	return 1;
       
   812 	}
       
   813 
       
   814 /**
       
   815 Finds the deviceattributes.ini file which best match the current locale. If more 
       
   816 than one INI file is found for the current locale (this is a result of having 
       
   817 different versions of the INI file in different ROFS sections) then the contents 
       
   818 of the INI file are merged. If a attribute appears more than once then the most 
       
   819 recent value is taken. On return akeys and aValues will contain the merged 
       
   820 results.
       
   821 
       
   822 Note: The keys and values are in UID order from low to high.
       
   823 
       
   824 @param	aKeys		On return, contains the attribute UIDs.
       
   825 @param  aValues		On return, contains the attribute values.
       
   826 @leave	KErrGeneral A UID in the INI file is missing the '0x' hex prefix.
       
   827 @leave	-			Otherwise, one of the other system-wide error codes.
       
   828 @internalComponent
       
   829 */
       
   830 static void ReadDeviceAttribFilesAsArraysL( 
       
   831 	RArray<TInt32>& aKeys, 
       
   832 	CDesC16ArraySeg& aValues )
       
   833 	{
       
   834 	_LIT( KWildCardChar, "*" );
       
   835 	
       
   836 	RFs fs;
       
   837 	fs.Connect();
       
   838 	CleanupClosePushL( fs );
       
   839 	
       
   840 	// Get the localised version of deviceattributes.ini, if available, and use
       
   841 	// it to create a search pattern which will be used to find versions of the
       
   842 	// file that may be available in additional ROFS sections.
       
   843 	TFileName matchPattern;
       
   844 	User::LeaveIfError( GetFilePath( matchPattern ) );
       
   845 	matchPattern.Append( KDeviceAttributesFileName );
       
   846 	BaflUtils::NearestLanguageFile( fs, matchPattern );
       
   847 	matchPattern.Append( KWildCardChar );
       
   848 	
       
   849 	// Get a list of all the versions of the localised deviceattributes.ini
       
   850 	// that may be available in additional ROFS sections. If an error occurs
       
   851 	// the default values will be used.
       
   852 	CDir* iniFileList = NULL;
       
   853 	TInt err = fs.GetDir( matchPattern, KEntryAttReadOnly | KEntryAttHidden | 
       
   854 							KEntryAttSystem | KEntryAttArchive, ESortByName, iniFileList );
       
   855 	
       
   856 	__SYSUTIL_TRACE1( "Error: %d, while getting a list of deviceattribute.ini files", err );
       
   857 	
       
   858 	if( err == KErrNone )
       
   859 		{
       
   860 		CleanupStack::PushL( iniFileList );
       
   861 		// Go through each INI file (starting with the last file first) extracting 
       
   862 		// the keys and values which are then stored in the two provided arrays. 
       
   863 		// This keys and values are stored in key order from low to high. Only the 
       
   864 		// most recent version of each value is stored i.e. the value in the INI 
       
   865 		// file which is stored in the newest ROFS section.	
       
   866 		TLinearOrder<TInt32> orderer( CompareUids );
       
   867 		for( TInt iniNumber = iniFileList->Count() - 1; iniNumber >= 0; iniNumber-- )
       
   868 			{
       
   869 			// Get next INI file
       
   870 			TFileName iniPath;
       
   871 			User::LeaveIfError( GetFilePath( iniPath ) );
       
   872 			iniPath.Append( (*iniFileList)[iniNumber].iName );
       
   873 			
       
   874 			BSUL::CIniDocument16* iniFile = NULL;
       
   875 			TRAPD( err, iniFile = BSUL::CIniDocument16::NewL( fs, iniPath ) );
       
   876 			__SYSUTIL_TRACE1("BSUL::CIniDocument16::NewL error = %d", err);
       
   877 			if( err == KErrNone )
       
   878 				{
       
   879 				CleanupStack::PushL( iniFile );
       
   880 				
       
   881 				RArray<TPtrC16> iniFileSections;
       
   882 				iniFile->GetSectionList( iniFileSections );
       
   883 				CleanupClosePushL( iniFileSections );
       
   884 				
       
   885 				// For each section get the key/value pairs and insert in order to 
       
   886 				// the provided arrays. If a key already exists do not insert the 
       
   887 				// value in aValue.
       
   888 				TInt numIniFileSections = iniFileSections.Count();
       
   889 				for( TInt sectionNum = 0; sectionNum < numIniFileSections; sectionNum++ )
       
   890 					{
       
   891 					BSUL::CIniSecIter16* sectionIter = BSUL::CIniSecIter16::NewL( iniFileSections[sectionNum], iniFile );
       
   892 					CleanupStack::PushL( sectionIter );
       
   893 					
       
   894 					TPtrC16 key;
       
   895 					TPtrC16 value;
       
   896 					while( sectionIter->Next( key, value ) )
       
   897 						{
       
   898 						const TChar char0('0');
       
   899 						const TChar charX('x');
       
   900 						
       
   901 						TUint32 tempUid;
       
   902 						TLex16 lex( key );
       
   903 						
       
   904 						// Skip over the '0' and 'x' hex number prefix
       
   905 						if( lex.Get() != char0 || lex.Get() != charX )
       
   906 							{
       
   907 							User::Leave(KErrGeneral);
       
   908 							}
       
   909 						User::LeaveIfError( lex.Val( tempUid, EHex ) );	
       
   910 						
       
   911 						TInt err = aKeys.InsertInOrder( static_cast<TInt32>(tempUid), orderer );
       
   912 						if( KErrAlreadyExists != err )
       
   913 							{
       
   914 							User::LeaveIfError( err );
       
   915 							
       
   916 							TInt index = aKeys.FindInOrder( static_cast<TInt32>(tempUid), orderer );
       
   917 							aValues.InsertL( index, value );
       
   918 							}
       
   919 						}
       
   920 					CleanupStack::PopAndDestroy( 1 ); // sectionIter
       
   921 					}
       
   922 				CleanupStack::PopAndDestroy( 2 ); // iniFile and iniFileSections
       
   923 				}
       
   924 			}
       
   925 		CleanupStack::PopAndDestroy( 1 ); // iniFileList
       
   926 		}
       
   927 	CleanupStack::PopAndDestroy( 1 ); // fs
       
   928 	}
       
   929 
       
   930 /**
       
   931 Retrieves the provisioned device type information attribute key/value pairs 
       
   932 which are stored in aKeys and aValues.
       
   933 
       
   934 Note: The keys and values are in UID order from low to high.
       
   935 
       
   936 @param	aKeys		On return, contains the attribute UIDs.
       
   937 @param	aValues		On return, contains the attribute values.
       
   938 @leave	KErrCorrupt	There is a mismatch between the number of keys and values or
       
   939 					an invalid key has been provided.
       
   940 @leave	-			Otherwise, one of the other system-wide error codes.
       
   941 @panic KErrTooBig	More than 450 attributes where provisioned.
       
   942 @internalComponent
       
   943 */
       
   944 static void GetDeviceAttributesL( RArray<TInt32>& aKeys, CDesC16ArraySeg& aValues )
       
   945 	{
       
   946 	RArray<TInt32> iniKeys;
       
   947 	CleanupClosePushL( iniKeys );
       
   948 	
       
   949 	CDesC16ArraySeg* iniValues = new (ELeave) CDesC16ArraySeg( 8 );
       
   950 	CleanupStack::PushL( iniValues );
       
   951 	
       
   952 	// First try to get the device type information attributes from the INI file/s.
       
   953 	ReadDeviceAttribFilesAsArraysL( iniKeys, *iniValues );
       
   954 	
       
   955 	if( !KSysUtilDisableDeviceTypeInfoSetupExe )
       
   956 		{
       
   957 		// Now try to get the device type information attributes from a DLL.
       
   958 		TFileName deviceAttributeDllLocation;
       
   959 		GetDllLocationL(deviceAttributeDllLocation);
       
   960 		
       
   961 		RLibrary deviceAttributeDll;
       
   962 		TInt err = deviceAttributeDll.Load( deviceAttributeDllLocation );
       
   963 		CleanupClosePushL( deviceAttributeDll );
       
   964 		
       
   965 		if( KErrNone == err )
       
   966 			{
       
   967 			SysUtilPlugin::GetDeviceAttributesAsArraysFuncL GetDeviceAttributesAsArraysL = reinterpret_cast<SysUtilPlugin::GetDeviceAttributesAsArraysFuncL>( deviceAttributeDll.Lookup( SysUtilPlugin::EGetDeviceAttributesAsArraysLOrdinal ) );
       
   968 			User::LeaveIfNull( &GetDeviceAttributesAsArraysL );
       
   969 			GetDeviceAttributesAsArraysL( aKeys, aValues );
       
   970 			}
       
   971 		else
       
   972 			{
       
   973 			__SYSUTIL_TRACE1("Could not load sysutilplug.dll with error: %d ", err);
       
   974 			}
       
   975 		CleanupStack::PopAndDestroy( 1 );
       
   976 		}
       
   977 	
       
   978 	// Merge results with the INI taking lowest priority i.e. if the value already
       
   979 	// exists in aKeys/aValues then ignore the one in iniKeys/iniValues.
       
   980 	TLinearOrder<TInt32> orderer( CompareUids );
       
   981 	TInt numIniAttribs = iniKeys.Count();
       
   982 	for( TInt keyNum = 0; keyNum < numIniAttribs; keyNum++ )
       
   983 		{
       
   984 		TInt err = aKeys.InsertInOrder( iniKeys[keyNum], orderer );
       
   985 		if( KErrAlreadyExists != err )
       
   986 			{
       
   987 			User::LeaveIfError( err );
       
   988 			
       
   989 			TInt index = aKeys.FindInOrder( iniKeys[keyNum], orderer );
       
   990 			aValues.InsertL( index, (*iniValues)[keyNum] );
       
   991 			}
       
   992 		}	
       
   993 	CleanupStack::PopAndDestroy( 2 );
       
   994 	
       
   995 	// Check we have the same number of keys and values and that we don't have too many keys
       
   996 	if( aKeys.Count() != aValues.Count() )
       
   997 		{
       
   998 		User::Leave( KErrCorrupt );
       
   999 		}
       
  1000 	else if( aKeys.Count() > KAttributeLimit )
       
  1001 		{
       
  1002 		_LIT( KPanicReason, "KAttributeLimit exceeded" );
       
  1003 		User::Panic( KPanicReason, KErrTooBig );
       
  1004 		}
       
  1005 	}
       
  1006 
       
  1007 /**
       
  1008 Validates major and minor version numbers. This means both values must be 
       
  1009 within the range 0 to KMaxTUint16. If the major, minor or both numbers are 
       
  1010 invalid their values will be replaced by KNullDesC16.
       
  1011 
       
  1012 @param	aKeys	An array which contains a list of device type information attribute
       
  1013 				UIDs. The UIDs corrospond to the values in aValues.
       
  1014 @param	aValues	An array which contains a list of device type information attribute
       
  1015 				values. The values corrospond to the UIDs in aKeys.
       
  1016 @internalComponent
       
  1017 */
       
  1018 static void ValidateVersionNumbersL( RArray<TInt32>& aKeys, CDesC16ArraySeg& aValues, const TUid& aMajorVersionUid, const TUid& aMinorVersionUid)
       
  1019 	{
       
  1020 	TLinearOrder<TInt32> orderer( CompareUids );
       
  1021 	TInt pos = aKeys.FindInOrder( aMajorVersionUid.iUid, orderer );
       
  1022 	if( KErrNotFound != pos )
       
  1023 		{
       
  1024 		if( aKeys[pos + 1] == aMinorVersionUid.iUid )
       
  1025 			{		
       
  1026 			TInt32 value;
       
  1027 			TLex16 lex( aValues[pos] );
       
  1028 			TInt err = lex.Val( value );
       
  1029 				
       
  1030 			if( KErrNone == err && value >= 0 && value <= KMaxTUint16 )
       
  1031 				{
       
  1032 				lex = aValues[pos+ 1];
       
  1033 				err = lex.Val( value );
       
  1034 				
       
  1035 				if( KErrNone == err && value >= 0 && value <= KMaxTUint16 )
       
  1036 					{
       
  1037 					return;
       
  1038 					}
       
  1039 				}
       
  1040 			aValues.Delete( pos + 1 );
       
  1041 			aValues.InsertL( pos + 1, KNullDesC16 );
       
  1042 			}
       
  1043 		aValues.Delete( pos );
       
  1044 		aValues.InsertL( pos, KNullDesC16 );
       
  1045 		return;
       
  1046 		}
       
  1047 
       
  1048 	pos = aKeys.FindInOrder( aMinorVersionUid.iUid, orderer );
       
  1049 	if( KErrNotFound != pos )
       
  1050 		{
       
  1051 		aValues.Delete( pos );
       
  1052 		aValues.InsertL( pos, KNullDesC16 );
       
  1053 		}
       
  1054 	}
       
  1055 
       
  1056 /**
       
  1057 Gets the device type information attributes and stores them in their formatted form.
       
  1058 
       
  1059 @return	TUint16*	Formatted device type information attributes.
       
  1060 @internalComponent
       
  1061 */
       
  1062 static TUint16* FormattedDeviceTypeInfoL()
       
  1063 	{
       
  1064 	RArray<TInt32> keys;
       
  1065 	CleanupClosePushL( keys );
       
  1066 	
       
  1067 	CDesC16ArraySeg* values = new (ELeave) CDesC16ArraySeg( 8 );
       
  1068 	CleanupStack::PushL( values );
       
  1069 	
       
  1070 	GetDeviceAttributesL( keys, *values );
       
  1071 	
       
  1072 	// Validate the major and minor UI and OS version numbers. This should be done now to avoid repeated processing
       
  1073 	// later on when the client calls either of the GetUIPlatformVersion APIs. An added advantage of doing 
       
  1074 	// this now is that we save memory space if the version numbers are corrupt.
       
  1075 	ValidateVersionNumbersL( keys, *values, KUIPlatformVersionMajorUid, KUIPlatformVersionMinorUid );
       
  1076 	ValidateVersionNumbersL( keys, *values, KOSVersionMajorUid, KOSVersionMinorUid );
       
  1077 	
       
  1078 	TUint16* deviceAttributes = CreateDeviceTypeInfoPSDataL( keys, *values );
       
  1079 
       
  1080 	CleanupStack::PopAndDestroy( 2 );
       
  1081 	
       
  1082 	return deviceAttributes;
       
  1083 	}
       
  1084 
       
  1085 /**
       
  1086 Sets the Device Type Information attributes Publish and Subscribe property 
       
  1087 value. If the property does not already exist it will define it. Otherwise, it 
       
  1088 will set the value again.
       
  1089 
       
  1090 @leave -	One of the system-wide error codes.
       
  1091 @internalComponent
       
  1092 */
       
  1093 EXPORT_C void SetDeviceTypeInfoPropertyL()
       
  1094 	{
       
  1095 	TUint16* deviceAttributes = FormattedDeviceTypeInfoL();
       
  1096 	CleanupStack::PushL( deviceAttributes );
       
  1097 
       
  1098 	// Set the Publish and Subscribe property
       
  1099 	TPtrC16 deviceAttributesTPtrC( deviceAttributes, deviceAttributes[0] );
       
  1100 	TInt propertyType = deviceAttributesTPtrC.Size() < 512 ? RProperty::EByteArray : RProperty::ELargeByteArray;
       
  1101 	
       
  1102 	TInt err = RProperty::Define( KDeviceTypeInfoUid.iUid, propertyType, KSecurityPolicyNone, 
       
  1103 								  KSecurityPolicyWriteDeviceData, deviceAttributesTPtrC.Size() );
       
  1104 	if ( KErrAlreadyExists != err )
       
  1105 		{
       
  1106 		User::LeaveIfError( err );
       
  1107 		}	
       
  1108 	User::LeaveIfError( RProperty::Set( KSysUtilSetupUid, KDeviceTypeInfoUid.iUid, deviceAttributesTPtrC ) );
       
  1109 
       
  1110 	CleanupStack::PopAndDestroy( 1 );
       
  1111 	}
       
  1112 
       
  1113 // ========================= SysUtil MEMBER FUNCTIONS ==========================
       
  1114 
       
  1115 /**
       
  1116 Obtains the displayable software version string. 
       
  1117 
       
  1118 Usage example:
       
  1119 @code
       
  1120 TBuf<KSysUtilVersionTextLength> version;
       
  1121 if ( SysUtil::GetSWVersion( version ) == KErrNone )
       
  1122 	{
       
  1123 	// Use the version string.
       
  1124 	...
       
  1125 	}
       
  1126 @endcode
       
  1127 The software version is provisioned by the device creator into the ROM
       
  1128 as a Unicode UTF16 format displayable string, for example:
       
  1129 
       
  1130 <code>V 1.0\\n29-07-07\\nBuild12345\\n(c) Symbian Software</code>
       
  1131 
       
  1132 This provisioned text string contains only one line of text with "\n" sequences
       
  1133 in the text which indicate a new line. This API will parse the
       
  1134 text and remove any "\n" sequences that it finds and replace it with the 
       
  1135 Unicode newline sequence - 0x000A. The resulting
       
  1136 buffer is then a unicode string with newline sequences built in. This
       
  1137 then can for example, allow the buffer to be displayed directly to the
       
  1138 screen already formatted on multiple lines.
       
  1139 
       
  1140 @param aValue On return, contains the software version string. The buffer should
       
  1141 have space for KSysUtilVersionTextLength characters. If the buffer is 
       
  1142 insufficient the descriptor is filled to its maximum length. If a buffer is 
       
  1143 provided that is longer than 64 characters, and the provisioned text is larger 
       
  1144 than 64 characters, the returned buffer is truncated at 64 characters (see error 
       
  1145 codes below).
       
  1146 @return KErrNone on success, KErrTooBig if the maximum length of the descriptor 
       
  1147 is insufficient to hold the provisioned text, or has been truncated (see above). 
       
  1148 In both cases new-line processing is done on the buffers. If a zero length
       
  1149 text string has been provisioned KErrEof is returned, and the length of the 
       
  1150 buffer is set to zero. If none of these cases apply then one of the Symbian 
       
  1151 error codes is returned if reading the version string fails.
       
  1152 */
       
  1153 EXPORT_C TInt SysUtil::GetSWVersion( TDes& aValue )
       
  1154 	{
       
  1155 	if( KSysUtilDisableVersionSetupExe )
       
  1156 		{
       
  1157 		__SYSUTIL_TRACE("GetSWVersion caching disabled");
       
  1158 		
       
  1159 		TFileName filePath;
       
  1160 		TInt err = GetFilePath( filePath );
       
  1161 		if( KErrNone != err)
       
  1162 			{
       
  1163 			return err;
       
  1164 			}
       
  1165 		
       
  1166 		filePath.Append( KSWVersionFileName );
       
  1167 		
       
  1168 		err = GetTextFromFile( filePath, aValue, ETrue );
       
  1169 		if ( err != KErrNone )
       
  1170 			{
       
  1171 			__SYSUTIL_TRACE2("Error: %d, while processing: %S",err, &filePath);
       
  1172 			}
       
  1173 		
       
  1174 		return err;
       
  1175 		}
       
  1176 	else
       
  1177 		{
       
  1178 		__SYSUTIL_TRACE("GetSWVersion caching enabled");
       
  1179 		return GetVersionPropertyData( KSWVersionUid, aValue );
       
  1180 		}
       
  1181 	}
       
  1182 
       
  1183 /**
       
  1184 Returns displayable software version which the currently installed language 
       
  1185 package is compatible with. 
       
  1186 
       
  1187 This version text is provisioned by the device creator into the ROM
       
  1188 as a Unicode UTF16 format displayable string, for example:
       
  1189 
       
  1190 <code>V 1.0\\n29-07-07\\nBuild12345\\n(c) Symbian Software</code>
       
  1191 
       
  1192 This provisioned text string contains only one line of text with "\n" sequences
       
  1193 in the text which indicate a new line. This API will parse the
       
  1194 text and remove any "\n" sequences that it finds and replace it with the 
       
  1195 Unicode newline sequence - 0x000A. The resulting
       
  1196 buffer is then a unicode string with newline sequences built in. This
       
  1197 then can for example, allow the buffer to be displayed directly to the
       
  1198 screen already formatted on multiple lines.
       
  1199 
       
  1200 @param aValue On return, contains the software version string. The buffer should
       
  1201 have space for KSysUtilVersionTextLength characters. If the buffer is 
       
  1202 insufficient the descriptor is filled to its maximum length. If a buffer is 
       
  1203 provided that is longer than 64 characters, and the provisioned text is larger 
       
  1204 than 64 characters, the returned buffer is truncated at 64 characters (see error 
       
  1205 codes below).
       
  1206 @return KErrNone on success, KErrTooBig if the maximum length of the descriptor 
       
  1207 is insufficient to hold the provisioned text, or has been truncated (see above). 
       
  1208 In both cases new-line processing is done on the buffers. If a zero length
       
  1209 text string has been provisioned KErrEof is returned, and the length of the 
       
  1210 buffer is set to zero. If none of these cases apply then one of the Symbian 
       
  1211 error codes is returned if reading the version string fails.
       
  1212 */
       
  1213 EXPORT_C TInt SysUtil::GetLangSWVersion( TDes& aValue )
       
  1214 	{
       
  1215 	if( KSysUtilDisableVersionSetupExe )
       
  1216 		{
       
  1217 		__SYSUTIL_TRACE("GetLangSWVersion caching disabled");
       
  1218 		
       
  1219 		TFileName filePath;
       
  1220 		TInt err = GetFilePath( filePath );
       
  1221 		if( KErrNone != err)
       
  1222 			{
       
  1223 			return err;
       
  1224 			}
       
  1225 		
       
  1226 		filePath.Append( KLangSWVersionFileName );
       
  1227 		
       
  1228 		err = GetTextFromFile( filePath, aValue, ETrue );
       
  1229 		if ( err != KErrNone )
       
  1230 			{
       
  1231 			__SYSUTIL_TRACE2("Error: %d, while processing: %S",err, &filePath);
       
  1232 			}
       
  1233 		
       
  1234 		return err;
       
  1235 		}
       
  1236 	else
       
  1237 		{
       
  1238 		__SYSUTIL_TRACE("GetLangSWVersion caching enabled");
       
  1239 		return GetVersionPropertyData( KLangSWVersionUid, aValue );
       
  1240 		}
       
  1241 	}
       
  1242 
       
  1243 /**
       
  1244 Obtains the displayable version of the currently installed language package.
       
  1245 This does NOT do any newline processing on the version text.
       
  1246 (unlike, for example GetLangSWVersion() or GetSWVersion()).
       
  1247 
       
  1248 This version text is provisioned by the device creator into the ROM
       
  1249 as a Unicode UTF16 format displayable string.
       
  1250 
       
  1251 @param aValue On return, contains the software version string. The buffer should
       
  1252 have space for KSysUtilVersionTextLength characters. If the buffer is 
       
  1253 insufficient the descriptor is filled to its maximum length. If a buffer is 
       
  1254 provided that is longer than 64 characters, and the provisioned text is larger 
       
  1255 than 64 characters, the returned buffer is truncated at 64 characters (see error 
       
  1256 codes below).
       
  1257 @return KErrNone on success, KErrTooBig if the maximum length of the descriptor 
       
  1258 is insufficient to hold the provisioned text, or has been truncated (see above). 
       
  1259 In both cases new-line processing is done on the buffers. If a zero length
       
  1260 text string has been provisioned KErrEof is returned, and the length of the 
       
  1261 buffer is set to zero. If none of these cases apply then one of the Symbian 
       
  1262 error codes is returned if reading the version string fails.
       
  1263 */
       
  1264 EXPORT_C TInt SysUtil::GetLangVersion( TDes& aValue )
       
  1265 	{
       
  1266 	if( KSysUtilDisableVersionSetupExe )
       
  1267 		{
       
  1268 		__SYSUTIL_TRACE("GetLangVersion caching disabled");
       
  1269 		
       
  1270 		TFileName filePath;
       
  1271 		TInt err = GetFilePath( filePath );
       
  1272 		if( KErrNone != err)
       
  1273 			{
       
  1274 			return err;
       
  1275 			}
       
  1276 		
       
  1277 		filePath.Append( KLangVersionFileName );
       
  1278 		
       
  1279 		err = GetTextFromFile( filePath, aValue, ETrue );
       
  1280 		if ( err != KErrNone )
       
  1281 			{
       
  1282 			__SYSUTIL_TRACE2("Error: %d, while processing: %S",err, &filePath);
       
  1283 			}
       
  1284 		
       
  1285 		return err;
       
  1286 		}
       
  1287 	else
       
  1288 		{
       
  1289 		__SYSUTIL_TRACE("GetLangVersion caching enabled");
       
  1290 		return GetVersionPropertyData( KLangVersionUid, aValue );
       
  1291 		}
       
  1292 	}
       
  1293 
       
  1294 /**
       
  1295 Obtains the displayable product release information string. 
       
  1296 
       
  1297 Usage example:
       
  1298 @code
       
  1299 TBuf<KSysUtilVersionTextLength> prInfo;
       
  1300 if ( SysUtil::GetPRInformation( prInfo ) == KErrNone )
       
  1301     {
       
  1302     // Use the version string.
       
  1303     ...
       
  1304     }
       
  1305 @endcode
       
  1306 The product release information is provisioned by the device creator into the ROM
       
  1307 as a Unicode UTF16 format displayable string, for example:
       
  1308 
       
  1309 <code>custom build\n20090626\nusb fix xyz</code>
       
  1310 or
       
  1311 <code>PR1.0</code>
       
  1312 or
       
  1313 <code>PR1.1</code>
       
  1314 
       
  1315 This provisioned text string contains only one line of text with "\n" sequences
       
  1316 in the text which indicate a new line. This API will parse the
       
  1317 text and remove any "\n" sequences that it finds and replace it with the 
       
  1318 Unicode newline sequence - 0x000A. The resulting
       
  1319 buffer is then a unicode string with newline sequences built in. This
       
  1320 then can for example, allow the buffer to be displayed directly to the
       
  1321 screen already formatted on multiple lines.
       
  1322 
       
  1323 @param aValue On return, contains the product release information string. The buffer should
       
  1324 have space for KSysUtilVersionTextLength characters. If the buffer is 
       
  1325 insufficient the descriptor is filled to its maximum length. If a buffer is 
       
  1326 provided that is longer than 64 characters, and the provisioned text is larger 
       
  1327 than 64 characters, the returned buffer is truncated at 64 characters.
       
  1328 @return KErrNone on success, KErrTooBig if the maximum length of the descriptor 
       
  1329 is insufficient to hold the provisioned text, or has been truncated. 
       
  1330 In both cases new-line processing is done on the buffers. If a zero length
       
  1331 text string has been provisioned KErrEof is returned, and the length of the 
       
  1332 buffer is set to zero. If none of these cases apply then one of the Symbian 
       
  1333 error codes is returned if reading the product release string fails.
       
  1334 */
       
  1335 EXPORT_C TInt SysUtil::GetPRInformation( TDes& aValue )
       
  1336     {
       
  1337 	TInt err = KErrNone;
       
  1338     if( KSysUtilDisableVersionSetupExe )
       
  1339         {
       
  1340         __SYSUTIL_TRACE("GetPRInformation caching disabled");
       
  1341         TFileName filePath;
       
  1342         GetFilePath( filePath );
       
  1343 		filePath.Append( KPRInformationFileName );
       
  1344 		err = GetTextFromFile( filePath, aValue, ETrue );
       
  1345 		if ( err != KErrNone )
       
  1346 			{
       
  1347 			__SYSUTIL_TRACE2("Error: %d, while processing: %S",err, &filePath);
       
  1348 			}
       
  1349 		}
       
  1350     else
       
  1351         {
       
  1352         __SYSUTIL_TRACE("GetPRInformation caching enabled");
       
  1353         err = GetVersionPropertyData( KPRInformationUid, aValue );
       
  1354         }
       
  1355 	return err;
       
  1356     }
       
  1357     
       
  1358 /**
       
  1359 Checks if free system drive storage space is or will fall below critical level.
       
  1360 The system drive (internal, read/write, persistent drive) is also known
       
  1361 as the FFS (internal flash file system).
       
  1362 
       
  1363 To calculate if a critical level has been reached the critical level threshold
       
  1364 setting will be used. This setting is available in the patchable data.
       
  1365 
       
  1366 RAM drives and non-RAM drives have different threshold levels, so the corresponding
       
  1367 setting will be used for the calculation depending on the drive type.
       
  1368 
       
  1369 RAM drives are defined to be drives that have the media type of EMediaRam
       
  1370 as returned by RFs. @see RFs::Drive
       
  1371 
       
  1372 To set the patchdata for the RAM drive threshold set the MACRO 
       
  1373 SYMBIAN_BAFL_SYSUTIL_RAM_DRIVE_CRITICAL_THRESHOLD at ROM build time to an
       
  1374 appropriate level. To set the patchdata for the non-RAM drive threshold
       
  1375 set the MACRO SYMBIAN_BAFL_SYSUTIL_OTHER_DISK_CRITICAL_THRESHOLD at ROM 
       
  1376 build time to an appropriate level.
       
  1377 
       
  1378 This method also needs to determine which drive is the FFS drive. To do
       
  1379 this patchable data has been provided. If the patchable data has not been
       
  1380 set, then RFs::GetSystemDrive() will be used to determine the FFS drive. 
       
  1381 
       
  1382 To set the patchdata to the FFS drive set the MACRO 
       
  1383 SYMBIAN_BAFL_SYSUTIL_DEFAULT_FFS_DRIVE to the appropriate drive letter. 
       
  1384 @see TDriveNumber
       
  1385 
       
  1386 This function exists here to maintain binary compatibility .
       
  1387 @see  SysUtil::FFSSpaceBelowCriticalLevelL
       
  1388 
       
  1389 @param aFs File server session. Must be given if available, e.g. from
       
  1390 EIKON environment. If NULL, this method will create a temporary session,
       
  1391 which causes the method to consume more time and system resources.
       
  1392 @param aBytesToWrite Number of bytes the caller is about to write to the
       
  1393 system drive. If value 0 is given, this method checks if the current system
       
  1394 drive space is already below critical level.
       
  1395 @return ETrue if system drive space would go below critical level after writing
       
  1396 aBytesToWrite more data, EFalse otherwise.
       
  1397 @leave System wide error codes
       
  1398 */
       
  1399 EXPORT_C TBool SysUtil::FFSSpaceBelowCriticalLevel_OldL(
       
  1400     RFs* aFs,
       
  1401     TInt aBytesToWrite )
       
  1402     {
       
  1403     __SYSUTIL_TRACE("SysUtil::FFSSpaceBelowCriticalLevel_OldL");
       
  1404     TBool retVal( EFalse );
       
  1405     
       
  1406     RFs fs;
       
  1407     if ( !aFs )
       
  1408         {
       
  1409         User::LeaveIfError( fs.Connect() );  // Create temp session.
       
  1410         CleanupClosePushL( fs );
       
  1411         }
       
  1412     else
       
  1413         {
       
  1414         if( aFs->Handle() == KNullHandle )
       
  1415         	{
       
  1416         	User::Panic(_L("BAFL"), EBafPanicRFsConnectArg );
       
  1417         	}
       
  1418         fs = *aFs;
       
  1419         }
       
  1420 
       
  1421     TInt ffsDrive = GetFFSDriveLetter( fs );
       
  1422     retVal = DiskSpaceBelowCriticalLevel_OldL(&fs, aBytesToWrite, ffsDrive );
       
  1423     
       
  1424 	if ( !aFs )
       
  1425 	    {
       
  1426 	    CleanupStack::PopAndDestroy(); // Close temp session
       
  1427 	    }
       
  1428     
       
  1429     return retVal;
       
  1430     }
       
  1431 
       
  1432 /**
       
  1433 Checks if free disk drive storage space is or will fall below critical
       
  1434 level. 
       
  1435 
       
  1436 To calculate if a critical level has been reached the critical level threshold
       
  1437 setting will be used. This setting is available in the patchable data.
       
  1438 
       
  1439 RAM drives  and non-RAM drives have different threshold levels, so the corresponding
       
  1440 setting will be used for the calculation depending on the drive type.
       
  1441 
       
  1442 RAM drives are defined to be drives that have the media type of EMediaRam
       
  1443 as returned by RFs. @see RFs::Drive
       
  1444  
       
  1445 To set the patchdata for the RAM drive threshold set the MACRO 
       
  1446 SYMBIAN_BAFL_SYSUTIL_RAM_DRIVE_CRITICAL_THRESHOLD at ROM build time to an
       
  1447 appropriate level. To set the patchdata for the non-RAM drive threshold
       
  1448 set the MACRO SYMBIAN_BAFL_SYSUTIL_OTHER_DISK_CRITICAL_THRESHOLD at ROM 
       
  1449 build time to an appropriate level.
       
  1450 
       
  1451 This function exists here to maintain binary compatibility .
       
  1452 @see  SysUtil::DiskSpaceBelowCriticalLevelL
       
  1453 
       
  1454 @param aFs File server session. Must be given if available, e.g. from
       
  1455 EIKON environment. If NULL, this method will create a temporary session,
       
  1456 which causes the method to consume more time and system resources.
       
  1457 @param aBytesToWrite Number of bytes the caller is about to write to
       
  1458 disk. If value 0 is given, this method checks if the current disk space
       
  1459 is already below critical level.
       
  1460 @param aDrive Identifies the disk drive to be checked. Numeric values
       
  1461 for identifying disk drives are defined in TDriveNumber enumeration.
       
  1462 @see TDriveNumber in f32file.h.
       
  1463 @return ETrue if disk space would go below critical level after writing
       
  1464 aBytesToWrite more data, EFalse otherwise.
       
  1465 @leave System wide error codes
       
  1466 */
       
  1467 EXPORT_C TBool SysUtil::DiskSpaceBelowCriticalLevel_OldL(
       
  1468     RFs* aFs,
       
  1469     TInt aBytesToWrite,
       
  1470     TInt aDrive )
       
  1471     {
       
  1472     __SYSUTIL_TRACE1("SysUtil::DiskSpaceBelowCriticalLevel_OldL( %d )",aDrive);
       
  1473     
       
  1474     RFs fs;
       
  1475     if ( !aFs )
       
  1476         {
       
  1477         User::LeaveIfError( fs.Connect() );  // Create temp session.
       
  1478         CleanupClosePushL( fs );
       
  1479         }
       
  1480     else
       
  1481         {
       
  1482         if( aFs->Handle() == KNullHandle )
       
  1483         	{
       
  1484         	User::Panic(_L("BAFL"), EBafPanicRFsConnectArg );
       
  1485         	}
       
  1486         fs = *aFs;
       
  1487         }
       
  1488 
       
  1489     TVolumeInfo vinfo;
       
  1490     // This may leave e.g. KErrNotReady if no drive
       
  1491     TInt errorCode = fs.Volume( vinfo, aDrive );
       
  1492     
       
  1493     if ( !aFs )
       
  1494         {
       
  1495         CleanupStack::PopAndDestroy(); // Close temp session
       
  1496         }
       
  1497         
       
  1498 	__SYSUTIL_TRACE1("SysUtil::DiskSpaceBelowCriticalLevel_OldL RFs::Volume returned error code %d.",errorCode);
       
  1499     User::LeaveIfError( errorCode );
       
  1500 
       
  1501     const TInt64 criticalLevel = FindCriticalLevelTresholdL( vinfo.iDrive.iType );
       
  1502     __SYSUTIL_TRACE3("SysUtil: CL treshold value: %Ld, Free: %Ld, Size: %Ld",criticalLevel,vinfo.iFree,vinfo.iSize);
       
  1503   
       
  1504     return ( vinfo.iFree - (TInt64)aBytesToWrite ) <= criticalLevel;
       
  1505     }
       
  1506 
       
  1507 /**
       
  1508 Checks if free MMC storage space is or will fall below critical
       
  1509 level. 
       
  1510 
       
  1511 To calculate if a critical level has been reached the critical level threshold
       
  1512 setting will be used. This setting is available in the patchable data.
       
  1513 
       
  1514 RAM drives and non-RAM drives have different threshold levels, so the corresponding
       
  1515 setting will be used for the calculation depending on the drive type.
       
  1516 
       
  1517 RAM drives are defined to be drives that have the media type of EMediaRam
       
  1518 as returned by RFs. @see RFs::Drive
       
  1519 
       
  1520 This method also needs to determine which drive is the MMC drive. To do
       
  1521 this a patchable data has been provided. If the patchable data
       
  1522 has not been set, then the drive will be fetched using BSUL.
       
  1523 @see CCachedDriveInfo
       
  1524 
       
  1525 To set the patchdata for the RAM drive threshold set the MACRO 
       
  1526 SYMBIAN_BAFL_SYSUTIL_RAM_DRIVE_CRITICAL_THRESHOLD at ROM build time to an
       
  1527 appropriate level. To set the patchdata for the non-RAM drive threshold
       
  1528 set the MACRO SYMBIAN_BAFL_SYSUTIL_OTHER_DISK_CRITICAL_THRESHOLD at ROM 
       
  1529 build time to an appropriate level.
       
  1530 
       
  1531 To set the patchdata to the MMC drive set the MACRO 
       
  1532 SYMBIAN_BAFL_SYSUTIL_DEFAULT_MMC_DRIVE to the appropriate drive letter. 
       
  1533 @see TDriveNumber
       
  1534 
       
  1535 This function exists here to maintain binary compatibility .
       
  1536 @see  SysUtil::MMCSpaceBelowCriticalLevelL
       
  1537 
       
  1538 @param aFs File server session. Must be given if available, e.g. from
       
  1539 EIKON environment. If NULL, this method will create a temporary session,
       
  1540 which causes the method to consume more time and system resources.
       
  1541 @param aBytesToWrite Number of bytes the caller is about to write to
       
  1542 MMC. If value 0 is given, this method checks if the current MMC space
       
  1543 is already below critical level.
       
  1544 @return ETrue if MMC space would go below critical level after writing
       
  1545 aBytesToWrite more data, EFalse otherwise.
       
  1546 @leave KErrNotFound if the MMC drive cannot be found, otherwise one of the
       
  1547 system-wide error codes.
       
  1548 */
       
  1549 EXPORT_C TBool SysUtil::MMCSpaceBelowCriticalLevel_OldL(RFs* aFs, TInt aBytesToWrite)
       
  1550 	{
       
  1551 	__SYSUTIL_TRACE("SysUtil::MMCSpaceBelowCriticalLevel_OldL");
       
  1552     TBool retVal(EFalse);
       
  1553 
       
  1554     RFs fs;
       
  1555     if ( !aFs )
       
  1556         {
       
  1557         User::LeaveIfError( fs.Connect() );  // Create temp session.
       
  1558         CleanupClosePushL( fs );
       
  1559         }
       
  1560     else
       
  1561         {
       
  1562         if( aFs->Handle() == KNullHandle )
       
  1563         	{
       
  1564         	User::Panic(_L("BAFL"), EBafPanicRFsConnectArg );
       
  1565         	}
       
  1566         fs = *aFs;
       
  1567         } 
       
  1568     
       
  1569     TInt mmcDrive = GetMMCDriveLetter( fs );
       
  1570     retVal = DiskSpaceBelowCriticalLevel_OldL(&fs, aBytesToWrite, mmcDrive );
       
  1571  	
       
  1572     if ( !aFs )
       
  1573         {
       
  1574         CleanupStack::PopAndDestroy(); // Close temp session
       
  1575         }
       
  1576  			
       
  1577     return retVal;
       
  1578     }
       
  1579 
       
  1580 /**
       
  1581 Checks if free system drive storage space is or will fall below critical level.
       
  1582 The system drive (internal, read/write, persistent drive) is also known
       
  1583 as the FFS (internal flash file system).
       
  1584 
       
  1585 To calculate if a critical level has been reached the critical level threshold
       
  1586 setting will be used. This setting is available in the patchable data.
       
  1587 
       
  1588 RAM drives and non-RAM drives have different threshold levels, so the corresponding
       
  1589 setting will be used for the calculation depending on the drive type.
       
  1590 
       
  1591 RAM drives are defined to be drives that have the media type of EMediaRam
       
  1592 as returned by RFs. @see RFs::Drive
       
  1593 
       
  1594 To set the patchdata for the RAM drive threshold set the MACRO 
       
  1595 SYMBIAN_BAFL_SYSUTIL_RAM_DRIVE_CRITICAL_THRESHOLD at ROM build time to an
       
  1596 appropriate level. To set the patchdata for the non-RAM drive threshold
       
  1597 set the MACRO SYMBIAN_BAFL_SYSUTIL_OTHER_DISK_CRITICAL_THRESHOLD at ROM 
       
  1598 build time to an appropriate level.
       
  1599 
       
  1600 This method also needs to determine which drive is the FFS drive. To do
       
  1601 this patchable data has been provided. If the patchable data has not been
       
  1602 set, then RFs::GetSystemDrive() will be used to determine the FFS drive. 
       
  1603 
       
  1604 To set the patchdata to the FFS drive set the MACRO 
       
  1605 SYMBIAN_BAFL_SYSUTIL_DEFAULT_FFS_DRIVE to the appropriate drive letter. 
       
  1606 @see TDriveNumber
       
  1607 
       
  1608 @param aFs File server session. Must be given if available, e.g. from
       
  1609 EIKON environment. If NULL, this method will create a temporary session,
       
  1610 which causes the method to consume more time and system resources.
       
  1611 @param aBytesToWrite Number of bytes the caller is about to write to the
       
  1612 system drive. If value 0 is given, this method checks if the current system
       
  1613 drive space is already below critical level.
       
  1614 @return ETrue if system drive space would go below critical level after writing
       
  1615 aBytesToWrite more data, EFalse otherwise.
       
  1616 @leave System wide error codes
       
  1617 */
       
  1618 
       
  1619 EXPORT_C TBool SysUtil::FFSSpaceBelowCriticalLevelL(
       
  1620     RFs* aFs,
       
  1621     TInt64 aBytesToWrite )
       
  1622     {
       
  1623     __SYSUTIL_TRACE("SysUtil::FFSSpaceBelowCriticalLevelL");
       
  1624     TBool retVal( EFalse );
       
  1625     
       
  1626     RFs fs;
       
  1627     if ( !aFs )
       
  1628         {
       
  1629         User::LeaveIfError( fs.Connect() );  // Create temp session.
       
  1630         CleanupClosePushL( fs );
       
  1631         }
       
  1632     else
       
  1633         {
       
  1634         if( aFs->Handle() == KNullHandle )
       
  1635         	{
       
  1636         	User::Panic(_L("BAFL"), EBafPanicRFsConnectArg );
       
  1637         	}
       
  1638         fs = *aFs;
       
  1639         }
       
  1640 
       
  1641     TInt ffsDrive = GetFFSDriveLetter( fs );
       
  1642     retVal = DiskSpaceBelowCriticalLevelL(&fs, aBytesToWrite, ffsDrive );
       
  1643     
       
  1644 	if ( !aFs )
       
  1645 	    {
       
  1646 	    CleanupStack::PopAndDestroy(); // Close temp session
       
  1647 	    }
       
  1648     
       
  1649     return retVal;
       
  1650     }
       
  1651 
       
  1652 /**
       
  1653 Checks if free disk drive storage space is or will fall below critical
       
  1654 level. 
       
  1655 
       
  1656 To calculate if a critical level has been reached the critical level threshold
       
  1657 setting will be used. This setting is available in the patchable data.
       
  1658 
       
  1659 RAM drives  and non-RAM drives have different threshold levels, so the corresponding
       
  1660 setting will be used for the calculation depending on the drive type.
       
  1661 
       
  1662 RAM drives are defined to be drives that have the media type of EMediaRam
       
  1663 as returned by RFs. @see RFs::Drive
       
  1664  
       
  1665 To set the patchdata for the RAM drive threshold set the MACRO 
       
  1666 SYMBIAN_BAFL_SYSUTIL_RAM_DRIVE_CRITICAL_THRESHOLD at ROM build time to an
       
  1667 appropriate level. To set the patchdata for the non-RAM drive threshold
       
  1668 set the MACRO SYMBIAN_BAFL_SYSUTIL_OTHER_DISK_CRITICAL_THRESHOLD at ROM 
       
  1669 build time to an appropriate level.
       
  1670 
       
  1671 Usage example:
       
  1672 @code
       
  1673 TInt64 dataSize = 500000000;
       
  1674 if ( SysUtil::DiskSpaceBelowCriticalLevelL( &iFsSession, dataSize, EDriveC ) )
       
  1675     {
       
  1676     // Can not write the data, there's not enough free space on disk.
       
  1677     ...
       
  1678     }
       
  1679 else
       
  1680     {
       
  1681     // It's ok to actually write the data.
       
  1682     ...
       
  1683     }
       
  1684 @endcode
       
  1685 @param aFs File server session. Must be given if available, e.g. from
       
  1686 EIKON environment. If NULL, this method will create a temporary session,
       
  1687 which causes the method to consume more time and system resources.
       
  1688 @param aBytesToWrite Number of bytes the caller is about to write to
       
  1689 disk. If value 0 is given, this method checks if the current disk space
       
  1690 is already below critical level.
       
  1691 @param aDrive Identifies the disk drive to be checked. Numeric values
       
  1692 for identifying disk drives are defined in TDriveNumber enumeration.
       
  1693 @see TDriveNumber in f32file.h.
       
  1694 @return ETrue if disk space would go below critical level after writing
       
  1695 aBytesToWrite more data, EFalse otherwise.
       
  1696 @leave System wide error codes
       
  1697 */
       
  1698 
       
  1699 EXPORT_C TBool SysUtil::DiskSpaceBelowCriticalLevelL(
       
  1700     RFs* aFs,
       
  1701     TInt64 aBytesToWrite,
       
  1702     TInt aDrive )
       
  1703     {
       
  1704     __SYSUTIL_TRACE1("SysUtil::DiskSpaceBelowCriticalLevelL( %d )",aDrive);
       
  1705     
       
  1706     RFs fs;
       
  1707     if ( !aFs )
       
  1708         {
       
  1709         User::LeaveIfError( fs.Connect() );  // Create temp session.
       
  1710         CleanupClosePushL( fs );
       
  1711         }
       
  1712     else
       
  1713         {
       
  1714         if( aFs->Handle() == KNullHandle )
       
  1715         	{
       
  1716         	User::Panic(_L("BAFL"), EBafPanicRFsConnectArg );
       
  1717         	}
       
  1718         fs = *aFs;
       
  1719         }
       
  1720 
       
  1721     TVolumeInfo vinfo;
       
  1722     // This may leave e.g. KErrNotReady if no drive
       
  1723     TInt errorCode = fs.Volume( vinfo, aDrive );
       
  1724     
       
  1725     if ( !aFs )
       
  1726         {
       
  1727         CleanupStack::PopAndDestroy(); // Close temp session
       
  1728         }
       
  1729         
       
  1730 	__SYSUTIL_TRACE1("SysUtil::DiskSpaceBelowCriticalLevelL RFs::Volume returned error code %d.",errorCode);
       
  1731     User::LeaveIfError( errorCode );
       
  1732 
       
  1733     const TInt64 criticalLevel = FindCriticalLevelTresholdL( vinfo.iDrive.iType );
       
  1734     __SYSUTIL_TRACE3("SysUtil: CL treshold value: %Ld, Free: %Ld, Size: %Ld",criticalLevel,vinfo.iFree,vinfo.iSize);
       
  1735   
       
  1736     return ( vinfo.iFree - aBytesToWrite ) <= criticalLevel;
       
  1737     }
       
  1738 
       
  1739 /**
       
  1740 Checks if free MMC storage space is or will fall below critical
       
  1741 level. 
       
  1742 
       
  1743 To calculate if a critical level has been reached the critical level threshold
       
  1744 setting will be used. This setting is available in the patchable data.
       
  1745 
       
  1746 RAM drives and non-RAM drives have different threshold levels, so the corresponding
       
  1747 setting will be used for the calculation depending on the drive type.
       
  1748 
       
  1749 RAM drives are defined to be drives that have the media type of EMediaRam
       
  1750 as returned by RFs. @see RFs::Drive
       
  1751 
       
  1752 This method also needs to determine which drive is the MMC drive. To do
       
  1753 this a patchable data has been provided. If the patchable data
       
  1754 has not been set, then the drive will be fetched using BSUL.
       
  1755 @see CCachedDriveInfo
       
  1756 
       
  1757 To set the patchdata for the RAM drive threshold set the MACRO 
       
  1758 SYMBIAN_BAFL_SYSUTIL_RAM_DRIVE_CRITICAL_THRESHOLD at ROM build time to an
       
  1759 appropriate level. To set the patchdata for the non-RAM drive threshold
       
  1760 set the MACRO SYMBIAN_BAFL_SYSUTIL_OTHER_DISK_CRITICAL_THRESHOLD at ROM 
       
  1761 build time to an appropriate level.
       
  1762 
       
  1763 To set the patchdata to the MMC drive set the MACRO 
       
  1764 SYMBIAN_BAFL_SYSUTIL_DEFAULT_MMC_DRIVE to the appropriate drive letter. 
       
  1765 @see TDriveNumber
       
  1766 
       
  1767 @param aFs File server session. Must be given if available, e.g. from
       
  1768 EIKON environment. If NULL, this method will create a temporary session,
       
  1769 which causes the method to consume more time and system resources.
       
  1770 @param aBytesToWrite Number of bytes the caller is about to write to
       
  1771 MMC. If value 0 is given, this method checks if the current MMC space
       
  1772 is already below critical level.
       
  1773 @return ETrue if MMC space would go below critical level after writing
       
  1774 aBytesToWrite more data, EFalse otherwise.
       
  1775 @leave KErrNotFound if the MMC drive cannot be found, otherwise one of the
       
  1776 system-wide error codes.
       
  1777 */
       
  1778 EXPORT_C TBool SysUtil::MMCSpaceBelowCriticalLevelL(RFs* aFs, TInt64 aBytesToWrite)
       
  1779 	{
       
  1780 	__SYSUTIL_TRACE("SysUtil::MMCSpaceBelowCriticalLevelL");
       
  1781     TBool retVal(EFalse);
       
  1782 
       
  1783     RFs fs;
       
  1784     if ( !aFs )
       
  1785         {
       
  1786         User::LeaveIfError( fs.Connect() );  // Create temp session.
       
  1787         CleanupClosePushL( fs );
       
  1788         }
       
  1789     else
       
  1790         {
       
  1791         if( aFs->Handle() == KNullHandle )
       
  1792         	{
       
  1793         	User::Panic(_L("BAFL"), EBafPanicRFsConnectArg );
       
  1794         	}
       
  1795         fs = *aFs;
       
  1796         } 
       
  1797     
       
  1798     TInt mmcDrive = GetMMCDriveLetter( fs );
       
  1799     retVal = DiskSpaceBelowCriticalLevelL(&fs, aBytesToWrite, mmcDrive );
       
  1800  	
       
  1801     if ( !aFs )
       
  1802         {
       
  1803         CleanupStack::PopAndDestroy(); // Close temp session
       
  1804         }
       
  1805  			
       
  1806     return retVal;
       
  1807     }
       
  1808 
       
  1809 
       
  1810 /**
       
  1811 Returns the FFS drive letter  
       
  1812 
       
  1813 This method determines which drive is the FFS drive. To do
       
  1814 this a patchable data has been provided. If the patchable data
       
  1815 has not been set, then the drive will be fetched via a call to
       
  1816 GetSystemDrive().
       
  1817 
       
  1818 To set the patchdata to the FFS drive set the MACRO 
       
  1819 SYMBIAN_BAFL_SYSUTIL_DEFAULT_FFS_DRIVE to the appropriate drive letter. 
       
  1820 @see TDriveNumber
       
  1821 
       
  1822 @return TInt the integer value equivalent of the TDriveNumber
       
  1823 */
       
  1824 EXPORT_C TInt SysUtil::GetFFSDriveLetter( RFs & aFs )
       
  1825 	{
       
  1826 	// Check the argument, and panic if necessary
       
  1827     if( aFs.Handle() == KNullHandle )
       
  1828     	{
       
  1829     	User::Panic(_L("KERN-EXEC"), 0);
       
  1830     	}
       
  1831 	
       
  1832 	// Check to see if FFS drive is set in patchable data
       
  1833 	TInt ffsDrive = KSysUtilDefaultFFSDrive;
       
  1834 	if( !(ffsDrive >= EDriveA && ffsDrive <= EDriveZ) )
       
  1835 		{
       
  1836 		ffsDrive =  aFs.GetSystemDrive();
       
  1837 		} 
       
  1838 
       
  1839 	return ffsDrive;
       
  1840 	}
       
  1841 
       
  1842 /**
       
  1843 Returns the MMC drive letter  
       
  1844 
       
  1845 This method determines which drive is the MMC drive. To do
       
  1846 this a patchable data has been provided. 
       
  1847 
       
  1848 To set the patchdata to the MMC drive set the MACRO 
       
  1849 SYMBIAN_BAFL_SYSUTIL_DEFAULT_MMC_DRIVE to the appropriate drive letter. 
       
  1850 @see TDriveNumber
       
  1851 
       
  1852 @return TInt the integer value equivalent of the TDriveNumber
       
  1853 */
       
  1854 
       
  1855 EXPORT_C TInt SysUtil::GetMMCDriveLetter( RFs & aFs )
       
  1856 	{
       
  1857 	// Check the argument, and panic if necessary
       
  1858     if( aFs.Handle() == KNullHandle )
       
  1859     	{
       
  1860     	User::Panic(_L("KERN-EXEC"), 0);
       
  1861     	}
       
  1862     
       
  1863     // Check to see if MMC drive is set in patchable data
       
  1864     TInt mmcDrive = KSysUtilDefaultMMCDrive;
       
  1865     
       
  1866 	// If a valid mmcDrive is not currently found in patchable data, then search for one.
       
  1867     if( !(mmcDrive >= EDriveA && mmcDrive <= EDriveZ) )
       
  1868 		{
       
  1869 		__SYSUTIL_TRACE("SysUtil::MMCSpaceBelowCriticalLevelL - searching for MMC drive");
       
  1870 	    // If mmcDrive is not set in patchable data, then fetch the MMC drive from BSUL.
       
  1871 	    BSUL::CCachedDriveInfo *cachedDriveInfo = BSUL::CCachedDriveInfo::NewLC( aFs );
       
  1872 	    // This will find valid MMC drive, leave if none available
       
  1873 	    mmcDrive = cachedDriveInfo->GetDefaultRemovableMemoryCardDriveL();
       
  1874 		__SYSUTIL_TRACE1("SysUtil::MMCSpaceBelowCriticalLevelL, Selected MMC drive %d.",mmcDrive);
       
  1875 		CleanupStack::PopAndDestroy(cachedDriveInfo);
       
  1876 		}
       
  1877 
       
  1878 	return mmcDrive;
       
  1879 	}
       
  1880 
       
  1881 /**
       
  1882 Creates and returns a populated CDeviceTypeInformation object which is used 
       
  1883 to access the device type information attributes.
       
  1884 
       
  1885 All the attributes are provisioned by the device creator.
       
  1886 
       
  1887 The returned object is owned by the calling code and so it is the calling
       
  1888 codes responsibility to delete this object when it no longer requires it. 
       
  1889 
       
  1890 @return	CDeviceTypeInformation*	A pointer to an instance of CDeviceTypeInformation.
       
  1891 @leave	KErrNoMemory			If there is not enough memory to create the object. 
       
  1892 @leave	KErrNotReady			If there was a problem retrieving the device type
       
  1893  								information attributes.
       
  1894 @leave	-			 			Otherwise one of the other system-wide error codes.
       
  1895 @see CDeviceTypeInformation
       
  1896 */
       
  1897 EXPORT_C CDeviceTypeInformation* SysUtil::GetDeviceTypeInfoL()
       
  1898 	{
       
  1899 	__SYSUTIL_TRACE("SysUtil::GetDeviceTypeInfoL");
       
  1900 	return CDeviceTypeInformation::NewL();
       
  1901 	}
       
  1902 
       
  1903 // ================= CDeviceTypeInformation MEMBER FUNCTIONS ===================
       
  1904 
       
  1905 /**
       
  1906 Class destructor.
       
  1907 
       
  1908 Performs any clean up such as deleting memory on the heap.
       
  1909 */
       
  1910 EXPORT_C CDeviceTypeInformation::~CDeviceTypeInformation()
       
  1911 	{
       
  1912 	SDeviceAttributes* attr = reinterpret_cast<SDeviceAttributes*>( iImpl );
       
  1913 	if( attr != NULL )
       
  1914 		{
       
  1915 		delete attr->iDeviceAttributes;
       
  1916 		delete attr;
       
  1917 		}
       
  1918 	}
       
  1919 
       
  1920 /**
       
  1921 Allocates and constructs an instance of CDeviceTypeInformation.
       
  1922 
       
  1923 @return A pointer to an instance of CDeviceTypeInformation.
       
  1924 @leave KErrNoMemory, if there is not enough memory to create the object.
       
  1925 @leave -			 Otherwise one of the other system-wide error codes.
       
  1926 */
       
  1927 CDeviceTypeInformation* CDeviceTypeInformation::NewL()
       
  1928 	{
       
  1929 	CDeviceTypeInformation* self = new (ELeave) CDeviceTypeInformation();
       
  1930 	CleanupStack::PushL( self );
       
  1931 	self->ConstructL();
       
  1932 	CleanupStack::Pop( self );
       
  1933 	return self;
       
  1934 	}
       
  1935 
       
  1936 /**
       
  1937 Class constructor.
       
  1938 
       
  1939 Performs any class construction tasks that will not cause a leave.
       
  1940 */
       
  1941 CDeviceTypeInformation::CDeviceTypeInformation() : iImpl( NULL )
       
  1942 	{
       
  1943 	}
       
  1944 
       
  1945 /**
       
  1946 Performs class creation tasks as part of two phase construction.
       
  1947 
       
  1948 Performs any class construction tasks that will cause a leave.
       
  1949 */
       
  1950 void CDeviceTypeInformation::ConstructL()
       
  1951 	{
       
  1952 	SDeviceAttributes* attr = new (ELeave) SDeviceAttributes;
       
  1953 	attr->iDeviceAttributes = NULL;
       
  1954 	iImpl = reinterpret_cast<TImpl*>( attr );
       
  1955 	
       
  1956 	if( !KSysUtilDisableDeviceTypeInfoSetupExe )
       
  1957 		{
       
  1958 		__SYSUTIL_TRACE("GetDeviceTypeInfoL caching enabled");
       
  1959 		
       
  1960 		// Check if the P&S property is already set. If it isn't then define and set it. If it 
       
  1961 		// is we will most likely get KErrOverflow as we are only providing enough space to 
       
  1962 		// get the first TUint16. This stores the length of the attribute.
       
  1963 		TUint16 attributesLength;
       
  1964 		TPtr16 attributesLengthTPtr( &attributesLength, 1 );
       
  1965 		TInt err = RProperty::Get( KSysUtilSetupUid, KDeviceTypeInfoUid.iUid, attributesLengthTPtr );
       
  1966 		if ( KErrNotFound == err )
       
  1967 			{
       
  1968 			__SYSUTIL_TRACE("Launching sysutilsetup.exe");
       
  1969 			User::LeaveIfError( LaunchSetupExecutable( KSetDeviceTypeInfoPropertyFlag ) );
       
  1970 			__SYSUTIL_TRACE("sysutilsetup.exe terminated");
       
  1971 			
       
  1972 			err = RProperty::Get( KSysUtilSetupUid, KDeviceTypeInfoUid.iUid, attributesLengthTPtr );
       
  1973 			if( KErrOverflow != err )
       
  1974 				{
       
  1975 				User::LeaveIfError( err );
       
  1976 				}
       
  1977 			}
       
  1978 		else if( KErrOverflow != err )
       
  1979 			{
       
  1980 			User::LeaveIfError( err );
       
  1981 			}
       
  1982 		
       
  1983 		attr->iDeviceAttributes = static_cast<TUint16*>( User::AllocL( sizeof(TUint16) * attributesLength ) );
       
  1984 		TPtr16 deviceAttributesTPtr( attr->iDeviceAttributes, attributesLength );
       
  1985 		User::LeaveIfError( RProperty::Get( KSysUtilSetupUid, KDeviceTypeInfoUid.iUid, deviceAttributesTPtr ) );
       
  1986 		}
       
  1987 	else
       
  1988 		{
       
  1989 		__SYSUTIL_TRACE("GetDeviceTypeInfoL caching disabled");
       
  1990 		attr->iDeviceAttributes = FormattedDeviceTypeInfoL();
       
  1991 		}
       
  1992 	}
       
  1993 
       
  1994 /**
       
  1995 Retrieves a reference to the attribute string which matches the provided 
       
  1996 UID. The attribute has a maximum length of KMaxAttributeLength UTF-16 
       
  1997 characters. 
       
  1998 
       
  1999 The attribute is provisioned by the device creator. If the device creator 
       
  2000 does not provide an attribute value for the given UID then KNullDesC16 
       
  2001 will be supplied and KErrNotFound will be returned. If the device creator 
       
  2002 has supplied an attribute value which is longer than KMaxAttributeLength 
       
  2003 then the supplied value will be truncated. In this case KErrKErrOverflow 
       
  2004 will be returned.
       
  2005 
       
  2006 @param	aAttributeUid	The UID of the required attribute.
       
  2007 @param	aValue			On return, contains the attribute value if successful 
       
  2008 						and KNullDesC16 otherwise.
       
  2009 @return KErrNone		Successful, the provisioned value has been returned.
       
  2010 @return KErrNotFound	A value for the given UID was not provisioned.
       
  2011 @return KErrOverflow	The provisioned attribute value has been truncated.
       
  2012 @return -				Otherwise, one of the other system-wide error codes.
       
  2013 @publishedPartner
       
  2014 @released
       
  2015 */
       
  2016 EXPORT_C TInt CDeviceTypeInformation::GetAttribute( const TUid& aAttributeUid, TPtrC16& aValue ) const
       
  2017 	{
       
  2018 	SDeviceAttributes* attr = reinterpret_cast<SDeviceAttributes*>( this->iImpl );
       
  2019 
       
  2020 	TInt attributeNumber = FindAttributeNumber( *attr, aAttributeUid );
       
  2021 	if( KErrNotFound != attributeNumber )
       
  2022 		{
       
  2023 		aValue.Set( attr->AttributePtr( attributeNumber ), attr->AttributeLength( attributeNumber ) );
       
  2024 		return attr->Error( attributeNumber );
       
  2025 		}
       
  2026 
       
  2027 	aValue.Set( KNullDesC16 );
       
  2028 	return KErrNotFound;
       
  2029 	}
       
  2030 
       
  2031 /**
       
  2032 Retrieves a reference to the Manufacturer Name string. This value conveys 
       
  2033 the name of the device manufacturer. The Manufacturer Name has a maximum 
       
  2034 length of KMaxAttributeLength UTF-16 characters. 
       
  2035 
       
  2036 This is a standard device type information attribute (it is common to all 
       
  2037 device creators) as such it can be assumed that an attribute value will 
       
  2038 always be retrieved.
       
  2039 
       
  2040 The Manufacturer Name is provisioned by the device creator. If the device 
       
  2041 creator does not provide a value for this attribute then a default value 
       
  2042 will be supplied instead and KDefaultValue will be returned. If the device 
       
  2043 creator has supplied a value and it is longer than KMaxAttributeLength 
       
  2044 then the provisioned value will be truncated. In this case KErrOverflow 
       
  2045 will be returned.
       
  2046 
       
  2047 Note: This attribute is represented by a UID of 0x10286358. 
       
  2048 
       
  2049 @param	aValue 			On return, contains the Manufacturer Name UTF-16 string.
       
  2050 @return KErrNone		Successful, the provisioned value has been returned.
       
  2051 @return KDefaultValue	Successful, the default value has been returned.
       
  2052 @return KErrOverflow	The provisioned attribute value has been truncated
       
  2053 @return -				Otherwise one of the other system-wide error codes.
       
  2054 */
       
  2055 EXPORT_C TInt CDeviceTypeInformation::GetManufacturerName( TPtrC16& aValue ) const
       
  2056 	{
       
  2057 	TInt err = GetAttribute( KManufacturerNameUid, aValue );
       
  2058 	if( KErrNotFound == err )
       
  2059 		{
       
  2060 		aValue.Set( KDefaultManufacturer );
       
  2061 		return CDeviceTypeInformation::KDefaultValue;
       
  2062 		}
       
  2063 	
       
  2064 	return err;
       
  2065 	}
       
  2066 
       
  2067 /**
       
  2068 Retrieves a reference to the Model Name string. This value conveys the 
       
  2069 model name of the device as recognisable by the end-user i.e. the consumer. 
       
  2070 The Model Name has a maximum length of KMaxAttributeLength UTF-16 
       
  2071 characters.  
       
  2072 
       
  2073 This is a standard device type information attribute (it is common to all 
       
  2074 device creators) as such it can be assumed that an attribute value will 
       
  2075 always be retrieved.
       
  2076 
       
  2077 The Model Name is provisioned by the device creator. If the device creator 
       
  2078 does not provide a value for this attribute then a default value will be 
       
  2079 supplied instead and KDefaultValue will be returned. If the device creator 
       
  2080 has supplied a value and it is longer than KMaxAttributeLength then the 
       
  2081 provisioned value will be truncated. In this case KErrKErrOverflow will be 
       
  2082 returned.
       
  2083 
       
  2084 Note: This attribute is represented by a UID of 0x10286359. 
       
  2085 
       
  2086 @param	aValue			On return, contains the Model Name.
       
  2087 @return KErrNone		Successful, the provisioned value has been returned.
       
  2088 @return KDefaultValue	Successful, the default value has been returned.
       
  2089 @return KErrOverflow	The provisioned attribute value has been truncated.
       
  2090 @return -				Otherwise, one of the other system-wide error codes.
       
  2091 */
       
  2092 EXPORT_C TInt CDeviceTypeInformation::GetModelName( TPtrC16& aValue ) const
       
  2093 	{
       
  2094 	TInt err = GetAttribute( KModelNameUid, aValue );
       
  2095 	if( KErrNotFound == err )
       
  2096 		{
       
  2097 		aValue.Set( KDefaultModelName );
       
  2098 		return CDeviceTypeInformation::KDefaultValue;
       
  2099 		}
       
  2100 	
       
  2101 	return err;
       
  2102 	}
       
  2103 
       
  2104 /**
       
  2105 Retrieves a reference to the Model Code string. This value conveys the 
       
  2106 internal model name or part number by which this model is known to the 
       
  2107 manufacturer. The Model Code has a maximum length of KMaxAttributeLength 
       
  2108 UTF-16 characters. 
       
  2109 
       
  2110 This is a standard device type information attribute (it is common to all 
       
  2111 device creators) as such it can be assumed that an attribute value will 
       
  2112 always be retrieved.
       
  2113 
       
  2114 The Model Code is provisioned by the device creator. If the device creator 
       
  2115 does not provide a value for this attribute then a default value will be 
       
  2116 supplied instead and KDefaultValue will be returned. If the device creator 
       
  2117 has supplied a value and it is longer than KMaxAttributeLength then the 
       
  2118 provisioned value will be truncated. In this case KErrKErrOverflow will be 
       
  2119 returned.
       
  2120 
       
  2121 Note: This attribute is represented by a UID of 0x1028635A. 
       
  2122 
       
  2123 @param	aValue			On return, contains the Model Code.
       
  2124 @return KErrNone		Successful, the provisioned value has been returned.
       
  2125 @return KDefaultValue	Successful, the default value has been returned.
       
  2126 @return KErrOverflow	The provisioned attribute value has been truncated.
       
  2127 @return -				Otherwise, one of the other system-wide error codes.
       
  2128 */
       
  2129 EXPORT_C TInt CDeviceTypeInformation::GetModelCode( TPtrC16& aValue ) const
       
  2130 	{
       
  2131 	TInt err = GetAttribute( KModelCodeUid, aValue );
       
  2132 	if( KErrNotFound == err )
       
  2133 		{
       
  2134 		aValue.Set( KDefaultModelCode );
       
  2135 		return CDeviceTypeInformation::KDefaultValue;
       
  2136 		}
       
  2137 	
       
  2138 	return err;
       
  2139 	}
       
  2140 
       
  2141 /**
       
  2142 Retrieves a reference to the Revision ID string. This value contains the 
       
  2143 device revision and/or variant identification string and conveys the 
       
  2144 specific version of the hardware and software used in the device. The 
       
  2145 Revision ID has a maximum length of KMaxAttributeLength UTF-16
       
  2146 characters. 
       
  2147 
       
  2148 This is a standard device type information attribute (it is common to all 
       
  2149 device creators) as such it can be assumed that an attribute value will 
       
  2150 always be retrieved.
       
  2151 
       
  2152 The Revision ID is provisioned by the device creator. If the device 
       
  2153 creator does not provide a value for this attribute then a default value 
       
  2154 will be supplied instead and KDefaultValue will be returned. If the device 
       
  2155 creator has supplied a value and it is longer than KMaxAttributeLength 
       
  2156 then the provisioned value will be truncated. In this case 
       
  2157 KErrKErrOverflow will be returned.
       
  2158 
       
  2159 Note: This attribute is represented by a UID of 0x1028635B. 
       
  2160 
       
  2161 @param	aValue			On return, contains the Revision ID (this also 
       
  2162 						includes the Variant ID).
       
  2163 @return KErrNone		Successful, the provisioned value has been returned.
       
  2164 @return KDefaultValue	Successful, the default value has been returned.
       
  2165 @return KErrOverflow	The provisioned attribute value has been truncated.
       
  2166 @return -				Otherwise, one of the other system-wide error codes.
       
  2167 */
       
  2168 EXPORT_C TInt CDeviceTypeInformation::GetRevisionID( TPtrC16& aValue ) const
       
  2169 	{
       
  2170 	TInt err = GetAttribute( KRevisionIDUid, aValue );
       
  2171 	if( KErrNotFound == err )
       
  2172 		{
       
  2173 		aValue.Set( KDefaultRevisionID );
       
  2174 		return CDeviceTypeInformation::KDefaultValue;
       
  2175 		}
       
  2176 	
       
  2177 	return err;
       
  2178 	}
       
  2179 
       
  2180 /**
       
  2181 Retrieves a copy of the default Device Name string. This value conveys 
       
  2182 the default name for the device as might be used for network identification 
       
  2183 e.g. Bluetooth nickname. The Device Name has a maximum length of 
       
  2184 KMaxAttributeLength UTF-16 characters. 
       
  2185 
       
  2186 This is a standard device type information attribute (it is common to all 
       
  2187 device creators) as such it can be assumed that an attribute value will 
       
  2188 always be retrieved.
       
  2189 
       
  2190 The Default Device Name is provisioned by the device creator. If the device 
       
  2191 creator does not provide a value for this attribute then a default value 
       
  2192 will be supplied instead and KDefaultValue will be returned. If the device 
       
  2193 creator has supplied a value and it is longer than KMaxAttributeLength or 
       
  2194 the user supplied descriptors length is less than KMaxAttributeLength then 
       
  2195 the provioned value will be truncated. In this case KErrKErrOverflow will 
       
  2196 be returned.
       
  2197 
       
  2198 Note: This attribute is represented by a UID of 0x1028635C. 
       
  2199 
       
  2200 @param	aValue			On return, contains the Default Device Name.
       
  2201 @return KErrNone		Successful, the provisioned value has been returned.
       
  2202 @return KDefaultValue	Successful, the default value has been returned.
       
  2203 @return KErrOverflow	The provisioned attribute value has been truncated.
       
  2204 @return -				Otherwise, one of the other system-wide error codes.
       
  2205 */
       
  2206 EXPORT_C TInt CDeviceTypeInformation::GetDefaultDeviceName( TPtrC16& aValue ) const
       
  2207 	{
       
  2208 	TInt err = GetAttribute( KDefaultDeviceNameUid, aValue );
       
  2209 	if( KErrNotFound == err )
       
  2210 		{
       
  2211 		aValue.Set( KDefaultDeviceName );
       
  2212 		return CDeviceTypeInformation::KDefaultValue;
       
  2213 		}
       
  2214 	
       
  2215 	return err;
       
  2216 	}
       
  2217 
       
  2218 /**
       
  2219 Retrieves a reference to the name of the UI Platform software used 
       
  2220 in the device. The UI Platform name has a maximum length of 
       
  2221 KMaxAttributeLength UTF-16 characters. 
       
  2222 
       
  2223 This is a standard device type information attribute (it is common to all 
       
  2224 device creators) as such it can be assumed that an attribute value will 
       
  2225 always be retrieved.
       
  2226 
       
  2227 The UI Platform is provisioned by the device creator. If the device 
       
  2228 creator does not provide a value for this attribute then a default value 
       
  2229 will be supplied instead and KDefaultValue will be returned. If the device 
       
  2230 creator has supplied a value and it is longer than KMaxAttributeLength 
       
  2231 then the provisioned value will be truncated. In this case 
       
  2232 KErrKErrOverflow will be returned.
       
  2233 
       
  2234 Note: This attribute is represented by a UID of 0x1028635D. 
       
  2235 
       
  2236 @param	aValue			On return, contains the UI Platform.
       
  2237 @return KErrNone		Successful, the provisioned value has been returned.
       
  2238 @return KDefaultValue	Successful, the default value has been returned.
       
  2239 @return KErrOverflow	The provisioned attribute value has been truncated.
       
  2240 @return -				Otherwise, one of the other system-wide error codes.
       
  2241 */
       
  2242 EXPORT_C TInt CDeviceTypeInformation::GetUIPlatformName( TPtrC16& aValue ) const
       
  2243 	{
       
  2244 	TInt err = GetAttribute( KUIPlatformNameUid, aValue );
       
  2245 	if( KErrNotFound == err )
       
  2246 		{
       
  2247 		aValue.Set( KDefaultUIPlatform );
       
  2248 		return CDeviceTypeInformation::KDefaultValue;
       
  2249 		}
       
  2250 	
       
  2251 	return err;
       
  2252 	}
       
  2253 
       
  2254 /**
       
  2255 Retrieves a reference to the UI Platform version used in the device for 
       
  2256 display, transmission or tagging purposes. The UI Platform version has a maximum 
       
  2257 length of KMaxAttributeLength UTF-16 characters. 
       
  2258 
       
  2259 The string should never be used for programmatic decisions based on assumed
       
  2260 functionality present in the device as device creators can vary the content of
       
  2261 the device firmware. Instead Feature Manager should be used to query the 
       
  2262 functional capabilities of a device. @see CFeatureDiscovery
       
  2263 
       
  2264 The UI Platform version is provisioned by the device creator. If the device 
       
  2265 creator does not provide a value for this attribute then a default value 
       
  2266 indicating unknown version will be supplied instead and KDefaultValue will 
       
  2267 be returned. If the device creator has supplied a value and it is longer than 
       
  2268 KMaxAttributeLength then the provisioned value will be truncated. In this case 
       
  2269 KErrOverflow will be returned. The format of the string is device dependent.
       
  2270 
       
  2271 Note: This attribute is represented by a UID of 0x10286360. 
       
  2272 
       
  2273 @param	aValue			On return, contains the UI version number of the 
       
  2274 						current UI platform.
       
  2275 @return KErrNone		Successful, the provisioned value has been returned.
       
  2276 @return KDefaultValue	Successful, the default value has been returned.
       
  2277 @return KErrOverflow	The provisioned attribute value has been truncated 
       
  2278 						due to the provided descriptor being too small.
       
  2279 @return -				Otherwise, one of the other system-wide error codes.
       
  2280 */
       
  2281 EXPORT_C TInt CDeviceTypeInformation::GetUIPlatformVersion( TPtrC16& aValue ) const
       
  2282 	{
       
  2283 	TInt err = GetAttribute( KUIPlatformVersionUid, aValue );
       
  2284 	if( KErrNotFound == err )
       
  2285 		{
       
  2286 		aValue.Set( KDefaultUIPlatformVersion );
       
  2287 		return CDeviceTypeInformation::KDefaultValue;
       
  2288 		}
       
  2289 	
       
  2290 	return err;
       
  2291 	}
       
  2292 
       
  2293 /**
       
  2294 Retrieves the UI platform major and minor version numbers as TUint16s. 
       
  2295 
       
  2296 The retrieved values are both standard device type information attributes 
       
  2297 (they are common to all device creators) as such it can be assumed that 
       
  2298 values will always be retrieved.
       
  2299 
       
  2300 The UI version is provisioned by the device creator. If the device creator 
       
  2301 provides invalid major and minor UI version numbers the default version 
       
  2302 numbers will be supplied and KErrCorrupt will be returned. If the device 
       
  2303 creator does not provide values for these attributes then default values 
       
  2304 will be supplied and KDefaultValue will be returned.
       
  2305 
       
  2306 Note: The major UI version number attribute is represented by a UID of 
       
  2307 0x1028635E and minor UI version number is represented by a UID of 
       
  2308 0x1028635F. 
       
  2309 
       
  2310 @param	aMajor			On return, contains the UI major version number.
       
  2311 @param	aMinor			On return, contains the UI minor version number.
       
  2312 @return KErrNone		Successful, the provisioned value has been returned.
       
  2313 @return KDefaultValue	Successful, the default value has been returned.
       
  2314 @return KErrCorrupt		The provisioned attribute value is invalid. The 
       
  2315 						default value has been returned.
       
  2316 @return -				Otherwise, one of the other system-wide error codes.
       
  2317 */
       
  2318 EXPORT_C TInt CDeviceTypeInformation::GetUIPlatformVersion( 
       
  2319 	TUint16& aMajor, 
       
  2320 	TUint16& aMinor ) const
       
  2321 	{
       
  2322 	SDeviceAttributes* attr = reinterpret_cast<SDeviceAttributes*>( this->iImpl );
       
  2323 	TPtrC16 majorVersionNum( KDefaultUIPlatformVersionMajor );
       
  2324 	TPtrC16 minorVersionNum( KDefaultUIPlatformVersionMinor );
       
  2325 	
       
  2326 	// If we have valid major and minor numbers use these instead of the default values. 
       
  2327 	// Otherwise check to see if the minor version number exists. If it does the error 
       
  2328 	// number associated with this should be used instead of KDefaultValue as the 
       
  2329 	// version number (in major/minor form) is corrupt.
       
  2330 	TInt attributeNumber = FindAttributeNumber( *attr, KUIPlatformVersionMajorUid );
       
  2331 	if( KErrNotFound != attributeNumber )
       
  2332 		{
       
  2333 		if( attr->Uid( attributeNumber + 1 ) == KUIPlatformVersionMinorUid.iUid )
       
  2334 			{
       
  2335 			if( KErrNone == attr->Error( attributeNumber ) && KErrNone == attr->Error( attributeNumber + 1 ) )
       
  2336 				{
       
  2337 				majorVersionNum.Set( attr->AttributePtr( attributeNumber ), attr->AttributeLength( attributeNumber ) );
       
  2338 				minorVersionNum.Set( attr->AttributePtr( attributeNumber + 1 ), attr->AttributeLength( attributeNumber + 1 ) );
       
  2339 				}
       
  2340 			}
       
  2341 		}
       
  2342 	else
       
  2343 		{
       
  2344 		attributeNumber = FindAttributeNumber( *attr, KUIPlatformVersionMinorUid );
       
  2345 		}
       
  2346 	
       
  2347 	TLex16 lex( majorVersionNum );
       
  2348 	lex.Val( aMajor, EDecimal );
       
  2349 	
       
  2350 	lex.Assign( minorVersionNum );
       
  2351 	lex.Val( aMinor, EDecimal );
       
  2352 
       
  2353 	return attributeNumber == KErrNotFound ? KDefaultValue : attr->Error( attributeNumber );
       
  2354 	}
       
  2355 
       
  2356 /**
       
  2357 Retrieves a reference to the Symbian OS version used in the device for 
       
  2358 display, transmission or tagging purposes. The Symbian OS version has a maximum 
       
  2359 length of KMaxAttributeLength UTF-16 characters. 
       
  2360 
       
  2361 The string should never be used for programmatic decisions based on assumed
       
  2362 functionality present in the device as device creators can very the content of
       
  2363 the device firmware. Instead Feature Manager should be used to query the 
       
  2364 functional capabilities of a device. @see CFeatureDiscovery
       
  2365 
       
  2366 This is a standard device type information attribute (it is common to all 
       
  2367 devices) as such it can be assumed that an attribute value will 
       
  2368 always be retrieved. 
       
  2369  
       
  2370 The Symbian OS version is provisioned by the device creator. If the device 
       
  2371 creator does not provide a value for this attribute then a default value 
       
  2372 indicating unknown version will be supplied instead and KDefaultValue will 
       
  2373 be returned. If the device creator has supplied a value and it is longer than 
       
  2374 KMaxAttributeLength then the provisioned value will be truncated. In this case 
       
  2375 KErrOverflow will be returned. The format of the string is device dependent.
       
  2376 
       
  2377 Note: This attribute is represented by a UID of 0x10286363. 
       
  2378 
       
  2379 @param	aValue			On return, contains the Symbian OS version number.
       
  2380 @return KErrNone		Successful, the provisioned value has been returned.
       
  2381 @return KDefaultValue	Successful, the default value has been returned.
       
  2382 @return KErrOverflow	The provisioned attribute value has been truncated 
       
  2383 						due to the provided descriptor being too small.
       
  2384 @return -				Otherwise one of the other system-wide error codes.
       
  2385 */
       
  2386 EXPORT_C TInt CDeviceTypeInformation::GetOSVersion( TPtrC16& aValue ) const
       
  2387 	{
       
  2388 	TInt err = GetAttribute( KOSVersionUid, aValue );
       
  2389 	if( KErrNotFound == err )
       
  2390 		{
       
  2391 		aValue.Set( KDefaultOSVersion );
       
  2392 		return CDeviceTypeInformation::KDefaultValue;
       
  2393 		}
       
  2394 	
       
  2395 	return err;
       
  2396 	}
       
  2397 
       
  2398 /**
       
  2399 Retrieves the Symbian OS major and minor version numbers as TUint16s. 
       
  2400 
       
  2401 The retrieved values are both standard device type information attributes 
       
  2402 (they are common to all device creators) as such it can be assumed that 
       
  2403 values will always be retrieved.
       
  2404 
       
  2405 The OS version is provisioned by the device creator. If the device creator 
       
  2406 provides invalid major and minor UI version numbers the default version 
       
  2407 numbers will be supplied and KErrCorrupt will be returned. If the device 
       
  2408 creator does not provide values for these attributes then default values 
       
  2409 will be supplied and KDefaultValue will be returned.
       
  2410 
       
  2411 Note: The major UI version number attribute is represented by a UID of 
       
  2412 0x10286361 and minor UI version number is represented by a UID of 
       
  2413 0x10286362. 
       
  2414 
       
  2415 @param	aMajor			On return, contains the OS major version number.
       
  2416 @param	aMinor			On return, contains the OS minor version number.
       
  2417 @return KErrNone		Successful, the provisioned value has been returned.
       
  2418 @return KDefaultValue	Successful, the default value has been returned.
       
  2419 @return KErrCorrupt		The provisioned attribute value is invalid. The 
       
  2420 						default value has been returned.
       
  2421 @return -				Otherwise, one of the other system-wide error codes.
       
  2422 */
       
  2423 EXPORT_C TInt CDeviceTypeInformation::GetOSVersion( TUint16& aMajor,
       
  2424 	TUint16& aMinor ) const
       
  2425 	{
       
  2426 	SDeviceAttributes* attr = reinterpret_cast<SDeviceAttributes*>( this->iImpl );
       
  2427 	TPtrC16 majorVersionNum( KDefaultOSVersionMajor );
       
  2428 	TPtrC16 minorVersionNum( KDefaultOSVersionMinor );
       
  2429 	
       
  2430 	// If we have valid major and minor numbers use these instead of the default values. 
       
  2431 	// Otherwise check to see if the minor version number exists. If it does the error 
       
  2432 	// number associated with this should be used instead of KDefaultValue as the 
       
  2433 	// version number (in major/minor form) is corrupt.
       
  2434 	TInt attributeNumber = FindAttributeNumber( *attr, KOSVersionMajorUid );
       
  2435 	if( KErrNotFound != attributeNumber )
       
  2436 		{
       
  2437 		if( attr->Uid( attributeNumber + 1 ) == KOSVersionMinorUid.iUid )
       
  2438 			{
       
  2439 			if( KErrNone == attr->Error( attributeNumber ) && KErrNone == attr->Error( attributeNumber + 1 ) )
       
  2440 				{
       
  2441 				majorVersionNum.Set( attr->AttributePtr( attributeNumber ), attr->AttributeLength( attributeNumber ) );
       
  2442 				minorVersionNum.Set( attr->AttributePtr( attributeNumber + 1 ), attr->AttributeLength( attributeNumber + 1 ) );
       
  2443 				}
       
  2444 			}
       
  2445 		}
       
  2446 	else
       
  2447 		{
       
  2448 		attributeNumber = FindAttributeNumber( *attr, KOSVersionMinorUid );
       
  2449 		}
       
  2450 	
       
  2451 	TLex16 lex( majorVersionNum );
       
  2452 	lex.Val( aMajor, EDecimal );
       
  2453 	
       
  2454 	lex.Assign( minorVersionNum );
       
  2455 	lex.Val( aMinor, EDecimal );
       
  2456 	
       
  2457 	return attributeNumber == KErrNotFound ? KDefaultValue : attr->Error( attributeNumber );
       
  2458 	}