diff -r 000000000000 -r 4e1aa6a622a0 commonservices/sysutil/src/sysutil.cpp --- /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 +#include +#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 +#include +#include +#include +#include +#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(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&, 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& 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( 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(aKeys[attributeNumber] >> 16); + deviceAttributes[2 + (2 * attributeNumber) + 1] = static_cast(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(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(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(aKey.iUid) < aAttr.Uid( middle ) ) + { + top = middle - 1; + } + else if( static_cast(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(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(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 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( 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( 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( 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(aLeft); + TUint32 right = static_cast(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& 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 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 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(tempUid), orderer ); + if( KErrAlreadyExists != err ) + { + User::LeaveIfError( err ); + + TInt index = aKeys.FindInOrder( static_cast(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& aKeys, CDesC16ArraySeg& aValues ) + { + RArray 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( 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 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& aKeys, CDesC16ArraySeg& aValues, const TUid& aMajorVersionUid, const TUid& aMinorVersionUid) + { + TLinearOrder 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 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 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: + +V 1.0\\n29-07-07\\nBuild12345\\n(c) Symbian Software + +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: + +V 1.0\\n29-07-07\\nBuild12345\\n(c) Symbian Software + +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 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: + +custom build\n20090626\nusb fix xyz +or +PR1.0 +or +PR1.1 + +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( 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( 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( 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( 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( 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( 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 ); + }