--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/commonservices/sysutil/src/sysutil.cpp Tue Feb 02 00:53:00 2010 +0200
@@ -0,0 +1,2458 @@
+// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
+// All rights reserved.
+// This component and the accompanying materials are made available
+// under the terms of "Eclipse Public License v1.0"
+// which accompanies this distribution, and is available
+// at the URL "http://www.eclipse.org/legal/epl-v10.html".
+//
+// Initial Contributors:
+// Nokia Corporation - initial contribution.
+//
+// Contributors:
+//
+// Description:
+//
+
+
+
+// INCLUDE FILES
+#include "sysutil.h"
+#include <f32file.h>
+#include <bsul/ccacheddriveinfo.h>
+#include "sysutildomaincrkeys.h" // for disc space
+#include "sysutilinternalpskeys.h" // for disc space
+#include "sysutildebug.h" // debug helper
+#include "sysutilpatchdata.h" // patchable data defining the MMC drive integer identifer
+#include <baflpan.h>
+#include <e32property.h>
+#include <e32capability.h>
+#include <bsul/inifile.h>
+#include <bautils.h>
+#include "sysutilsetup.h"
+#include "sysutilplugindef.h"
+
+// File names of the files which store version and device type information.
+_LIT( KSWVersionFileName, "sw.txt" );
+_LIT( KLangSWVersionFileName, "langsw.txt" );
+_LIT( KLangVersionFileName, "lang.txt" );
+_LIT( KDeviceAttributesFileName, "deviceattributes.ini" );
+_LIT( KPRInformationFileName, "purpose.txt" );
+
+// UID of sysutilsetup.exe.
+const TUid KSysUtilSetupUid = {0x10285B3B};
+
+// Publish and Subscribe keys.
+const TUid KTestFilePathsUid = {0x10285B40};
+const TUid KSWVersionUid = {0x10285B3C};
+const TUid KLangSWVersionUid = {0x10285B3D};
+const TUid KLangVersionUid = {0x10285B3E};
+const TUid KDeviceTypeInfoUid = {0x10285B3F};
+const TUid KPRInformationUid = {0x20027BC4};
+
+// Device Type Information attribute UIDs.
+const TUid KManufacturerNameUid = {0x10286358};
+const TUid KModelNameUid = {0x10286359};
+const TUid KModelCodeUid = {0x1028635A};
+const TUid KRevisionIDUid = {0x1028635B};
+const TUid KDefaultDeviceNameUid = {0x1028635C};
+const TUid KUIPlatformNameUid = {0x1028635D};
+const TUid KUIPlatformVersionMajorUid = {0x1028635E};
+const TUid KUIPlatformVersionMinorUid = {0x1028635F};
+const TUid KUIPlatformVersionUid = {0x10286360};
+const TUid KOSVersionMajorUid = {0x10286361};
+const TUid KOSVersionMinorUid = {0x10286362};
+const TUid KOSVersionUid = {0x10286363};
+
+// This is the maximum number of Device Type Information attributes that can be
+// stored in the Device Type Information Publish and Subscribe property.
+const TUint16 KAttributeLimit = 450;
+
+// Default values that will be used if no plugin is provided, the
+// deviceattributes.ini file is missing or if a device attribute is not
+// specified by a licensee.
+_LIT16( KDefaultManufacturer, "Symbian" );
+_LIT16( KDefaultModelName, "Symbian" );
+_LIT16( KDefaultModelCode, "Symbian" );
+_LIT16( KDefaultRevisionID, "00.00" );
+_LIT16( KDefaultDeviceName, "Symbian" );
+_LIT16( KDefaultUIPlatform, "Symbian" );
+_LIT16( KDefaultUIPlatformVersionMajor, "0" );
+_LIT16( KDefaultUIPlatformVersionMinor, "0" );
+_LIT16( KDefaultUIPlatformVersion, "0.0" );
+_LIT16( KDefaultOSVersionMajor, "0" );
+_LIT16( KDefaultOSVersionMinor, "0" );
+_LIT16( KDefaultOSVersion, "0.0" );
+
+
+// Security policies for the Publish and Subscribe properties.
+_LIT_SECURITY_POLICY_C1( KSecurityPolicyNone, ECapability_None );
+_LIT_SECURITY_POLICY_S1( KSecurityPolicyWriteDeviceData, 0x10285B3B, ECapabilityWriteDeviceData );
+
+_LIT( KNewLinePattern, "\\n" );
+_LIT( KNewline, "\n" );
+
+
+/**
+Dummy sysutil implementation object - never instantiated.
+@internalComponent
+*/
+class CDeviceTypeInformation::TImpl
+ {
+ TUint32 iDummy;
+ };
+
+/**
+Stores a copy of the device type information attributes. For details of the
+memory layout see SGL.TS0017.201 BAFL Component Design Document.doc.
+@internalComponent
+*/
+typedef struct _SDeviceAttributes
+ {
+ TUint16 Length() const;
+ TUint16 Count() const;
+ TInt32 Uid( const TInt aAttributeIndex ) const;
+ TInt16 Error( const TInt aAttributeIndex ) const;
+ TInt AttributeLength( const TInt aAttributeIndex ) const;
+ TUint16* AttributePtr( const TInt aAttributeIndex ) const;
+ TUint16* iDeviceAttributes;
+ } SDeviceAttributes;
+
+/**
+@return TInt16 The number of elements in the memory block.
+*/
+inline TUint16 SDeviceAttributes::Length() const
+ {
+ return iDeviceAttributes[0];
+ }
+
+/**
+@return TInt16 The number of device type information attributes.
+*/
+inline TUint16 SDeviceAttributes::Count() const
+ {
+ return iDeviceAttributes[1];
+ }
+
+/**
+Returns the UID which matches the attribute with the given index.
+
+@param aAttribIndex The index of the attribute in iDeviceAttributes.
+@return TInt32 The UID of the attribute with the given index.
+*/
+inline TInt32 SDeviceAttributes::Uid( const TInt aAttribIndex ) const
+ {
+ return (iDeviceAttributes[2 + (2 * aAttribIndex)] << 16) + iDeviceAttributes[2 + (2 * aAttribIndex) + 1];
+ }
+
+/**
+Returns an error code associated with the device type information attribute with
+the given index. This error code is generated when the attribute is retrieved
+from a plugin/deviceattributes.ini. It indicates if a value was successfully
+read, no value was provided or if an error occured.
+
+@param aAttribIndex The index of the attribute in iDeviceAttributes.
+@return TInt16 The error of the attribute with the given index.
+*/
+inline TInt16 SDeviceAttributes::Error( const TInt aAttribIndex) const
+ {
+ return static_cast<TInt16>(iDeviceAttributes[2 + (3 * Count()) + 1 + aAttribIndex]);
+ }
+
+/**
+Returns the length of the attribute with the given index.
+
+@param aAttribIndex The index of the attribute in iDeviceAttributes.
+@return TInt The length of the attribute with the given index.
+*/
+inline TInt SDeviceAttributes::AttributeLength( const TInt aAttribIndex ) const
+ {
+ return iDeviceAttributes[2 + (2 * Count()) + aAttribIndex + 1] - iDeviceAttributes[2 + (2 * Count()) + aAttribIndex];
+ }
+
+/**
+Returns a pointer to the attribute value in iDeviceAttributes with the given
+index.
+
+@param aAttribIndex The index of the attribute in iDeviceAttributes.
+@return TUint16* A pointer to the attribute value with the given index.
+*/
+inline TUint16* SDeviceAttributes::AttributePtr( const TInt aAttribIndex ) const
+ {
+ return iDeviceAttributes + iDeviceAttributes[2 + (2 * Count()) + aAttribIndex];
+ }
+
+// ======== LOCAL FUNCTIONS ========
+
+/**
+Returns the total length of all the device type information attribute values stored
+in aValues.
+
+@param aKeys An array which contains a list of device type information attribute
+ UIDs. The UIDs corrospond to the values in aValues.
+@param aValues An array which contains a list of device type information attribute
+ values. The values corrospond to the UIDs in aKeys.
+@return TInt The total length of all the device type information attribute values
+ stored in aValues.
+@internalComponent
+*/
+static TInt AttributesTotalLength( RArray<TInt32>&, CDesC16ArraySeg& aValues )
+ {
+ TUint attributesTotalLength = 0;
+ TInt numAttributes = aValues.Count();
+ for( TInt attributeIndex = 0; attributeIndex < numAttributes; attributeIndex++ )
+ {
+ TInt attributeLength = aValues[attributeIndex].Length();
+ if( attributeLength < CDeviceTypeInformation::KMaxAttributeLength )
+ {
+ attributesTotalLength += attributeLength;
+ }
+ else
+ {
+ attributesTotalLength += CDeviceTypeInformation::KMaxAttributeLength;
+ }
+ }
+
+ return attributesTotalLength;
+ }
+
+/**
+Returns a pointer to some memory which contains the device type information attribute
+UIDs and values (these are contained in aKeys and aValues) in a compact format. The
+layout of the memory can be found in the Design Document
+(SGL.TS0017.201 BAFL Component Design Document.doc).
+
+@param aKeys An array which contains a list of device type information
+ attribute UIDs. The UIDs corrospond to the values in aValues.
+@param aValues An array which contains a list of device type information
+ attribute values. The values corrospond to the UIDs in aKeys.
+@leave - One of the system-wide error codes.
+@return TUint16* A pointer to the memory which contains the device type
+ information attribute UIDs and values in a compact format.
+@internalComponent
+*/
+static TUint16* CreateDeviceTypeInfoPSDataL( RArray<TInt32>& aKeys, CDesC16ArraySeg& aValues )
+ {
+ // See SGL.TS0017.201 BAFL Component Design Document.doc for more information on the
+ // memory requirements and layout.
+ TInt memoryElements = 3 + (4 * aKeys.Count()) + AttributesTotalLength( aKeys, aValues );
+
+ // Allocate memory to store the device type information attribute keys and values
+ TUint16* deviceAttributes = static_cast<TUint16*>( User::AllocL( sizeof(TUint16) * memoryElements ) );
+ CleanupStack::PushL( deviceAttributes );
+
+ // Store the attributes length and count
+ deviceAttributes[0] = memoryElements;
+ deviceAttributes[1] = aKeys.Count();
+
+ // Store the attribute UIDs, offsets of the attributes in the memory, error codes and attribute values.
+ if( deviceAttributes[1] > 0 )
+ {
+ // Set the first offset to point to the start of the attributes
+ deviceAttributes[2 + (2 * deviceAttributes[1])] = 2 + 1 + (4 * deviceAttributes[1]);
+
+ for( TInt attributeNumber = 0; attributeNumber < deviceAttributes[1]; attributeNumber++ )
+ {
+ // Store the UID as two TUint16s
+ deviceAttributes[2 + (2 * attributeNumber)] = static_cast<TUint16>(aKeys[attributeNumber] >> 16);
+ deviceAttributes[2 + (2 * attributeNumber) + 1] = static_cast<TUint16>(aKeys[attributeNumber]);
+
+ if( KUIPlatformVersionMajorUid.iUid == aKeys[attributeNumber] || KUIPlatformVersionMinorUid.iUid == aKeys[attributeNumber]
+ || KOSVersionMajorUid.iUid == aKeys[attributeNumber] || KOSVersionMinorUid.iUid == aKeys[attributeNumber] )
+ {
+ // If the values were present in the INI/plugin (as we have the attribute keys) and the values
+ // are KNullDesC16 then the values were corrupt.
+ if( aValues[attributeNumber].Compare( KNullDesC16 ) == 0 )
+ {
+ deviceAttributes[2 + (2 * deviceAttributes[1]) + 1 + attributeNumber] = deviceAttributes[2 + (2 * deviceAttributes[1]) + 1 + attributeNumber - 1];
+ deviceAttributes[2 + (3 * deviceAttributes[1]) + 1 + attributeNumber] = static_cast<TUint16>(KErrCorrupt);
+ continue;
+ }
+ }
+
+ // If the attribute value is too long we need to truncate it and set the error as KErrOverflow.
+ if( aValues[attributeNumber].Length() > CDeviceTypeInformation::KMaxAttributeLength )
+ {
+ deviceAttributes[2 + (2 * deviceAttributes[1]) + 1 + attributeNumber] = deviceAttributes[2 + (2 * deviceAttributes[1]) + attributeNumber] + CDeviceTypeInformation::KMaxAttributeLength;
+ deviceAttributes[2 + (3 * deviceAttributes[1]) + 1 + attributeNumber] = static_cast<TUint16>(KErrOverflow);
+ Mem::Copy( deviceAttributes + deviceAttributes[2 + (2 * deviceAttributes[1]) + attributeNumber], aValues[attributeNumber].Ptr(), CDeviceTypeInformation::KMaxAttributeLength * 2 );
+ }
+ else
+ {
+ deviceAttributes[2 + (2 * deviceAttributes[1]) + 1 + attributeNumber] = deviceAttributes[2 + (2 * deviceAttributes[1]) + attributeNumber] + aValues[attributeNumber].Length();
+ deviceAttributes[2 + (3 * deviceAttributes[1]) + 1 + attributeNumber] = KErrNone;
+ Mem::Copy( deviceAttributes + deviceAttributes[2 + (2 * deviceAttributes[1]) + attributeNumber], aValues[attributeNumber].Ptr(), aValues[attributeNumber].Size() );
+ }
+ }
+ }
+ CleanupStack::Pop( 1 );
+
+ return deviceAttributes;
+ }
+
+/**
+Helper function which deletes the Version and Device Type Information Publish and
+Subscribe properties. This is meant for testing purposes only and requires the
+KSysUtilTestModeEnabled constant to be patched to ETrue.
+
+@leave - One of the system-wide error codes.
+@internalComponent
+*/
+EXPORT_C void DeletePSPropertiesL()
+ {
+ if( KSysUtilTestModeEnabled )
+ {
+ TInt err = RProperty::Delete(KSWVersionUid.iUid);
+ if(err != KErrNotFound)
+ {
+ User::LeaveIfError(err);
+ }
+
+ err = RProperty::Delete(KLangSWVersionUid.iUid);
+ if(err != KErrNotFound)
+ {
+ User::LeaveIfError(err);
+ }
+
+ err = RProperty::Delete(KLangVersionUid.iUid);
+ if(err != KErrNotFound)
+ {
+ User::LeaveIfError(err);
+ }
+
+ err = RProperty::Delete(KDeviceTypeInfoUid.iUid);
+ if(err != KErrNotFound)
+ {
+ User::LeaveIfError(err);
+ }
+
+ err = RProperty::Delete(KPRInformationUid.iUid);
+ if(err != KErrNotFound)
+ {
+ User::LeaveIfError(err);
+ }
+ }
+ }
+
+/**
+Finds and returns the device type information attribute number in aAttr. This
+number is used as an index in a populated instance of SDeviceAttributes.
+
+@param aAttr A reference to SDeviceAttributes which contains a copy of the device type information attributes.
+@param aKey The UID of the device type information attribute which needs to be found.
+@return The attribute index number (position) in aAttr.
+@return KErrNotFound aKey is not present in aAttr.
+@internalComponent
+*/
+static TInt FindAttributeNumber( const SDeviceAttributes& aAttr, const TUid& aKey )
+ {
+ TInt bottom = 0;
+ TInt top = aAttr.Count() - 1;
+
+ while( bottom <= top )
+ {
+ TUint middle = bottom + ( top - bottom ) / 2;
+ if( static_cast<TUint32>(aKey.iUid) < aAttr.Uid( middle ) )
+ {
+ top = middle - 1;
+ }
+ else if( static_cast<TUint32>(aKey.iUid) > aAttr.Uid( middle ) )
+ {
+ bottom = middle + 1;
+ }
+ else
+ {
+ return middle;
+ }
+ }
+ return KErrNotFound;
+ }
+
+/**
+Find a value from the patchable data. If that fails try Publish&Subscribe,
+or if that fails, from Central Repository.
+
+@internalComponent
+@param aPCKey identifies the value to get from P&S.
+@param aCRKey identifies the value to get from Centrep
+@param aPatchableData patchable data set at compile time, may have been patched via rom patching
+@return Disk level threshold
+*/
+static TInt FindValueL(
+ const TUint aPCKey,
+ const TUint aCRKey,
+ const TInt aPatchableData )
+ {
+ TInt val( 0 );
+
+ if (aPatchableData != -1)
+ {
+ __SYSUTIL_TRACE1("SysUtil: CL treshold value found from patchable data %d",aPatchableData);
+ return aPatchableData;
+ }
+
+ // Patchable data not set, try to get it from P & S Keys.
+ TInt errorCode = RProperty::Get( KPSUidDiskLevel, aPCKey, val );
+ if ( errorCode != KErrNone )
+ {
+ __SYSUTIL_TRACE1("SysUtil: CL treshold value not found from PS: %d, trying CR",errorCode);
+
+ CRepository* repository = CRepository::NewLC(KCRUidDiskLevel);
+ User::LeaveIfError(repository->Get(aCRKey,val));
+ CleanupStack::PopAndDestroy( repository );
+ }
+
+ return val;
+ }
+
+/**
+Find out the critical level treashold (in bytes) for disk drives of type
+aMediaType. Different media types may have different tresholds. If adding
+a non-default treshold for some media type, implementation should go here.
+
+@internalComponent
+@param aMediaType identifies the media type of the drive
+@return Disk level threshold
+*/
+static TInt64 FindCriticalLevelTresholdL( const TMediaType aMediaType )
+ {
+ if ( aMediaType == EMediaRam ) // RAM drives have different critical level than others
+ {
+ return (TInt64) FindValueL(KRamDiskCriticalThreshold, KRamDiskCriticalLevel, KSysUtilRamDiskCriticalThreshold );
+ }
+ else // Some other media type
+ {
+ return (TInt64) FindValueL(KOtherDiskCriticalThreshold, KDiskCriticalThreshold, KSysUtilOtherDiskCriticalThreshold );
+ }
+ }
+
+/**
+Retrieves a string containing the location of sysutilplugin.dll. The location
+which is retrieved is dependent upon two things. The first is a patchable constant
+KSysUtilTestModeEnabled. This must be set to ETrue in order to use the test location instead
+of the standard path. This is set to EFalse by default for hardware builds.
+
+The second is a Publish and Subscribe property, which has a UID of
+0x10285B40. If KSysUtilTestModeEnabled is set to ETrue then this property will be defined
+and set to ETrue. This means that the test location is being used instead of the
+standard location. If the client wishes to switch to the standard location they
+can set this property to EFalse.
+
+It may be the case that the standard location needs to be used before the property
+is defined. If this is needed then the client can define and set the property.
+Alternatively, a call can be made to SysUtil::GetSWVersion,
+SysUtil::GetLangSWVersion, SysUtil::GetLangVersion or SysUtil::GetDeviceTypeInfoL.
+It can then call RProperty::Set with a value of EFalse.
+
+@param aLocation On return contains the location of sysutilplugin.dll.
+@leave - One of the system-wide error codes.
+@internalComponent
+*/
+static void GetDllLocationL( TDes& aLocation )
+ {
+ _LIT( KDeviceAttributeDll, "Z:\\sys\\bin\\sysutilplugin.dll" );
+
+ if( KSysUtilTestModeEnabled )
+ {
+ TBool testPaths = EFalse;
+ TInt err = RProperty::Get( KUidSystemCategory, KTestFilePathsUid.iUid, testPaths );
+ if( KErrNone != err )
+ testPaths = EFalse;
+
+ if( testPaths )
+ {
+ TDriveUnit systemDrive( static_cast<TUint>(RFs::GetSystemDrive()) );
+ TParse path;
+ path.Set( systemDrive.Name(), &KDeviceAttributeDll, NULL );
+
+ aLocation = path.FullName();
+ __SYSUTIL_TRACE1("DLL Location: %S", &aLocation);
+ return;
+ }
+ }
+
+ __SYSUTIL_TRACE1("DLL Location: %S", &KDeviceAttributeDll);
+ aLocation = KDeviceAttributeDll;
+ }
+
+/**
+Retrieves a string containing the path to deviceattributes.ini. The path which
+is retrieved is dependent upon two things. The first is a patchable constant
+KSysUtilTestModeEnabled. This must be set to ETrue in order to use the test path instead
+of the standard path. This is set to EFalse by default for hardware builds.
+
+The second is a Publish and Subscribe property, which has a UID of
+0x10285B40. If KSysUtilTestModeEnabled is set to ETrue then this property will be defined
+and set to ETrue. This means that the test path is being used instead of the
+standard path. If the client wishes to switch to the standard path they can set
+this property to EFalse.
+
+It may be the case that the standard path needs to be used before the property
+is defined. If this is needed then the client can define and set the property.
+Alternatively, a call can be made to SysUtil::GetSWVersion,
+SysUtil::GetLangSWVersion, SysUtil::GetLangVersion SysUtil::GetDeviceTypeInfoL or SysUtil::GetPRInformation.
+It can then call RProperty::Set with a value of EFalse.
+
+@param aPath On return contains the path to deviceattributes.ini.
+@return - One of the system-wide error codes.
+@internalComponent
+*/
+static TInt GetFilePath( TDes& aPath )
+ {
+ _LIT( KDebugPath, "Z:\\versions\\" );
+ _LIT( KPath, "Z:\\resource\\versions\\" );
+
+ if( KSysUtilTestModeEnabled )
+ {
+ TBool testPaths = EFalse;
+
+ TInt err = RProperty::Get( KUidSystemCategory, KTestFilePathsUid.iUid, testPaths );
+ if( KErrNone != err )
+ testPaths = EFalse;
+
+ if( testPaths )
+ {
+ TDriveUnit systemDrive( static_cast<TUint>(RFs::GetSystemDrive()) );
+ TParse path;
+ path.Set( systemDrive.Name(), &KDebugPath, NULL );
+
+ aPath = path.DriveAndPath();
+ __SYSUTIL_TRACE1("File Location: %S", &aPath);
+ return KErrNone;
+ }
+ }
+
+ __SYSUTIL_TRACE1("File Location: %S", &KPath);
+ aPath = KPath;
+ return KErrNone;
+ }
+
+/**
+Fetch text from specified files. The algorithm first reads the file and puts
+the string into a buffer. Then it searches for these "\n" sequences in
+the buffer. To search for "\n" in a string the search string is specified as "\\n"
+with the extra slash in front to mean that we are really searching for "\n" and not
+the newline character - 0x000A. Once the "\n" is found in the buffer it is replaced
+with the newline character - 0x000A. So since this input string is unicode, it is
+actually searching for the byte sequence of 0x005C, 0x006E. These 4 bytes are
+replaced by the two byte sequence of 0x000A.
+
+@internalComponent
+@param aFilename File name to fetch string from.
+@param aValue On return, contains the requested version string. If the buffer is
+insufficient the descriptor is filled to its maximum length. If a buffer is provided
+that is longer than 64 characters, and the file content is larger than 64 characters,
+the returned buffer is truncated at 64 characters (see error codes below).
+@param aRemoveNewLines Replaces new line patterns if set to ETrue
+@return KErrNone on success.
+ KErrTooBig if the maximum length of the descriptor is insufficient
+to hold the file content, or has been truncated (see above). In both cases new-line processing
+is done on the buffers if needed. If the file is empty KErrEof is returned, and the length of the
+buffer is set to zero. If none of these cases apply then one of the Symbian error codes is
+returned if reading the version string fails.
+*/
+static TInt GetTextFromFile(
+ const TDesC& aFilename,
+ TDes& aValue,
+ TBool aRemoveNewLines )
+ {
+ RFs fs;
+ TInt err;
+ err = fs.Connect();
+ if (err != KErrNone)
+ return err;
+
+ RFile file;
+ err = file.Open( fs, aFilename,
+ EFileRead | EFileStreamText | EFileShareReadersOnly );
+ if (err != KErrNone)
+ {
+ fs.Close();
+ return err;
+ }
+
+ TBuf8<2> characters;
+ err = file.Read(characters);
+
+ if (err == KErrNone || err == KErrTooBig)
+ {
+ // This means that we have an ANSI file (without the header bytes)
+ if( characters.Length() == 0 || characters.Length() == 1 )
+ {
+ file.Close();
+ fs.Close();
+ return KErrCorrupt;
+ }
+ else
+ {
+ TUint8 firstByte = characters[0];
+ TUint8 secondByte = characters[1];
+
+ // Heading byte values for unicode files
+ const TInt KFFByte = 255;
+ const TInt KFEByte = 254;
+
+ // If file isn't unicode KErrCorrupt is returned
+ if( (firstByte!=KFFByte && secondByte!=KFEByte) && (secondByte!=KFFByte && firstByte!=KFEByte) )
+ {
+ file.Close();
+ fs.Close();
+ return KErrCorrupt;
+ }
+ }
+ }
+
+ TFileText tf;
+ tf.Set(file);
+ err = tf.Read(aValue);
+ // If the maximum length of the descriptor is insufficient to hold the record,
+ // the Read() function returns KErrTooBig and the descriptor is filled to its maximum length.
+ //
+ // If Read() is called when the current position is the end of the file (that is, after
+ // the last line delimiter in the file), KErrEof is returned, and the length of the buffer
+ // is set to zero. In this case, this would mean an empty file, as this code always reads
+ // from the beginning of the file.
+
+ if (err == KErrNone || err == KErrTooBig)
+ {
+ if (aValue.Length() > KSysUtilVersionTextLength)
+ {
+ // File content is larger than 64 characters. Truncate to 64 characters.
+ aValue.Delete(KSysUtilVersionTextLength,aValue.Length() - KSysUtilVersionTextLength);
+ err = KErrTooBig;
+ }
+ if (aRemoveNewLines)
+ {
+ // Replace new-line patterns with real ones
+ TInt error = aValue.Find(KNewLinePattern);
+ while (error != KErrNotFound)
+ {
+ // error is a position
+ aValue.Replace(error, KNewLinePattern().Length(), KNewline );
+ error = aValue.Find(KNewLinePattern);
+ }
+ }
+ }
+
+ file.Close();
+ fs.Close();
+
+ return err;
+ }
+
+/**
+Launches sysutilsetup.exe which is a helper executable. It should be launched
+when the current client does not have the correct capabilities to define Publish
+and Subscribe properties.
+
+Flags are used to determine which Publish and Subscribe properties are defined
+and set. The supported flags can be found in sysutilsetup.h.
+
+@param aFlags Used to determine which Publish and Subscribe properties
+ should be defined and set. See sysutilsetup.h for
+ supported flags.
+@return KErrNotReady The excutable has panicked or was not found.
+@return - Otherwise, one of the other system-wide error codes.
+@internalComponent
+*/
+static TInt LaunchSetupExecutable( const TDesC& aFlags )
+ {
+ _LIT( KSysUtilSetupExeName, "Z:\\sys\\bin\\sysutilsetup.exe" );
+ const TUidType KSetupUid( KNullUid, KNullUid, KSysUtilSetupUid );
+
+ RProcess setupProcess;
+ TInt err = setupProcess.Create( KSysUtilSetupExeName, aFlags, KSetupUid );
+ if( KErrNone != err )
+ {
+ return KErrNotFound == err ? KErrNotReady : err;
+ }
+
+ TRequestStatus status;
+ setupProcess.Rendezvous( status );
+ if( KRequestPending != status.Int() )
+ {
+ setupProcess.Kill( 0 ); // Abort startup
+ }
+ else
+ {
+ setupProcess.Resume(); // Logon OK - start the server
+ }
+
+ User::WaitForRequest( status ); // Wait for start or death
+
+ // We can't use the 'exit reason' if the server panicked as this
+ // is the panic 'reason' and may be '0' which cannot be distinguished
+ // from KErrNone
+ err = setupProcess.ExitType() == EExitPanic ? KErrNotReady : status.Int();
+ setupProcess.Close();
+
+ return err;
+ }
+
+/**
+Retrieves a string containing the version information for the given UID.
+
+@param aVersionUid The UID that corresponds to the version information which is required.
+@param aValue On return, contains the version string for the given aVersionUid.
+@return - One of the system-wide error codes.
+@internalComponent
+*/
+static TInt GetVersionPropertyData( const TUid& aVersionUid, TDes& aValue )
+ {
+ // The P&S property contains the version data (max length 64) and the error code
+ TBuf16<KSysUtilVersionTextLength + 1> temp;
+ TInt16 err = RProperty::Get( KSysUtilSetupUid, aVersionUid.iUid, temp );
+
+ // If the P&S properties are not set we need to set them
+ if ( KErrNotFound == err )
+ {
+ __SYSUTIL_TRACE("Launching sysutilsetup.exe");
+ err = LaunchSetupExecutable( KSetVersionPropertiesFlag );
+ __SYSUTIL_TRACE("sysutilsetup.exe terminated");
+ if( KErrNone != err )
+ {
+ return err;
+ }
+
+ err = RProperty::Get( KSysUtilSetupUid, aVersionUid.iUid, temp );
+ if( KErrNone != err )
+ {
+ return err;
+ }
+ }
+
+ if( aValue.MaxLength() < temp.Length() - 1 )
+ {
+ aValue = temp.MidTPtr( 1, aValue.MaxLength() );
+ return KErrTooBig;
+ }
+ aValue = temp.MidTPtr( 1, temp.Length() - 1 );
+
+ return static_cast<TInt16>( temp[0] );
+ }
+
+/**
+Retrieves the version information from aFileName and stores it in a Publish and
+Subscribe property which has a key of aKey.
+
+@param aFileName The name of the file which contains the version information.
+@param aKey The key to be used for the Publish and Subscribe property.
+@leave - One of the system-wide error codes.
+@internalComponent
+*/
+static void SetVersionPropertyL( const TDesC& aFileName, const TUid& aKey )
+ {
+ TFileName filePath;
+ User::LeaveIfError( GetFilePath( filePath ) );
+ filePath.Append( aFileName );
+
+ // The P&S property must store the version data (max length 64) and the error code.
+ TUint16* versionData = static_cast<TUint16*>( User::AllocL( sizeof(TUint16) * (KSysUtilVersionTextLength + 1) ) );
+ CleanupDeletePushL( versionData );
+
+ // The error code is store in the first TUint16 and the rest is for data.
+ TPtr16 versionDataPtr( versionData + 1, KSysUtilVersionTextLength );
+ TInt err = GetTextFromFile( filePath, versionDataPtr, ETrue );
+ if ( err != KErrNone )
+ {
+ __SYSUTIL_TRACE2( "Error: %d, while processing: %S", err, &filePath );
+ }
+
+ // Store the error code from GetTextFromFile in the first TUint16.
+ versionData[0] = static_cast<TUint16>( err );
+
+ err = RProperty::Define( aKey.iUid, RProperty::EByteArray, KSecurityPolicyNone,
+ KSecurityPolicyWriteDeviceData, KSysUtilVersionTextLength + 1 );
+ if ( KErrAlreadyExists != err )
+ {
+ User::LeaveIfError( err );
+ }
+
+ versionDataPtr.Set( versionData, versionDataPtr.Length() + 1, versionDataPtr.Length() + 1 );
+ User::LeaveIfError( RProperty::Set( KSysUtilSetupUid, aKey.iUid, versionDataPtr ) );
+ CleanupStack::PopAndDestroy( 1 );
+ }
+
+/**
+Sets the version information Publish and Subscribe properties.
+
+@leave - One of the system-wide error codes.
+@internalComponent
+*/
+EXPORT_C void SetVersionPropertiesL()
+ {
+ SetVersionPropertyL( KSWVersionFileName, KSWVersionUid );
+ SetVersionPropertyL( KLangSWVersionFileName, KLangSWVersionUid );
+ SetVersionPropertyL( KLangVersionFileName, KLangVersionUid);
+ SetVersionPropertyL( KPRInformationFileName, KPRInformationUid );
+ }
+
+/**
+Compares two UIDs.
+
+@param aLeft The first of two UIDs to compare.
+@param aRight The second of two UIDs to compare.
+@return TInt Zero if both UIDs are the same. Positive if aLeft is greater
+ than aRight. Negative if aLeft is less than aRight.
+@leave - One of the system-wide error codes.
+@internalComponent
+*/
+static TInt CompareUids( const TInt32& aLeft, const TInt32& aRight )
+ {
+ TUint32 left = static_cast<TUint32>(aLeft);
+ TUint32 right = static_cast<TUint32>(aRight);
+ if( left == right )
+ {
+ return 0;
+ }
+ else if ( left < right )
+ {
+ return -1;
+ }
+ return 1;
+ }
+
+/**
+Finds the deviceattributes.ini file which best match the current locale. If more
+than one INI file is found for the current locale (this is a result of having
+different versions of the INI file in different ROFS sections) then the contents
+of the INI file are merged. If a attribute appears more than once then the most
+recent value is taken. On return akeys and aValues will contain the merged
+results.
+
+Note: The keys and values are in UID order from low to high.
+
+@param aKeys On return, contains the attribute UIDs.
+@param aValues On return, contains the attribute values.
+@leave KErrGeneral A UID in the INI file is missing the '0x' hex prefix.
+@leave - Otherwise, one of the other system-wide error codes.
+@internalComponent
+*/
+static void ReadDeviceAttribFilesAsArraysL(
+ RArray<TInt32>& aKeys,
+ CDesC16ArraySeg& aValues )
+ {
+ _LIT( KWildCardChar, "*" );
+
+ RFs fs;
+ fs.Connect();
+ CleanupClosePushL( fs );
+
+ // Get the localised version of deviceattributes.ini, if available, and use
+ // it to create a search pattern which will be used to find versions of the
+ // file that may be available in additional ROFS sections.
+ TFileName matchPattern;
+ User::LeaveIfError( GetFilePath( matchPattern ) );
+ matchPattern.Append( KDeviceAttributesFileName );
+ BaflUtils::NearestLanguageFile( fs, matchPattern );
+ matchPattern.Append( KWildCardChar );
+
+ // Get a list of all the versions of the localised deviceattributes.ini
+ // that may be available in additional ROFS sections. If an error occurs
+ // the default values will be used.
+ CDir* iniFileList = NULL;
+ TInt err = fs.GetDir( matchPattern, KEntryAttReadOnly | KEntryAttHidden |
+ KEntryAttSystem | KEntryAttArchive, ESortByName, iniFileList );
+
+ __SYSUTIL_TRACE1( "Error: %d, while getting a list of deviceattribute.ini files", err );
+
+ if( err == KErrNone )
+ {
+ CleanupStack::PushL( iniFileList );
+ // Go through each INI file (starting with the last file first) extracting
+ // the keys and values which are then stored in the two provided arrays.
+ // This keys and values are stored in key order from low to high. Only the
+ // most recent version of each value is stored i.e. the value in the INI
+ // file which is stored in the newest ROFS section.
+ TLinearOrder<TInt32> orderer( CompareUids );
+ for( TInt iniNumber = iniFileList->Count() - 1; iniNumber >= 0; iniNumber-- )
+ {
+ // Get next INI file
+ TFileName iniPath;
+ User::LeaveIfError( GetFilePath( iniPath ) );
+ iniPath.Append( (*iniFileList)[iniNumber].iName );
+
+ BSUL::CIniDocument16* iniFile = NULL;
+ TRAPD( err, iniFile = BSUL::CIniDocument16::NewL( fs, iniPath ) );
+ __SYSUTIL_TRACE1("BSUL::CIniDocument16::NewL error = %d", err);
+ if( err == KErrNone )
+ {
+ CleanupStack::PushL( iniFile );
+
+ RArray<TPtrC16> iniFileSections;
+ iniFile->GetSectionList( iniFileSections );
+ CleanupClosePushL( iniFileSections );
+
+ // For each section get the key/value pairs and insert in order to
+ // the provided arrays. If a key already exists do not insert the
+ // value in aValue.
+ TInt numIniFileSections = iniFileSections.Count();
+ for( TInt sectionNum = 0; sectionNum < numIniFileSections; sectionNum++ )
+ {
+ BSUL::CIniSecIter16* sectionIter = BSUL::CIniSecIter16::NewL( iniFileSections[sectionNum], iniFile );
+ CleanupStack::PushL( sectionIter );
+
+ TPtrC16 key;
+ TPtrC16 value;
+ while( sectionIter->Next( key, value ) )
+ {
+ const TChar char0('0');
+ const TChar charX('x');
+
+ TUint32 tempUid;
+ TLex16 lex( key );
+
+ // Skip over the '0' and 'x' hex number prefix
+ if( lex.Get() != char0 || lex.Get() != charX )
+ {
+ User::Leave(KErrGeneral);
+ }
+ User::LeaveIfError( lex.Val( tempUid, EHex ) );
+
+ TInt err = aKeys.InsertInOrder( static_cast<TInt32>(tempUid), orderer );
+ if( KErrAlreadyExists != err )
+ {
+ User::LeaveIfError( err );
+
+ TInt index = aKeys.FindInOrder( static_cast<TInt32>(tempUid), orderer );
+ aValues.InsertL( index, value );
+ }
+ }
+ CleanupStack::PopAndDestroy( 1 ); // sectionIter
+ }
+ CleanupStack::PopAndDestroy( 2 ); // iniFile and iniFileSections
+ }
+ }
+ CleanupStack::PopAndDestroy( 1 ); // iniFileList
+ }
+ CleanupStack::PopAndDestroy( 1 ); // fs
+ }
+
+/**
+Retrieves the provisioned device type information attribute key/value pairs
+which are stored in aKeys and aValues.
+
+Note: The keys and values are in UID order from low to high.
+
+@param aKeys On return, contains the attribute UIDs.
+@param aValues On return, contains the attribute values.
+@leave KErrCorrupt There is a mismatch between the number of keys and values or
+ an invalid key has been provided.
+@leave - Otherwise, one of the other system-wide error codes.
+@panic KErrTooBig More than 450 attributes where provisioned.
+@internalComponent
+*/
+static void GetDeviceAttributesL( RArray<TInt32>& aKeys, CDesC16ArraySeg& aValues )
+ {
+ RArray<TInt32> iniKeys;
+ CleanupClosePushL( iniKeys );
+
+ CDesC16ArraySeg* iniValues = new (ELeave) CDesC16ArraySeg( 8 );
+ CleanupStack::PushL( iniValues );
+
+ // First try to get the device type information attributes from the INI file/s.
+ ReadDeviceAttribFilesAsArraysL( iniKeys, *iniValues );
+
+ if( !KSysUtilDisableDeviceTypeInfoSetupExe )
+ {
+ // Now try to get the device type information attributes from a DLL.
+ TFileName deviceAttributeDllLocation;
+ GetDllLocationL(deviceAttributeDllLocation);
+
+ RLibrary deviceAttributeDll;
+ TInt err = deviceAttributeDll.Load( deviceAttributeDllLocation );
+ CleanupClosePushL( deviceAttributeDll );
+
+ if( KErrNone == err )
+ {
+ SysUtilPlugin::GetDeviceAttributesAsArraysFuncL GetDeviceAttributesAsArraysL = reinterpret_cast<SysUtilPlugin::GetDeviceAttributesAsArraysFuncL>( deviceAttributeDll.Lookup( SysUtilPlugin::EGetDeviceAttributesAsArraysLOrdinal ) );
+ User::LeaveIfNull( &GetDeviceAttributesAsArraysL );
+ GetDeviceAttributesAsArraysL( aKeys, aValues );
+ }
+ else
+ {
+ __SYSUTIL_TRACE1("Could not load sysutilplug.dll with error: %d ", err);
+ }
+ CleanupStack::PopAndDestroy( 1 );
+ }
+
+ // Merge results with the INI taking lowest priority i.e. if the value already
+ // exists in aKeys/aValues then ignore the one in iniKeys/iniValues.
+ TLinearOrder<TInt32> orderer( CompareUids );
+ TInt numIniAttribs = iniKeys.Count();
+ for( TInt keyNum = 0; keyNum < numIniAttribs; keyNum++ )
+ {
+ TInt err = aKeys.InsertInOrder( iniKeys[keyNum], orderer );
+ if( KErrAlreadyExists != err )
+ {
+ User::LeaveIfError( err );
+
+ TInt index = aKeys.FindInOrder( iniKeys[keyNum], orderer );
+ aValues.InsertL( index, (*iniValues)[keyNum] );
+ }
+ }
+ CleanupStack::PopAndDestroy( 2 );
+
+ // Check we have the same number of keys and values and that we don't have too many keys
+ if( aKeys.Count() != aValues.Count() )
+ {
+ User::Leave( KErrCorrupt );
+ }
+ else if( aKeys.Count() > KAttributeLimit )
+ {
+ _LIT( KPanicReason, "KAttributeLimit exceeded" );
+ User::Panic( KPanicReason, KErrTooBig );
+ }
+ }
+
+/**
+Validates major and minor version numbers. This means both values must be
+within the range 0 to KMaxTUint16. If the major, minor or both numbers are
+invalid their values will be replaced by KNullDesC16.
+
+@param aKeys An array which contains a list of device type information attribute
+ UIDs. The UIDs corrospond to the values in aValues.
+@param aValues An array which contains a list of device type information attribute
+ values. The values corrospond to the UIDs in aKeys.
+@internalComponent
+*/
+static void ValidateVersionNumbersL( RArray<TInt32>& aKeys, CDesC16ArraySeg& aValues, const TUid& aMajorVersionUid, const TUid& aMinorVersionUid)
+ {
+ TLinearOrder<TInt32> orderer( CompareUids );
+ TInt pos = aKeys.FindInOrder( aMajorVersionUid.iUid, orderer );
+ if( KErrNotFound != pos )
+ {
+ if( aKeys[pos + 1] == aMinorVersionUid.iUid )
+ {
+ TInt32 value;
+ TLex16 lex( aValues[pos] );
+ TInt err = lex.Val( value );
+
+ if( KErrNone == err && value >= 0 && value <= KMaxTUint16 )
+ {
+ lex = aValues[pos+ 1];
+ err = lex.Val( value );
+
+ if( KErrNone == err && value >= 0 && value <= KMaxTUint16 )
+ {
+ return;
+ }
+ }
+ aValues.Delete( pos + 1 );
+ aValues.InsertL( pos + 1, KNullDesC16 );
+ }
+ aValues.Delete( pos );
+ aValues.InsertL( pos, KNullDesC16 );
+ return;
+ }
+
+ pos = aKeys.FindInOrder( aMinorVersionUid.iUid, orderer );
+ if( KErrNotFound != pos )
+ {
+ aValues.Delete( pos );
+ aValues.InsertL( pos, KNullDesC16 );
+ }
+ }
+
+/**
+Gets the device type information attributes and stores them in their formatted form.
+
+@return TUint16* Formatted device type information attributes.
+@internalComponent
+*/
+static TUint16* FormattedDeviceTypeInfoL()
+ {
+ RArray<TInt32> keys;
+ CleanupClosePushL( keys );
+
+ CDesC16ArraySeg* values = new (ELeave) CDesC16ArraySeg( 8 );
+ CleanupStack::PushL( values );
+
+ GetDeviceAttributesL( keys, *values );
+
+ // Validate the major and minor UI and OS version numbers. This should be done now to avoid repeated processing
+ // later on when the client calls either of the GetUIPlatformVersion APIs. An added advantage of doing
+ // this now is that we save memory space if the version numbers are corrupt.
+ ValidateVersionNumbersL( keys, *values, KUIPlatformVersionMajorUid, KUIPlatformVersionMinorUid );
+ ValidateVersionNumbersL( keys, *values, KOSVersionMajorUid, KOSVersionMinorUid );
+
+ TUint16* deviceAttributes = CreateDeviceTypeInfoPSDataL( keys, *values );
+
+ CleanupStack::PopAndDestroy( 2 );
+
+ return deviceAttributes;
+ }
+
+/**
+Sets the Device Type Information attributes Publish and Subscribe property
+value. If the property does not already exist it will define it. Otherwise, it
+will set the value again.
+
+@leave - One of the system-wide error codes.
+@internalComponent
+*/
+EXPORT_C void SetDeviceTypeInfoPropertyL()
+ {
+ TUint16* deviceAttributes = FormattedDeviceTypeInfoL();
+ CleanupStack::PushL( deviceAttributes );
+
+ // Set the Publish and Subscribe property
+ TPtrC16 deviceAttributesTPtrC( deviceAttributes, deviceAttributes[0] );
+ TInt propertyType = deviceAttributesTPtrC.Size() < 512 ? RProperty::EByteArray : RProperty::ELargeByteArray;
+
+ TInt err = RProperty::Define( KDeviceTypeInfoUid.iUid, propertyType, KSecurityPolicyNone,
+ KSecurityPolicyWriteDeviceData, deviceAttributesTPtrC.Size() );
+ if ( KErrAlreadyExists != err )
+ {
+ User::LeaveIfError( err );
+ }
+ User::LeaveIfError( RProperty::Set( KSysUtilSetupUid, KDeviceTypeInfoUid.iUid, deviceAttributesTPtrC ) );
+
+ CleanupStack::PopAndDestroy( 1 );
+ }
+
+// ========================= SysUtil MEMBER FUNCTIONS ==========================
+
+/**
+Obtains the displayable software version string.
+
+Usage example:
+@code
+TBuf<KSysUtilVersionTextLength> version;
+if ( SysUtil::GetSWVersion( version ) == KErrNone )
+ {
+ // Use the version string.
+ ...
+ }
+@endcode
+The software version is provisioned by the device creator into the ROM
+as a Unicode UTF16 format displayable string, for example:
+
+<code>V 1.0\\n29-07-07\\nBuild12345\\n(c) Symbian Software</code>
+
+This provisioned text string contains only one line of text with "\n" sequences
+in the text which indicate a new line. This API will parse the
+text and remove any "\n" sequences that it finds and replace it with the
+Unicode newline sequence - 0x000A. The resulting
+buffer is then a unicode string with newline sequences built in. This
+then can for example, allow the buffer to be displayed directly to the
+screen already formatted on multiple lines.
+
+@param aValue On return, contains the software version string. The buffer should
+have space for KSysUtilVersionTextLength characters. If the buffer is
+insufficient the descriptor is filled to its maximum length. If a buffer is
+provided that is longer than 64 characters, and the provisioned text is larger
+than 64 characters, the returned buffer is truncated at 64 characters (see error
+codes below).
+@return KErrNone on success, KErrTooBig if the maximum length of the descriptor
+is insufficient to hold the provisioned text, or has been truncated (see above).
+In both cases new-line processing is done on the buffers. If a zero length
+text string has been provisioned KErrEof is returned, and the length of the
+buffer is set to zero. If none of these cases apply then one of the Symbian
+error codes is returned if reading the version string fails.
+*/
+EXPORT_C TInt SysUtil::GetSWVersion( TDes& aValue )
+ {
+ if( KSysUtilDisableVersionSetupExe )
+ {
+ __SYSUTIL_TRACE("GetSWVersion caching disabled");
+
+ TFileName filePath;
+ TInt err = GetFilePath( filePath );
+ if( KErrNone != err)
+ {
+ return err;
+ }
+
+ filePath.Append( KSWVersionFileName );
+
+ err = GetTextFromFile( filePath, aValue, ETrue );
+ if ( err != KErrNone )
+ {
+ __SYSUTIL_TRACE2("Error: %d, while processing: %S",err, &filePath);
+ }
+
+ return err;
+ }
+ else
+ {
+ __SYSUTIL_TRACE("GetSWVersion caching enabled");
+ return GetVersionPropertyData( KSWVersionUid, aValue );
+ }
+ }
+
+/**
+Returns displayable software version which the currently installed language
+package is compatible with.
+
+This version text is provisioned by the device creator into the ROM
+as a Unicode UTF16 format displayable string, for example:
+
+<code>V 1.0\\n29-07-07\\nBuild12345\\n(c) Symbian Software</code>
+
+This provisioned text string contains only one line of text with "\n" sequences
+in the text which indicate a new line. This API will parse the
+text and remove any "\n" sequences that it finds and replace it with the
+Unicode newline sequence - 0x000A. The resulting
+buffer is then a unicode string with newline sequences built in. This
+then can for example, allow the buffer to be displayed directly to the
+screen already formatted on multiple lines.
+
+@param aValue On return, contains the software version string. The buffer should
+have space for KSysUtilVersionTextLength characters. If the buffer is
+insufficient the descriptor is filled to its maximum length. If a buffer is
+provided that is longer than 64 characters, and the provisioned text is larger
+than 64 characters, the returned buffer is truncated at 64 characters (see error
+codes below).
+@return KErrNone on success, KErrTooBig if the maximum length of the descriptor
+is insufficient to hold the provisioned text, or has been truncated (see above).
+In both cases new-line processing is done on the buffers. If a zero length
+text string has been provisioned KErrEof is returned, and the length of the
+buffer is set to zero. If none of these cases apply then one of the Symbian
+error codes is returned if reading the version string fails.
+*/
+EXPORT_C TInt SysUtil::GetLangSWVersion( TDes& aValue )
+ {
+ if( KSysUtilDisableVersionSetupExe )
+ {
+ __SYSUTIL_TRACE("GetLangSWVersion caching disabled");
+
+ TFileName filePath;
+ TInt err = GetFilePath( filePath );
+ if( KErrNone != err)
+ {
+ return err;
+ }
+
+ filePath.Append( KLangSWVersionFileName );
+
+ err = GetTextFromFile( filePath, aValue, ETrue );
+ if ( err != KErrNone )
+ {
+ __SYSUTIL_TRACE2("Error: %d, while processing: %S",err, &filePath);
+ }
+
+ return err;
+ }
+ else
+ {
+ __SYSUTIL_TRACE("GetLangSWVersion caching enabled");
+ return GetVersionPropertyData( KLangSWVersionUid, aValue );
+ }
+ }
+
+/**
+Obtains the displayable version of the currently installed language package.
+This does NOT do any newline processing on the version text.
+(unlike, for example GetLangSWVersion() or GetSWVersion()).
+
+This version text is provisioned by the device creator into the ROM
+as a Unicode UTF16 format displayable string.
+
+@param aValue On return, contains the software version string. The buffer should
+have space for KSysUtilVersionTextLength characters. If the buffer is
+insufficient the descriptor is filled to its maximum length. If a buffer is
+provided that is longer than 64 characters, and the provisioned text is larger
+than 64 characters, the returned buffer is truncated at 64 characters (see error
+codes below).
+@return KErrNone on success, KErrTooBig if the maximum length of the descriptor
+is insufficient to hold the provisioned text, or has been truncated (see above).
+In both cases new-line processing is done on the buffers. If a zero length
+text string has been provisioned KErrEof is returned, and the length of the
+buffer is set to zero. If none of these cases apply then one of the Symbian
+error codes is returned if reading the version string fails.
+*/
+EXPORT_C TInt SysUtil::GetLangVersion( TDes& aValue )
+ {
+ if( KSysUtilDisableVersionSetupExe )
+ {
+ __SYSUTIL_TRACE("GetLangVersion caching disabled");
+
+ TFileName filePath;
+ TInt err = GetFilePath( filePath );
+ if( KErrNone != err)
+ {
+ return err;
+ }
+
+ filePath.Append( KLangVersionFileName );
+
+ err = GetTextFromFile( filePath, aValue, ETrue );
+ if ( err != KErrNone )
+ {
+ __SYSUTIL_TRACE2("Error: %d, while processing: %S",err, &filePath);
+ }
+
+ return err;
+ }
+ else
+ {
+ __SYSUTIL_TRACE("GetLangVersion caching enabled");
+ return GetVersionPropertyData( KLangVersionUid, aValue );
+ }
+ }
+
+/**
+Obtains the displayable product release information string.
+
+Usage example:
+@code
+TBuf<KSysUtilVersionTextLength> prInfo;
+if ( SysUtil::GetPRInformation( prInfo ) == KErrNone )
+ {
+ // Use the version string.
+ ...
+ }
+@endcode
+The product release information is provisioned by the device creator into the ROM
+as a Unicode UTF16 format displayable string, for example:
+
+<code>custom build\n20090626\nusb fix xyz</code>
+or
+<code>PR1.0</code>
+or
+<code>PR1.1</code>
+
+This provisioned text string contains only one line of text with "\n" sequences
+in the text which indicate a new line. This API will parse the
+text and remove any "\n" sequences that it finds and replace it with the
+Unicode newline sequence - 0x000A. The resulting
+buffer is then a unicode string with newline sequences built in. This
+then can for example, allow the buffer to be displayed directly to the
+screen already formatted on multiple lines.
+
+@param aValue On return, contains the product release information string. The buffer should
+have space for KSysUtilVersionTextLength characters. If the buffer is
+insufficient the descriptor is filled to its maximum length. If a buffer is
+provided that is longer than 64 characters, and the provisioned text is larger
+than 64 characters, the returned buffer is truncated at 64 characters.
+@return KErrNone on success, KErrTooBig if the maximum length of the descriptor
+is insufficient to hold the provisioned text, or has been truncated.
+In both cases new-line processing is done on the buffers. If a zero length
+text string has been provisioned KErrEof is returned, and the length of the
+buffer is set to zero. If none of these cases apply then one of the Symbian
+error codes is returned if reading the product release string fails.
+*/
+EXPORT_C TInt SysUtil::GetPRInformation( TDes& aValue )
+ {
+ TInt err = KErrNone;
+ if( KSysUtilDisableVersionSetupExe )
+ {
+ __SYSUTIL_TRACE("GetPRInformation caching disabled");
+ TFileName filePath;
+ GetFilePath( filePath );
+ filePath.Append( KPRInformationFileName );
+ err = GetTextFromFile( filePath, aValue, ETrue );
+ if ( err != KErrNone )
+ {
+ __SYSUTIL_TRACE2("Error: %d, while processing: %S",err, &filePath);
+ }
+ }
+ else
+ {
+ __SYSUTIL_TRACE("GetPRInformation caching enabled");
+ err = GetVersionPropertyData( KPRInformationUid, aValue );
+ }
+ return err;
+ }
+
+/**
+Checks if free system drive storage space is or will fall below critical level.
+The system drive (internal, read/write, persistent drive) is also known
+as the FFS (internal flash file system).
+
+To calculate if a critical level has been reached the critical level threshold
+setting will be used. This setting is available in the patchable data.
+
+RAM drives and non-RAM drives have different threshold levels, so the corresponding
+setting will be used for the calculation depending on the drive type.
+
+RAM drives are defined to be drives that have the media type of EMediaRam
+as returned by RFs. @see RFs::Drive
+
+To set the patchdata for the RAM drive threshold set the MACRO
+SYMBIAN_BAFL_SYSUTIL_RAM_DRIVE_CRITICAL_THRESHOLD at ROM build time to an
+appropriate level. To set the patchdata for the non-RAM drive threshold
+set the MACRO SYMBIAN_BAFL_SYSUTIL_OTHER_DISK_CRITICAL_THRESHOLD at ROM
+build time to an appropriate level.
+
+This method also needs to determine which drive is the FFS drive. To do
+this patchable data has been provided. If the patchable data has not been
+set, then RFs::GetSystemDrive() will be used to determine the FFS drive.
+
+To set the patchdata to the FFS drive set the MACRO
+SYMBIAN_BAFL_SYSUTIL_DEFAULT_FFS_DRIVE to the appropriate drive letter.
+@see TDriveNumber
+
+This function exists here to maintain binary compatibility .
+@see SysUtil::FFSSpaceBelowCriticalLevelL
+
+@param aFs File server session. Must be given if available, e.g. from
+EIKON environment. If NULL, this method will create a temporary session,
+which causes the method to consume more time and system resources.
+@param aBytesToWrite Number of bytes the caller is about to write to the
+system drive. If value 0 is given, this method checks if the current system
+drive space is already below critical level.
+@return ETrue if system drive space would go below critical level after writing
+aBytesToWrite more data, EFalse otherwise.
+@leave System wide error codes
+*/
+EXPORT_C TBool SysUtil::FFSSpaceBelowCriticalLevel_OldL(
+ RFs* aFs,
+ TInt aBytesToWrite )
+ {
+ __SYSUTIL_TRACE("SysUtil::FFSSpaceBelowCriticalLevel_OldL");
+ TBool retVal( EFalse );
+
+ RFs fs;
+ if ( !aFs )
+ {
+ User::LeaveIfError( fs.Connect() ); // Create temp session.
+ CleanupClosePushL( fs );
+ }
+ else
+ {
+ if( aFs->Handle() == KNullHandle )
+ {
+ User::Panic(_L("BAFL"), EBafPanicRFsConnectArg );
+ }
+ fs = *aFs;
+ }
+
+ TInt ffsDrive = GetFFSDriveLetter( fs );
+ retVal = DiskSpaceBelowCriticalLevel_OldL(&fs, aBytesToWrite, ffsDrive );
+
+ if ( !aFs )
+ {
+ CleanupStack::PopAndDestroy(); // Close temp session
+ }
+
+ return retVal;
+ }
+
+/**
+Checks if free disk drive storage space is or will fall below critical
+level.
+
+To calculate if a critical level has been reached the critical level threshold
+setting will be used. This setting is available in the patchable data.
+
+RAM drives and non-RAM drives have different threshold levels, so the corresponding
+setting will be used for the calculation depending on the drive type.
+
+RAM drives are defined to be drives that have the media type of EMediaRam
+as returned by RFs. @see RFs::Drive
+
+To set the patchdata for the RAM drive threshold set the MACRO
+SYMBIAN_BAFL_SYSUTIL_RAM_DRIVE_CRITICAL_THRESHOLD at ROM build time to an
+appropriate level. To set the patchdata for the non-RAM drive threshold
+set the MACRO SYMBIAN_BAFL_SYSUTIL_OTHER_DISK_CRITICAL_THRESHOLD at ROM
+build time to an appropriate level.
+
+This function exists here to maintain binary compatibility .
+@see SysUtil::DiskSpaceBelowCriticalLevelL
+
+@param aFs File server session. Must be given if available, e.g. from
+EIKON environment. If NULL, this method will create a temporary session,
+which causes the method to consume more time and system resources.
+@param aBytesToWrite Number of bytes the caller is about to write to
+disk. If value 0 is given, this method checks if the current disk space
+is already below critical level.
+@param aDrive Identifies the disk drive to be checked. Numeric values
+for identifying disk drives are defined in TDriveNumber enumeration.
+@see TDriveNumber in f32file.h.
+@return ETrue if disk space would go below critical level after writing
+aBytesToWrite more data, EFalse otherwise.
+@leave System wide error codes
+*/
+EXPORT_C TBool SysUtil::DiskSpaceBelowCriticalLevel_OldL(
+ RFs* aFs,
+ TInt aBytesToWrite,
+ TInt aDrive )
+ {
+ __SYSUTIL_TRACE1("SysUtil::DiskSpaceBelowCriticalLevel_OldL( %d )",aDrive);
+
+ RFs fs;
+ if ( !aFs )
+ {
+ User::LeaveIfError( fs.Connect() ); // Create temp session.
+ CleanupClosePushL( fs );
+ }
+ else
+ {
+ if( aFs->Handle() == KNullHandle )
+ {
+ User::Panic(_L("BAFL"), EBafPanicRFsConnectArg );
+ }
+ fs = *aFs;
+ }
+
+ TVolumeInfo vinfo;
+ // This may leave e.g. KErrNotReady if no drive
+ TInt errorCode = fs.Volume( vinfo, aDrive );
+
+ if ( !aFs )
+ {
+ CleanupStack::PopAndDestroy(); // Close temp session
+ }
+
+ __SYSUTIL_TRACE1("SysUtil::DiskSpaceBelowCriticalLevel_OldL RFs::Volume returned error code %d.",errorCode);
+ User::LeaveIfError( errorCode );
+
+ const TInt64 criticalLevel = FindCriticalLevelTresholdL( vinfo.iDrive.iType );
+ __SYSUTIL_TRACE3("SysUtil: CL treshold value: %Ld, Free: %Ld, Size: %Ld",criticalLevel,vinfo.iFree,vinfo.iSize);
+
+ return ( vinfo.iFree - (TInt64)aBytesToWrite ) <= criticalLevel;
+ }
+
+/**
+Checks if free MMC storage space is or will fall below critical
+level.
+
+To calculate if a critical level has been reached the critical level threshold
+setting will be used. This setting is available in the patchable data.
+
+RAM drives and non-RAM drives have different threshold levels, so the corresponding
+setting will be used for the calculation depending on the drive type.
+
+RAM drives are defined to be drives that have the media type of EMediaRam
+as returned by RFs. @see RFs::Drive
+
+This method also needs to determine which drive is the MMC drive. To do
+this a patchable data has been provided. If the patchable data
+has not been set, then the drive will be fetched using BSUL.
+@see CCachedDriveInfo
+
+To set the patchdata for the RAM drive threshold set the MACRO
+SYMBIAN_BAFL_SYSUTIL_RAM_DRIVE_CRITICAL_THRESHOLD at ROM build time to an
+appropriate level. To set the patchdata for the non-RAM drive threshold
+set the MACRO SYMBIAN_BAFL_SYSUTIL_OTHER_DISK_CRITICAL_THRESHOLD at ROM
+build time to an appropriate level.
+
+To set the patchdata to the MMC drive set the MACRO
+SYMBIAN_BAFL_SYSUTIL_DEFAULT_MMC_DRIVE to the appropriate drive letter.
+@see TDriveNumber
+
+This function exists here to maintain binary compatibility .
+@see SysUtil::MMCSpaceBelowCriticalLevelL
+
+@param aFs File server session. Must be given if available, e.g. from
+EIKON environment. If NULL, this method will create a temporary session,
+which causes the method to consume more time and system resources.
+@param aBytesToWrite Number of bytes the caller is about to write to
+MMC. If value 0 is given, this method checks if the current MMC space
+is already below critical level.
+@return ETrue if MMC space would go below critical level after writing
+aBytesToWrite more data, EFalse otherwise.
+@leave KErrNotFound if the MMC drive cannot be found, otherwise one of the
+system-wide error codes.
+*/
+EXPORT_C TBool SysUtil::MMCSpaceBelowCriticalLevel_OldL(RFs* aFs, TInt aBytesToWrite)
+ {
+ __SYSUTIL_TRACE("SysUtil::MMCSpaceBelowCriticalLevel_OldL");
+ TBool retVal(EFalse);
+
+ RFs fs;
+ if ( !aFs )
+ {
+ User::LeaveIfError( fs.Connect() ); // Create temp session.
+ CleanupClosePushL( fs );
+ }
+ else
+ {
+ if( aFs->Handle() == KNullHandle )
+ {
+ User::Panic(_L("BAFL"), EBafPanicRFsConnectArg );
+ }
+ fs = *aFs;
+ }
+
+ TInt mmcDrive = GetMMCDriveLetter( fs );
+ retVal = DiskSpaceBelowCriticalLevel_OldL(&fs, aBytesToWrite, mmcDrive );
+
+ if ( !aFs )
+ {
+ CleanupStack::PopAndDestroy(); // Close temp session
+ }
+
+ return retVal;
+ }
+
+/**
+Checks if free system drive storage space is or will fall below critical level.
+The system drive (internal, read/write, persistent drive) is also known
+as the FFS (internal flash file system).
+
+To calculate if a critical level has been reached the critical level threshold
+setting will be used. This setting is available in the patchable data.
+
+RAM drives and non-RAM drives have different threshold levels, so the corresponding
+setting will be used for the calculation depending on the drive type.
+
+RAM drives are defined to be drives that have the media type of EMediaRam
+as returned by RFs. @see RFs::Drive
+
+To set the patchdata for the RAM drive threshold set the MACRO
+SYMBIAN_BAFL_SYSUTIL_RAM_DRIVE_CRITICAL_THRESHOLD at ROM build time to an
+appropriate level. To set the patchdata for the non-RAM drive threshold
+set the MACRO SYMBIAN_BAFL_SYSUTIL_OTHER_DISK_CRITICAL_THRESHOLD at ROM
+build time to an appropriate level.
+
+This method also needs to determine which drive is the FFS drive. To do
+this patchable data has been provided. If the patchable data has not been
+set, then RFs::GetSystemDrive() will be used to determine the FFS drive.
+
+To set the patchdata to the FFS drive set the MACRO
+SYMBIAN_BAFL_SYSUTIL_DEFAULT_FFS_DRIVE to the appropriate drive letter.
+@see TDriveNumber
+
+@param aFs File server session. Must be given if available, e.g. from
+EIKON environment. If NULL, this method will create a temporary session,
+which causes the method to consume more time and system resources.
+@param aBytesToWrite Number of bytes the caller is about to write to the
+system drive. If value 0 is given, this method checks if the current system
+drive space is already below critical level.
+@return ETrue if system drive space would go below critical level after writing
+aBytesToWrite more data, EFalse otherwise.
+@leave System wide error codes
+*/
+
+EXPORT_C TBool SysUtil::FFSSpaceBelowCriticalLevelL(
+ RFs* aFs,
+ TInt64 aBytesToWrite )
+ {
+ __SYSUTIL_TRACE("SysUtil::FFSSpaceBelowCriticalLevelL");
+ TBool retVal( EFalse );
+
+ RFs fs;
+ if ( !aFs )
+ {
+ User::LeaveIfError( fs.Connect() ); // Create temp session.
+ CleanupClosePushL( fs );
+ }
+ else
+ {
+ if( aFs->Handle() == KNullHandle )
+ {
+ User::Panic(_L("BAFL"), EBafPanicRFsConnectArg );
+ }
+ fs = *aFs;
+ }
+
+ TInt ffsDrive = GetFFSDriveLetter( fs );
+ retVal = DiskSpaceBelowCriticalLevelL(&fs, aBytesToWrite, ffsDrive );
+
+ if ( !aFs )
+ {
+ CleanupStack::PopAndDestroy(); // Close temp session
+ }
+
+ return retVal;
+ }
+
+/**
+Checks if free disk drive storage space is or will fall below critical
+level.
+
+To calculate if a critical level has been reached the critical level threshold
+setting will be used. This setting is available in the patchable data.
+
+RAM drives and non-RAM drives have different threshold levels, so the corresponding
+setting will be used for the calculation depending on the drive type.
+
+RAM drives are defined to be drives that have the media type of EMediaRam
+as returned by RFs. @see RFs::Drive
+
+To set the patchdata for the RAM drive threshold set the MACRO
+SYMBIAN_BAFL_SYSUTIL_RAM_DRIVE_CRITICAL_THRESHOLD at ROM build time to an
+appropriate level. To set the patchdata for the non-RAM drive threshold
+set the MACRO SYMBIAN_BAFL_SYSUTIL_OTHER_DISK_CRITICAL_THRESHOLD at ROM
+build time to an appropriate level.
+
+Usage example:
+@code
+TInt64 dataSize = 500000000;
+if ( SysUtil::DiskSpaceBelowCriticalLevelL( &iFsSession, dataSize, EDriveC ) )
+ {
+ // Can not write the data, there's not enough free space on disk.
+ ...
+ }
+else
+ {
+ // It's ok to actually write the data.
+ ...
+ }
+@endcode
+@param aFs File server session. Must be given if available, e.g. from
+EIKON environment. If NULL, this method will create a temporary session,
+which causes the method to consume more time and system resources.
+@param aBytesToWrite Number of bytes the caller is about to write to
+disk. If value 0 is given, this method checks if the current disk space
+is already below critical level.
+@param aDrive Identifies the disk drive to be checked. Numeric values
+for identifying disk drives are defined in TDriveNumber enumeration.
+@see TDriveNumber in f32file.h.
+@return ETrue if disk space would go below critical level after writing
+aBytesToWrite more data, EFalse otherwise.
+@leave System wide error codes
+*/
+
+EXPORT_C TBool SysUtil::DiskSpaceBelowCriticalLevelL(
+ RFs* aFs,
+ TInt64 aBytesToWrite,
+ TInt aDrive )
+ {
+ __SYSUTIL_TRACE1("SysUtil::DiskSpaceBelowCriticalLevelL( %d )",aDrive);
+
+ RFs fs;
+ if ( !aFs )
+ {
+ User::LeaveIfError( fs.Connect() ); // Create temp session.
+ CleanupClosePushL( fs );
+ }
+ else
+ {
+ if( aFs->Handle() == KNullHandle )
+ {
+ User::Panic(_L("BAFL"), EBafPanicRFsConnectArg );
+ }
+ fs = *aFs;
+ }
+
+ TVolumeInfo vinfo;
+ // This may leave e.g. KErrNotReady if no drive
+ TInt errorCode = fs.Volume( vinfo, aDrive );
+
+ if ( !aFs )
+ {
+ CleanupStack::PopAndDestroy(); // Close temp session
+ }
+
+ __SYSUTIL_TRACE1("SysUtil::DiskSpaceBelowCriticalLevelL RFs::Volume returned error code %d.",errorCode);
+ User::LeaveIfError( errorCode );
+
+ const TInt64 criticalLevel = FindCriticalLevelTresholdL( vinfo.iDrive.iType );
+ __SYSUTIL_TRACE3("SysUtil: CL treshold value: %Ld, Free: %Ld, Size: %Ld",criticalLevel,vinfo.iFree,vinfo.iSize);
+
+ return ( vinfo.iFree - aBytesToWrite ) <= criticalLevel;
+ }
+
+/**
+Checks if free MMC storage space is or will fall below critical
+level.
+
+To calculate if a critical level has been reached the critical level threshold
+setting will be used. This setting is available in the patchable data.
+
+RAM drives and non-RAM drives have different threshold levels, so the corresponding
+setting will be used for the calculation depending on the drive type.
+
+RAM drives are defined to be drives that have the media type of EMediaRam
+as returned by RFs. @see RFs::Drive
+
+This method also needs to determine which drive is the MMC drive. To do
+this a patchable data has been provided. If the patchable data
+has not been set, then the drive will be fetched using BSUL.
+@see CCachedDriveInfo
+
+To set the patchdata for the RAM drive threshold set the MACRO
+SYMBIAN_BAFL_SYSUTIL_RAM_DRIVE_CRITICAL_THRESHOLD at ROM build time to an
+appropriate level. To set the patchdata for the non-RAM drive threshold
+set the MACRO SYMBIAN_BAFL_SYSUTIL_OTHER_DISK_CRITICAL_THRESHOLD at ROM
+build time to an appropriate level.
+
+To set the patchdata to the MMC drive set the MACRO
+SYMBIAN_BAFL_SYSUTIL_DEFAULT_MMC_DRIVE to the appropriate drive letter.
+@see TDriveNumber
+
+@param aFs File server session. Must be given if available, e.g. from
+EIKON environment. If NULL, this method will create a temporary session,
+which causes the method to consume more time and system resources.
+@param aBytesToWrite Number of bytes the caller is about to write to
+MMC. If value 0 is given, this method checks if the current MMC space
+is already below critical level.
+@return ETrue if MMC space would go below critical level after writing
+aBytesToWrite more data, EFalse otherwise.
+@leave KErrNotFound if the MMC drive cannot be found, otherwise one of the
+system-wide error codes.
+*/
+EXPORT_C TBool SysUtil::MMCSpaceBelowCriticalLevelL(RFs* aFs, TInt64 aBytesToWrite)
+ {
+ __SYSUTIL_TRACE("SysUtil::MMCSpaceBelowCriticalLevelL");
+ TBool retVal(EFalse);
+
+ RFs fs;
+ if ( !aFs )
+ {
+ User::LeaveIfError( fs.Connect() ); // Create temp session.
+ CleanupClosePushL( fs );
+ }
+ else
+ {
+ if( aFs->Handle() == KNullHandle )
+ {
+ User::Panic(_L("BAFL"), EBafPanicRFsConnectArg );
+ }
+ fs = *aFs;
+ }
+
+ TInt mmcDrive = GetMMCDriveLetter( fs );
+ retVal = DiskSpaceBelowCriticalLevelL(&fs, aBytesToWrite, mmcDrive );
+
+ if ( !aFs )
+ {
+ CleanupStack::PopAndDestroy(); // Close temp session
+ }
+
+ return retVal;
+ }
+
+
+/**
+Returns the FFS drive letter
+
+This method determines which drive is the FFS drive. To do
+this a patchable data has been provided. If the patchable data
+has not been set, then the drive will be fetched via a call to
+GetSystemDrive().
+
+To set the patchdata to the FFS drive set the MACRO
+SYMBIAN_BAFL_SYSUTIL_DEFAULT_FFS_DRIVE to the appropriate drive letter.
+@see TDriveNumber
+
+@return TInt the integer value equivalent of the TDriveNumber
+*/
+EXPORT_C TInt SysUtil::GetFFSDriveLetter( RFs & aFs )
+ {
+ // Check the argument, and panic if necessary
+ if( aFs.Handle() == KNullHandle )
+ {
+ User::Panic(_L("KERN-EXEC"), 0);
+ }
+
+ // Check to see if FFS drive is set in patchable data
+ TInt ffsDrive = KSysUtilDefaultFFSDrive;
+ if( !(ffsDrive >= EDriveA && ffsDrive <= EDriveZ) )
+ {
+ ffsDrive = aFs.GetSystemDrive();
+ }
+
+ return ffsDrive;
+ }
+
+/**
+Returns the MMC drive letter
+
+This method determines which drive is the MMC drive. To do
+this a patchable data has been provided.
+
+To set the patchdata to the MMC drive set the MACRO
+SYMBIAN_BAFL_SYSUTIL_DEFAULT_MMC_DRIVE to the appropriate drive letter.
+@see TDriveNumber
+
+@return TInt the integer value equivalent of the TDriveNumber
+*/
+
+EXPORT_C TInt SysUtil::GetMMCDriveLetter( RFs & aFs )
+ {
+ // Check the argument, and panic if necessary
+ if( aFs.Handle() == KNullHandle )
+ {
+ User::Panic(_L("KERN-EXEC"), 0);
+ }
+
+ // Check to see if MMC drive is set in patchable data
+ TInt mmcDrive = KSysUtilDefaultMMCDrive;
+
+ // If a valid mmcDrive is not currently found in patchable data, then search for one.
+ if( !(mmcDrive >= EDriveA && mmcDrive <= EDriveZ) )
+ {
+ __SYSUTIL_TRACE("SysUtil::MMCSpaceBelowCriticalLevelL - searching for MMC drive");
+ // If mmcDrive is not set in patchable data, then fetch the MMC drive from BSUL.
+ BSUL::CCachedDriveInfo *cachedDriveInfo = BSUL::CCachedDriveInfo::NewLC( aFs );
+ // This will find valid MMC drive, leave if none available
+ mmcDrive = cachedDriveInfo->GetDefaultRemovableMemoryCardDriveL();
+ __SYSUTIL_TRACE1("SysUtil::MMCSpaceBelowCriticalLevelL, Selected MMC drive %d.",mmcDrive);
+ CleanupStack::PopAndDestroy(cachedDriveInfo);
+ }
+
+ return mmcDrive;
+ }
+
+/**
+Creates and returns a populated CDeviceTypeInformation object which is used
+to access the device type information attributes.
+
+All the attributes are provisioned by the device creator.
+
+The returned object is owned by the calling code and so it is the calling
+codes responsibility to delete this object when it no longer requires it.
+
+@return CDeviceTypeInformation* A pointer to an instance of CDeviceTypeInformation.
+@leave KErrNoMemory If there is not enough memory to create the object.
+@leave KErrNotReady If there was a problem retrieving the device type
+ information attributes.
+@leave - Otherwise one of the other system-wide error codes.
+@see CDeviceTypeInformation
+*/
+EXPORT_C CDeviceTypeInformation* SysUtil::GetDeviceTypeInfoL()
+ {
+ __SYSUTIL_TRACE("SysUtil::GetDeviceTypeInfoL");
+ return CDeviceTypeInformation::NewL();
+ }
+
+// ================= CDeviceTypeInformation MEMBER FUNCTIONS ===================
+
+/**
+Class destructor.
+
+Performs any clean up such as deleting memory on the heap.
+*/
+EXPORT_C CDeviceTypeInformation::~CDeviceTypeInformation()
+ {
+ SDeviceAttributes* attr = reinterpret_cast<SDeviceAttributes*>( iImpl );
+ if( attr != NULL )
+ {
+ delete attr->iDeviceAttributes;
+ delete attr;
+ }
+ }
+
+/**
+Allocates and constructs an instance of CDeviceTypeInformation.
+
+@return A pointer to an instance of CDeviceTypeInformation.
+@leave KErrNoMemory, if there is not enough memory to create the object.
+@leave - Otherwise one of the other system-wide error codes.
+*/
+CDeviceTypeInformation* CDeviceTypeInformation::NewL()
+ {
+ CDeviceTypeInformation* self = new (ELeave) CDeviceTypeInformation();
+ CleanupStack::PushL( self );
+ self->ConstructL();
+ CleanupStack::Pop( self );
+ return self;
+ }
+
+/**
+Class constructor.
+
+Performs any class construction tasks that will not cause a leave.
+*/
+CDeviceTypeInformation::CDeviceTypeInformation() : iImpl( NULL )
+ {
+ }
+
+/**
+Performs class creation tasks as part of two phase construction.
+
+Performs any class construction tasks that will cause a leave.
+*/
+void CDeviceTypeInformation::ConstructL()
+ {
+ SDeviceAttributes* attr = new (ELeave) SDeviceAttributes;
+ attr->iDeviceAttributes = NULL;
+ iImpl = reinterpret_cast<TImpl*>( attr );
+
+ if( !KSysUtilDisableDeviceTypeInfoSetupExe )
+ {
+ __SYSUTIL_TRACE("GetDeviceTypeInfoL caching enabled");
+
+ // Check if the P&S property is already set. If it isn't then define and set it. If it
+ // is we will most likely get KErrOverflow as we are only providing enough space to
+ // get the first TUint16. This stores the length of the attribute.
+ TUint16 attributesLength;
+ TPtr16 attributesLengthTPtr( &attributesLength, 1 );
+ TInt err = RProperty::Get( KSysUtilSetupUid, KDeviceTypeInfoUid.iUid, attributesLengthTPtr );
+ if ( KErrNotFound == err )
+ {
+ __SYSUTIL_TRACE("Launching sysutilsetup.exe");
+ User::LeaveIfError( LaunchSetupExecutable( KSetDeviceTypeInfoPropertyFlag ) );
+ __SYSUTIL_TRACE("sysutilsetup.exe terminated");
+
+ err = RProperty::Get( KSysUtilSetupUid, KDeviceTypeInfoUid.iUid, attributesLengthTPtr );
+ if( KErrOverflow != err )
+ {
+ User::LeaveIfError( err );
+ }
+ }
+ else if( KErrOverflow != err )
+ {
+ User::LeaveIfError( err );
+ }
+
+ attr->iDeviceAttributes = static_cast<TUint16*>( User::AllocL( sizeof(TUint16) * attributesLength ) );
+ TPtr16 deviceAttributesTPtr( attr->iDeviceAttributes, attributesLength );
+ User::LeaveIfError( RProperty::Get( KSysUtilSetupUid, KDeviceTypeInfoUid.iUid, deviceAttributesTPtr ) );
+ }
+ else
+ {
+ __SYSUTIL_TRACE("GetDeviceTypeInfoL caching disabled");
+ attr->iDeviceAttributes = FormattedDeviceTypeInfoL();
+ }
+ }
+
+/**
+Retrieves a reference to the attribute string which matches the provided
+UID. The attribute has a maximum length of KMaxAttributeLength UTF-16
+characters.
+
+The attribute is provisioned by the device creator. If the device creator
+does not provide an attribute value for the given UID then KNullDesC16
+will be supplied and KErrNotFound will be returned. If the device creator
+has supplied an attribute value which is longer than KMaxAttributeLength
+then the supplied value will be truncated. In this case KErrKErrOverflow
+will be returned.
+
+@param aAttributeUid The UID of the required attribute.
+@param aValue On return, contains the attribute value if successful
+ and KNullDesC16 otherwise.
+@return KErrNone Successful, the provisioned value has been returned.
+@return KErrNotFound A value for the given UID was not provisioned.
+@return KErrOverflow The provisioned attribute value has been truncated.
+@return - Otherwise, one of the other system-wide error codes.
+@publishedPartner
+@released
+*/
+EXPORT_C TInt CDeviceTypeInformation::GetAttribute( const TUid& aAttributeUid, TPtrC16& aValue ) const
+ {
+ SDeviceAttributes* attr = reinterpret_cast<SDeviceAttributes*>( this->iImpl );
+
+ TInt attributeNumber = FindAttributeNumber( *attr, aAttributeUid );
+ if( KErrNotFound != attributeNumber )
+ {
+ aValue.Set( attr->AttributePtr( attributeNumber ), attr->AttributeLength( attributeNumber ) );
+ return attr->Error( attributeNumber );
+ }
+
+ aValue.Set( KNullDesC16 );
+ return KErrNotFound;
+ }
+
+/**
+Retrieves a reference to the Manufacturer Name string. This value conveys
+the name of the device manufacturer. The Manufacturer Name has a maximum
+length of KMaxAttributeLength UTF-16 characters.
+
+This is a standard device type information attribute (it is common to all
+device creators) as such it can be assumed that an attribute value will
+always be retrieved.
+
+The Manufacturer Name is provisioned by the device creator. If the device
+creator does not provide a value for this attribute then a default value
+will be supplied instead and KDefaultValue will be returned. If the device
+creator has supplied a value and it is longer than KMaxAttributeLength
+then the provisioned value will be truncated. In this case KErrOverflow
+will be returned.
+
+Note: This attribute is represented by a UID of 0x10286358.
+
+@param aValue On return, contains the Manufacturer Name UTF-16 string.
+@return KErrNone Successful, the provisioned value has been returned.
+@return KDefaultValue Successful, the default value has been returned.
+@return KErrOverflow The provisioned attribute value has been truncated
+@return - Otherwise one of the other system-wide error codes.
+*/
+EXPORT_C TInt CDeviceTypeInformation::GetManufacturerName( TPtrC16& aValue ) const
+ {
+ TInt err = GetAttribute( KManufacturerNameUid, aValue );
+ if( KErrNotFound == err )
+ {
+ aValue.Set( KDefaultManufacturer );
+ return CDeviceTypeInformation::KDefaultValue;
+ }
+
+ return err;
+ }
+
+/**
+Retrieves a reference to the Model Name string. This value conveys the
+model name of the device as recognisable by the end-user i.e. the consumer.
+The Model Name has a maximum length of KMaxAttributeLength UTF-16
+characters.
+
+This is a standard device type information attribute (it is common to all
+device creators) as such it can be assumed that an attribute value will
+always be retrieved.
+
+The Model Name is provisioned by the device creator. If the device creator
+does not provide a value for this attribute then a default value will be
+supplied instead and KDefaultValue will be returned. If the device creator
+has supplied a value and it is longer than KMaxAttributeLength then the
+provisioned value will be truncated. In this case KErrKErrOverflow will be
+returned.
+
+Note: This attribute is represented by a UID of 0x10286359.
+
+@param aValue On return, contains the Model Name.
+@return KErrNone Successful, the provisioned value has been returned.
+@return KDefaultValue Successful, the default value has been returned.
+@return KErrOverflow The provisioned attribute value has been truncated.
+@return - Otherwise, one of the other system-wide error codes.
+*/
+EXPORT_C TInt CDeviceTypeInformation::GetModelName( TPtrC16& aValue ) const
+ {
+ TInt err = GetAttribute( KModelNameUid, aValue );
+ if( KErrNotFound == err )
+ {
+ aValue.Set( KDefaultModelName );
+ return CDeviceTypeInformation::KDefaultValue;
+ }
+
+ return err;
+ }
+
+/**
+Retrieves a reference to the Model Code string. This value conveys the
+internal model name or part number by which this model is known to the
+manufacturer. The Model Code has a maximum length of KMaxAttributeLength
+UTF-16 characters.
+
+This is a standard device type information attribute (it is common to all
+device creators) as such it can be assumed that an attribute value will
+always be retrieved.
+
+The Model Code is provisioned by the device creator. If the device creator
+does not provide a value for this attribute then a default value will be
+supplied instead and KDefaultValue will be returned. If the device creator
+has supplied a value and it is longer than KMaxAttributeLength then the
+provisioned value will be truncated. In this case KErrKErrOverflow will be
+returned.
+
+Note: This attribute is represented by a UID of 0x1028635A.
+
+@param aValue On return, contains the Model Code.
+@return KErrNone Successful, the provisioned value has been returned.
+@return KDefaultValue Successful, the default value has been returned.
+@return KErrOverflow The provisioned attribute value has been truncated.
+@return - Otherwise, one of the other system-wide error codes.
+*/
+EXPORT_C TInt CDeviceTypeInformation::GetModelCode( TPtrC16& aValue ) const
+ {
+ TInt err = GetAttribute( KModelCodeUid, aValue );
+ if( KErrNotFound == err )
+ {
+ aValue.Set( KDefaultModelCode );
+ return CDeviceTypeInformation::KDefaultValue;
+ }
+
+ return err;
+ }
+
+/**
+Retrieves a reference to the Revision ID string. This value contains the
+device revision and/or variant identification string and conveys the
+specific version of the hardware and software used in the device. The
+Revision ID has a maximum length of KMaxAttributeLength UTF-16
+characters.
+
+This is a standard device type information attribute (it is common to all
+device creators) as such it can be assumed that an attribute value will
+always be retrieved.
+
+The Revision ID is provisioned by the device creator. If the device
+creator does not provide a value for this attribute then a default value
+will be supplied instead and KDefaultValue will be returned. If the device
+creator has supplied a value and it is longer than KMaxAttributeLength
+then the provisioned value will be truncated. In this case
+KErrKErrOverflow will be returned.
+
+Note: This attribute is represented by a UID of 0x1028635B.
+
+@param aValue On return, contains the Revision ID (this also
+ includes the Variant ID).
+@return KErrNone Successful, the provisioned value has been returned.
+@return KDefaultValue Successful, the default value has been returned.
+@return KErrOverflow The provisioned attribute value has been truncated.
+@return - Otherwise, one of the other system-wide error codes.
+*/
+EXPORT_C TInt CDeviceTypeInformation::GetRevisionID( TPtrC16& aValue ) const
+ {
+ TInt err = GetAttribute( KRevisionIDUid, aValue );
+ if( KErrNotFound == err )
+ {
+ aValue.Set( KDefaultRevisionID );
+ return CDeviceTypeInformation::KDefaultValue;
+ }
+
+ return err;
+ }
+
+/**
+Retrieves a copy of the default Device Name string. This value conveys
+the default name for the device as might be used for network identification
+e.g. Bluetooth nickname. The Device Name has a maximum length of
+KMaxAttributeLength UTF-16 characters.
+
+This is a standard device type information attribute (it is common to all
+device creators) as such it can be assumed that an attribute value will
+always be retrieved.
+
+The Default Device Name is provisioned by the device creator. If the device
+creator does not provide a value for this attribute then a default value
+will be supplied instead and KDefaultValue will be returned. If the device
+creator has supplied a value and it is longer than KMaxAttributeLength or
+the user supplied descriptors length is less than KMaxAttributeLength then
+the provioned value will be truncated. In this case KErrKErrOverflow will
+be returned.
+
+Note: This attribute is represented by a UID of 0x1028635C.
+
+@param aValue On return, contains the Default Device Name.
+@return KErrNone Successful, the provisioned value has been returned.
+@return KDefaultValue Successful, the default value has been returned.
+@return KErrOverflow The provisioned attribute value has been truncated.
+@return - Otherwise, one of the other system-wide error codes.
+*/
+EXPORT_C TInt CDeviceTypeInformation::GetDefaultDeviceName( TPtrC16& aValue ) const
+ {
+ TInt err = GetAttribute( KDefaultDeviceNameUid, aValue );
+ if( KErrNotFound == err )
+ {
+ aValue.Set( KDefaultDeviceName );
+ return CDeviceTypeInformation::KDefaultValue;
+ }
+
+ return err;
+ }
+
+/**
+Retrieves a reference to the name of the UI Platform software used
+in the device. The UI Platform name has a maximum length of
+KMaxAttributeLength UTF-16 characters.
+
+This is a standard device type information attribute (it is common to all
+device creators) as such it can be assumed that an attribute value will
+always be retrieved.
+
+The UI Platform is provisioned by the device creator. If the device
+creator does not provide a value for this attribute then a default value
+will be supplied instead and KDefaultValue will be returned. If the device
+creator has supplied a value and it is longer than KMaxAttributeLength
+then the provisioned value will be truncated. In this case
+KErrKErrOverflow will be returned.
+
+Note: This attribute is represented by a UID of 0x1028635D.
+
+@param aValue On return, contains the UI Platform.
+@return KErrNone Successful, the provisioned value has been returned.
+@return KDefaultValue Successful, the default value has been returned.
+@return KErrOverflow The provisioned attribute value has been truncated.
+@return - Otherwise, one of the other system-wide error codes.
+*/
+EXPORT_C TInt CDeviceTypeInformation::GetUIPlatformName( TPtrC16& aValue ) const
+ {
+ TInt err = GetAttribute( KUIPlatformNameUid, aValue );
+ if( KErrNotFound == err )
+ {
+ aValue.Set( KDefaultUIPlatform );
+ return CDeviceTypeInformation::KDefaultValue;
+ }
+
+ return err;
+ }
+
+/**
+Retrieves a reference to the UI Platform version used in the device for
+display, transmission or tagging purposes. The UI Platform version has a maximum
+length of KMaxAttributeLength UTF-16 characters.
+
+The string should never be used for programmatic decisions based on assumed
+functionality present in the device as device creators can vary the content of
+the device firmware. Instead Feature Manager should be used to query the
+functional capabilities of a device. @see CFeatureDiscovery
+
+The UI Platform version is provisioned by the device creator. If the device
+creator does not provide a value for this attribute then a default value
+indicating unknown version will be supplied instead and KDefaultValue will
+be returned. If the device creator has supplied a value and it is longer than
+KMaxAttributeLength then the provisioned value will be truncated. In this case
+KErrOverflow will be returned. The format of the string is device dependent.
+
+Note: This attribute is represented by a UID of 0x10286360.
+
+@param aValue On return, contains the UI version number of the
+ current UI platform.
+@return KErrNone Successful, the provisioned value has been returned.
+@return KDefaultValue Successful, the default value has been returned.
+@return KErrOverflow The provisioned attribute value has been truncated
+ due to the provided descriptor being too small.
+@return - Otherwise, one of the other system-wide error codes.
+*/
+EXPORT_C TInt CDeviceTypeInformation::GetUIPlatformVersion( TPtrC16& aValue ) const
+ {
+ TInt err = GetAttribute( KUIPlatformVersionUid, aValue );
+ if( KErrNotFound == err )
+ {
+ aValue.Set( KDefaultUIPlatformVersion );
+ return CDeviceTypeInformation::KDefaultValue;
+ }
+
+ return err;
+ }
+
+/**
+Retrieves the UI platform major and minor version numbers as TUint16s.
+
+The retrieved values are both standard device type information attributes
+(they are common to all device creators) as such it can be assumed that
+values will always be retrieved.
+
+The UI version is provisioned by the device creator. If the device creator
+provides invalid major and minor UI version numbers the default version
+numbers will be supplied and KErrCorrupt will be returned. If the device
+creator does not provide values for these attributes then default values
+will be supplied and KDefaultValue will be returned.
+
+Note: The major UI version number attribute is represented by a UID of
+0x1028635E and minor UI version number is represented by a UID of
+0x1028635F.
+
+@param aMajor On return, contains the UI major version number.
+@param aMinor On return, contains the UI minor version number.
+@return KErrNone Successful, the provisioned value has been returned.
+@return KDefaultValue Successful, the default value has been returned.
+@return KErrCorrupt The provisioned attribute value is invalid. The
+ default value has been returned.
+@return - Otherwise, one of the other system-wide error codes.
+*/
+EXPORT_C TInt CDeviceTypeInformation::GetUIPlatformVersion(
+ TUint16& aMajor,
+ TUint16& aMinor ) const
+ {
+ SDeviceAttributes* attr = reinterpret_cast<SDeviceAttributes*>( this->iImpl );
+ TPtrC16 majorVersionNum( KDefaultUIPlatformVersionMajor );
+ TPtrC16 minorVersionNum( KDefaultUIPlatformVersionMinor );
+
+ // If we have valid major and minor numbers use these instead of the default values.
+ // Otherwise check to see if the minor version number exists. If it does the error
+ // number associated with this should be used instead of KDefaultValue as the
+ // version number (in major/minor form) is corrupt.
+ TInt attributeNumber = FindAttributeNumber( *attr, KUIPlatformVersionMajorUid );
+ if( KErrNotFound != attributeNumber )
+ {
+ if( attr->Uid( attributeNumber + 1 ) == KUIPlatformVersionMinorUid.iUid )
+ {
+ if( KErrNone == attr->Error( attributeNumber ) && KErrNone == attr->Error( attributeNumber + 1 ) )
+ {
+ majorVersionNum.Set( attr->AttributePtr( attributeNumber ), attr->AttributeLength( attributeNumber ) );
+ minorVersionNum.Set( attr->AttributePtr( attributeNumber + 1 ), attr->AttributeLength( attributeNumber + 1 ) );
+ }
+ }
+ }
+ else
+ {
+ attributeNumber = FindAttributeNumber( *attr, KUIPlatformVersionMinorUid );
+ }
+
+ TLex16 lex( majorVersionNum );
+ lex.Val( aMajor, EDecimal );
+
+ lex.Assign( minorVersionNum );
+ lex.Val( aMinor, EDecimal );
+
+ return attributeNumber == KErrNotFound ? KDefaultValue : attr->Error( attributeNumber );
+ }
+
+/**
+Retrieves a reference to the Symbian OS version used in the device for
+display, transmission or tagging purposes. The Symbian OS version has a maximum
+length of KMaxAttributeLength UTF-16 characters.
+
+The string should never be used for programmatic decisions based on assumed
+functionality present in the device as device creators can very the content of
+the device firmware. Instead Feature Manager should be used to query the
+functional capabilities of a device. @see CFeatureDiscovery
+
+This is a standard device type information attribute (it is common to all
+devices) as such it can be assumed that an attribute value will
+always be retrieved.
+
+The Symbian OS version is provisioned by the device creator. If the device
+creator does not provide a value for this attribute then a default value
+indicating unknown version will be supplied instead and KDefaultValue will
+be returned. If the device creator has supplied a value and it is longer than
+KMaxAttributeLength then the provisioned value will be truncated. In this case
+KErrOverflow will be returned. The format of the string is device dependent.
+
+Note: This attribute is represented by a UID of 0x10286363.
+
+@param aValue On return, contains the Symbian OS version number.
+@return KErrNone Successful, the provisioned value has been returned.
+@return KDefaultValue Successful, the default value has been returned.
+@return KErrOverflow The provisioned attribute value has been truncated
+ due to the provided descriptor being too small.
+@return - Otherwise one of the other system-wide error codes.
+*/
+EXPORT_C TInt CDeviceTypeInformation::GetOSVersion( TPtrC16& aValue ) const
+ {
+ TInt err = GetAttribute( KOSVersionUid, aValue );
+ if( KErrNotFound == err )
+ {
+ aValue.Set( KDefaultOSVersion );
+ return CDeviceTypeInformation::KDefaultValue;
+ }
+
+ return err;
+ }
+
+/**
+Retrieves the Symbian OS major and minor version numbers as TUint16s.
+
+The retrieved values are both standard device type information attributes
+(they are common to all device creators) as such it can be assumed that
+values will always be retrieved.
+
+The OS version is provisioned by the device creator. If the device creator
+provides invalid major and minor UI version numbers the default version
+numbers will be supplied and KErrCorrupt will be returned. If the device
+creator does not provide values for these attributes then default values
+will be supplied and KDefaultValue will be returned.
+
+Note: The major UI version number attribute is represented by a UID of
+0x10286361 and minor UI version number is represented by a UID of
+0x10286362.
+
+@param aMajor On return, contains the OS major version number.
+@param aMinor On return, contains the OS minor version number.
+@return KErrNone Successful, the provisioned value has been returned.
+@return KDefaultValue Successful, the default value has been returned.
+@return KErrCorrupt The provisioned attribute value is invalid. The
+ default value has been returned.
+@return - Otherwise, one of the other system-wide error codes.
+*/
+EXPORT_C TInt CDeviceTypeInformation::GetOSVersion( TUint16& aMajor,
+ TUint16& aMinor ) const
+ {
+ SDeviceAttributes* attr = reinterpret_cast<SDeviceAttributes*>( this->iImpl );
+ TPtrC16 majorVersionNum( KDefaultOSVersionMajor );
+ TPtrC16 minorVersionNum( KDefaultOSVersionMinor );
+
+ // If we have valid major and minor numbers use these instead of the default values.
+ // Otherwise check to see if the minor version number exists. If it does the error
+ // number associated with this should be used instead of KDefaultValue as the
+ // version number (in major/minor form) is corrupt.
+ TInt attributeNumber = FindAttributeNumber( *attr, KOSVersionMajorUid );
+ if( KErrNotFound != attributeNumber )
+ {
+ if( attr->Uid( attributeNumber + 1 ) == KOSVersionMinorUid.iUid )
+ {
+ if( KErrNone == attr->Error( attributeNumber ) && KErrNone == attr->Error( attributeNumber + 1 ) )
+ {
+ majorVersionNum.Set( attr->AttributePtr( attributeNumber ), attr->AttributeLength( attributeNumber ) );
+ minorVersionNum.Set( attr->AttributePtr( attributeNumber + 1 ), attr->AttributeLength( attributeNumber + 1 ) );
+ }
+ }
+ }
+ else
+ {
+ attributeNumber = FindAttributeNumber( *attr, KOSVersionMinorUid );
+ }
+
+ TLex16 lex( majorVersionNum );
+ lex.Val( aMajor, EDecimal );
+
+ lex.Assign( minorVersionNum );
+ lex.Val( aMinor, EDecimal );
+
+ return attributeNumber == KErrNotFound ? KDefaultValue : attr->Error( attributeNumber );
+ }