scrsaver/screensaveraiwplugin/src/screensaveraiwplugin.cpp
branchRCL_3
changeset 26 e8d784ac1a4b
parent 0 040fcad49f44
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/scrsaver/screensaveraiwplugin/src/screensaveraiwplugin.cpp	Wed Sep 01 12:30:40 2010 +0100
@@ -0,0 +1,657 @@
+/*
+* Copyright (c) 2005 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:   Implementation file for class CScreenSaverAIWPlugin
+*
+*/
+
+
+
+#include <eikmenup.h>
+#include <f32file.h>
+#include <e32property.h>
+#include <AiwMenu.h>
+#include <AiwCommon.h>
+#include <AiwCommon.hrh>
+#include <barsread.h>
+#include <eikenv.h>
+#include <implementationproxy.h>
+#include <StringLoader.h>
+#include <aknnotewrappers.h>
+#include <data_caging_path_literals.hrh>
+#include <screensaveraiwplugin.rsg>
+#include <AknsSrvClient.h>
+#include <imageconversion.h>
+#include <centralrepository.h>
+#include <ScreensaverInternalCRKeys.h>
+#include <ScreensaverInternalPSKeys.h>
+#include <pslninternalcrkeys.h> 
+#include "ScreenSaverAnimPluginInternalCRKeys.h"
+#include "screensaveraiwplugin.h"
+#include "screensaveraiwplugin.rh"
+
+_LIT(KResourceFileName, "screensaveraiwplugin.rsc");
+_LIT(KDriveZ, "z:");
+_LIT(KPluginUidAnimation, "[1020744D]25");  // '25' is the drive number (Z = ROM), not 
+_LIT(KPluginUidSlideshow, "[102823ED]25");  // mandatory
+
+
+_LIT(KScreenSaverAIWPluginMimeTypeImage, "image");
+_LIT(KScreenSaverAIWPluginMimeTypeOTABitmap, "image/x-ota-bitmap");
+_LIT(KScreenSaverAIWPluginSeparator, "/");
+
+_LIT(KScreenSaverAIWPluginMimeTypeGIF, "image/gif");
+_LIT(KScreenSaverAIWPluginMimeTypeSVG, "image/svg+xml");
+_LIT(KScreenSaverAIWPluginMimeTypeM3G, "application/m3g");
+_LIT(KScreenSaverAIWPluginMimeTypeSWF, "application/x-shockwave-flash");
+
+
+// ======== LOCAL FUNCTIONS ========
+
+// ======== MEMBER FUNCTIONS ========
+
+// -----------------------------------------------------------------------------
+// CScreenSaverAIWPlugin::NewL
+// -----------------------------------------------------------------------------
+//
+CScreenSaverAIWPlugin* CScreenSaverAIWPlugin::NewL()
+    {
+    CScreenSaverAIWPlugin* self = new( ELeave ) CScreenSaverAIWPlugin;
+    CleanupStack::PushL( self );
+    self->ConstructL();
+    CleanupStack::Pop(self);
+    return self;
+    }
+
+// -----------------------------------------------------------------------------
+// CScreenSaverAIWPlugin::CScreenSaverAIWPlugin
+// -----------------------------------------------------------------------------
+//
+CScreenSaverAIWPlugin::CScreenSaverAIWPlugin():
+    iConeResLoader(*CCoeEnv::Static())
+    {
+    }
+    
+// -----------------------------------------------------------------------------
+// CScreenSaverAIWPlugin::ConstructL
+// Symbian 2nd phase constructor can leave.
+// -----------------------------------------------------------------------------
+//
+void CScreenSaverAIWPlugin::ConstructL()
+    {
+    TParse parse;
+    parse.Set(KResourceFileName, &KDC_RESOURCE_FILES_DIR, &KDriveZ);
+    TFileName resourceFileName;
+    resourceFileName.Append(parse.FullName());
+    iConeResLoader.OpenL(resourceFileName);  
+    }    
+
+// -----------------------------------------------------------------------------
+// CScreenSaverAIWPlugin::~CScreenSaverAIWPlugin
+// -----------------------------------------------------------------------------
+//
+CScreenSaverAIWPlugin::~CScreenSaverAIWPlugin()
+    {
+    iConeResLoader.Close();
+    iSupportedImageFiles.Close();
+    delete iScreensaverRepository;
+    delete iAnimationRepository;
+    }
+
+// ---------------------------------------------------------------------------
+// From class CAiwServiceIfMenu.
+// ---------------------------------------------------------------------------
+//
+void CScreenSaverAIWPlugin::InitialiseL(MAiwNotifyCallback& /*aFrameworkCallback*/,
+    const RCriteriaArray& /*aInterest*/)
+    {
+    // Not needed.
+    }
+
+// ---------------------------------------------------------------------------
+// From class CAiwServiceIfMenu.
+//
+// Implements setting the passed image(s) as screensaver.
+// ---------------------------------------------------------------------------
+//
+void CScreenSaverAIWPlugin::HandleServiceCmdL(const TInt& aCmdId,
+    const CAiwGenericParamList& aInParamList,
+    CAiwGenericParamList& /*aOutParamList*/,
+    TUint /*aCmdOptions*/,
+    const MAiwNotifyCallback* aCallback)
+    {
+     // Handle only KAiwCmdAssignScreenSaver command.
+    if ( aCmdId == KAiwCmdAssignScreenSaver )
+        {
+#ifdef CSCREENSAVERAIWPLUGIN_TRACES	
+        DumpParamList(_L("HandleServiceCmdL"),aInParamList);
+#endif
+
+        // Leave, if there were not given all the required parameters
+        ValidateParamListL(aInParamList);
+        
+        // Get the supported image files to iSupportedImageFiles
+        GetSupportedImageFilesL(aInParamList,iSupportedImageFiles);
+
+#ifdef CSCREENSAVERAIWPLUGIN_TRACES	
+        DumpSupportedImageFileList(iSupportedImageFiles);
+#endif
+        
+        TInt textResourceId = 0;        
+        if (iSupportedImageFiles.Count() == 1 && IsAnimatedImageL(iSupportedImageFiles[0].iFileName,
+                                                                  iSupportedImageFiles[0].iMimeType))
+            {
+            textResourceId = R_SCREEN_SAVER_AIW_PLUGIN_TEXT_IMAGE_AS_ANIMATION;
+            SetAnimatedScreenSaverL(iSupportedImageFiles);
+            }
+        else
+            {
+            textResourceId = ((iSupportedImageFiles.Count() > 1)?R_SCREEN_SAVER_AIW_PLUGIN_TEXT_IMAGES_ADDED:
+                                                               R_SCREEN_SAVER_AIW_PLUGIN_TEXT_IMAGE_ADDED);           
+            SetSlideShowScreenSaverL(iSupportedImageFiles);
+            }            
+            
+        //  display confirmation note
+        DisplayInfoNoteL(textResourceId);              
+
+        // If aCallback defined inform consumers that we have done with
+        // the operation.
+        if (aCallback)
+            {
+            // Cope with the design problems of AIW framework
+            MAiwNotifyCallback* nonConstCallback =
+            const_cast<MAiwNotifyCallback*> (aCallback);
+        
+            CAiwGenericParamList* eventParamList = CAiwGenericParamList::NewL();
+            CleanupStack::PushL(eventParamList);
+            nonConstCallback->HandleNotifyL(
+        	    KAiwCmdAssignScreenSaver,
+        	    KAiwEventCompleted,
+        	    *eventParamList,
+        	    aInParamList);
+            CleanupStack::PopAndDestroy(eventParamList);
+            }
+        }
+    }
+    
+// ---------------------------------------------------------------------------
+// From class CAiwServiceIfMenu.
+//
+// Inserts plugin's menu items to aMenuPane.
+// ---------------------------------------------------------------------------
+//
+void CScreenSaverAIWPlugin::InitializeMenuPaneL(CAiwMenuPane& aMenuPane,
+    TInt aIndex,
+    TInt /*aCascadeId*/,
+    const CAiwGenericParamList& aInParamList)
+    {        
+#ifdef CSCREENSAVERAIWPLUGIN_TRACES	
+        DumpParamList(_L("InitializeMenuPaneL"),aInParamList);        
+#endif
+    			
+	// Insert menu only if there is at least a single supported MIME type is given
+	if ( AnyMimeTypeSupportedL(aInParamList) )   
+		{
+	    TResourceReader reader;
+	    CCoeEnv::Static()->CreateResourceReaderLC(reader, R_SCREEN_SAVER_AIW_PLUGIN_MENU);
+	    aMenuPane.AddMenuItemsL(reader, KAiwCmdAssignScreenSaver, aIndex);
+	    CleanupStack::PopAndDestroy(); // reader
+		}
+    }
+    
+// ---------------------------------------------------------------------------
+// From class CAiwServiceIfMenu.
+//
+// Implements menu command handling for EScreenSaverAIWPluginCmdSetScreenSaver.
+// ---------------------------------------------------------------------------
+//
+void CScreenSaverAIWPlugin::HandleMenuCmdL(
+	TInt aMenuCmdId,
+    const CAiwGenericParamList& aInParamList,
+    CAiwGenericParamList& aOutParamList,
+    TUint aCmdOptions,
+    const MAiwNotifyCallback* aCallback)
+    {
+    if (aMenuCmdId == EScreenSaverAIWPluginCmdSetScreenSaver)
+        {
+        // Menu commands are handled as service commands.
+        HandleServiceCmdL(
+            KAiwCmdAssignScreenSaver,
+            aInParamList,
+            aOutParamList,
+            aCmdOptions,
+            aCallback );
+        }
+    }
+
+// -----------------------------------------------------------------------------
+// Implements showing information note 
+// -----------------------------------------------------------------------------
+//
+void CScreenSaverAIWPlugin::DisplayInfoNoteL(TInt aTextResourceId)
+    {
+    HBufC* text = StringLoader::LoadLC(aTextResourceId);
+    CAknInformationNote* dlg = new (ELeave) CAknInformationNote(EFalse);
+    dlg->ExecuteLD(*text);
+    CleanupStack::PopAndDestroy(text);
+    }
+
+
+// -----------------------------------------------------------------------------
+// Validates aParamList if it is not valid
+// the method leaves with KErrArgument
+// -----------------------------------------------------------------------------
+//
+void CScreenSaverAIWPlugin::ValidateParamListL(const CAiwGenericParamList& aParamList)
+    {
+    TBool valid = EFalse;
+    
+    // The parameter list must be dividable by 2 because the number of file name
+    // items must be equal with the number of MIME type items.
+    valid = !(aParamList.Count()%2); 
+    
+    valid = valid && AnyMimeTypeSupportedL(aParamList);
+    
+    if (valid)
+        {
+        TInt index = 0;
+        TPtrC fileName = GetAiwParamAsDescriptor(index, aParamList, EGenericParamFile);
+        
+        // At least one file name parameter should be given
+        valid = !(fileName == KNullDesC);
+        }
+    
+    if (!valid)
+        {
+		User::Leave(KErrArgument);
+        }    
+    }
+    
+// -----------------------------------------------------------------------------
+// Gets supported image file list from generic param list
+// -----------------------------------------------------------------------------
+//
+void CScreenSaverAIWPlugin::GetSupportedImageFilesL(const CAiwGenericParamList& aParamList,
+                                                    RArray<TImageFile>& aSupportedImageFiles)
+    {    
+    aSupportedImageFiles.Reset();
+    for (TInt i = 0;; i++)
+        {        
+        TImageFile imageFile;
+        TPtrC fileName = GetAiwParamAsDescriptor(i, aParamList, EGenericParamFile);
+        
+        if (fileName == KNullDesC)
+            {
+            // last file item is reached
+            break;    
+            }
+            
+        TPtrC mimeTypeString = GetAiwParamAsDescriptor(i, aParamList, EGenericParamMIMEType);
+        if (mimeTypeString == KNullDesC)
+            {
+            // missing MIME type for file
+            User::Leave(KErrArgument);    
+            break;
+            }
+        else if (IsMimeTypeSupportedL(mimeTypeString))
+            {
+            imageFile.iFileName.Set(fileName);
+            imageFile.iMimeType.Set(mimeTypeString);
+            aSupportedImageFiles.Append(imageFile);
+            }            
+        }
+    }
+    
+
+// -----------------------------------------------------------------------------
+// Returns ETrue if any of the MIME types is supported
+// -----------------------------------------------------------------------------
+//
+TBool CScreenSaverAIWPlugin::AnyMimeTypeSupportedL(const CAiwGenericParamList& aParamList)
+    {
+    TBool ret = EFalse;
+    for (TInt i = 0;; i++)
+        {
+        TPtrC mimeTypeString = GetAiwParamAsDescriptor(i, aParamList, EGenericParamMIMEType);
+        if (mimeTypeString == KNullDesC)
+            {
+            // If no MIME type parameters are passed just leave
+            if (i <= 0)
+                {
+                User::Leave(KErrArgument);    
+                }            
+            break;
+            }
+        else if (IsMimeTypeSupportedL(mimeTypeString))
+            {
+            ret = ETrue;
+            break;
+            }            
+        }
+    return ret;
+    }
+// -----------------------------------------------------------------------------
+// Implements checking if a given MIME type is supported or not
+// -----------------------------------------------------------------------------
+//
+TBool CScreenSaverAIWPlugin::IsMimeTypeSupportedL(const TDesC& aMimeTypeString)
+    {   
+    // Check for a type separator in the string
+    TInt pos = aMimeTypeString.Find(KScreenSaverAIWPluginSeparator);
+
+    // Leave if no separator was found.. the MIME
+    // standard requires it   
+    if (pos == KErrNotFound)
+        {
+        User::Leave(KErrArgument);
+        }
+    
+	// Construct the compare string    
+    TPtrC compareString(aMimeTypeString.Left(pos));
+
+	// Perform the comparison
+    TBool ret = EFalse;
+    
+    // Mime type case:  IMAGE/* except IMAGE/X-OTA-BITMAP
+    if (!compareString.CompareF(KScreenSaverAIWPluginMimeTypeImage) &&
+         aMimeTypeString.CompareF(KScreenSaverAIWPluginMimeTypeOTABitmap))
+        {
+        ret = ETrue;
+        }   
+        
+    if (!ret)         	   		    	
+        {
+        TBool dummy;
+        ret = IsAnimatedMimeTypeL(aMimeTypeString,dummy);
+        }
+    
+	return ret;    
+    }    
+    
+// ---------------------------------------------------------------------------
+// Determines if the MIME type is animated or not and in addition returns
+// in aUseImageDecoder if image decoder should be used to determine if
+// the image is really animated
+// ---------------------------------------------------------------------------
+//
+TBool CScreenSaverAIWPlugin::IsAnimatedMimeTypeL( const TDesC& aMimeTypeString, TBool& aUseImageDecoder )
+    {    
+    TBool ret = EFalse;     
+    aUseImageDecoder = EFalse; 
+    
+    // check if animated an needs image decoder
+    if (!aMimeTypeString.CompareF(KScreenSaverAIWPluginMimeTypeGIF))
+        {
+        aUseImageDecoder = ETrue;
+        ret = ETrue; 
+        }
+    else if (!aMimeTypeString.CompareF(KScreenSaverAIWPluginMimeTypeSVG) ||
+             !aMimeTypeString.CompareF(KScreenSaverAIWPluginMimeTypeM3G) ||
+             !aMimeTypeString.CompareF(KScreenSaverAIWPluginMimeTypeSWF))
+        {
+        ret = ETrue; 
+        }
+    
+    return ret;
+    }
+    
+    
+// -----------------------------------------------------------------------------
+// Implements getting a AIW parameter as descriptor
+// -----------------------------------------------------------------------------
+//    
+TPtrC CScreenSaverAIWPlugin::GetAiwParamAsDescriptor(
+        TInt& aIndex,
+		const CAiwGenericParamList& aParamList,
+		TGenericParamId aParamType)
+	{	
+	const TAiwGenericParam* genericParam = NULL;
+    genericParam = aParamList.FindFirst( 
+        aIndex,
+        aParamType,
+        EVariantTypeDesC);
+        
+    if (aIndex != KErrNotFound && genericParam)
+        {
+        // Get the data
+        return genericParam->Value().AsDes();
+        }
+	else
+    	{
+		return KNullDesC();
+    	}
+	}
+	
+#ifdef CSCREENSAVERAIWPLUGIN_TRACES	
+
+// -----------------------------------------------------------------------------
+// Dump parameters in aParamList
+// -----------------------------------------------------------------------------
+//   
+void CScreenSaverAIWPlugin::DumpParamList(const TDesC& aMethod, const CAiwGenericParamList& aParamList)
+    {
+    DumpParamList(aMethod,EGenericParamFile,aParamList);
+    DumpParamList(aMethod,EGenericParamMIMEType,aParamList);
+    }
+    
+// -----------------------------------------------------------------------------
+// Dump parameters in aParamList for a given aParamType
+// -----------------------------------------------------------------------------
+//   
+void CScreenSaverAIWPlugin::DumpParamList(const TDesC& aMethod,
+                                          TGenericParamId aParamType,
+                                          const CAiwGenericParamList& aParamList)
+	{	
+    for (TInt i = 0 ;; i++)
+        {
+        TPtrC paramString = GetAiwParamAsDescriptor(i, aParamList, aParamType);
+        if (paramString == KNullDesC)
+            {
+            break;
+            }
+        else 
+            {
+            RDebug::Print( _L("ScreenSaverAIWPlugin: %x CScreenSaverAIWPlugin::%S: Index=%d, paramType=%d, paramString=%S"), this, &aMethod, i, aParamType, &paramString);
+            }            
+        }
+	}    
+	
+// -----------------------------------------------------------------------------
+// Dump supported image file list
+// -----------------------------------------------------------------------------
+//   
+void CScreenSaverAIWPlugin::DumpSupportedImageFileList(const RArray<TImageFile>& aSupportedImageFiles)
+	{	
+    for (TInt i = 0 ; i < aSupportedImageFiles.Count() ; i++)
+        {
+        RDebug::Print( _L("ScreenSaverAIWPlugin: %x DumpSupportedImageFileList: Index=%d, file=%S, MIME type=%S"), this, i, &aSupportedImageFiles[i].iFileName, &aSupportedImageFiles[i].iMimeType);
+        }
+	}    
+	
+#endif	    
+
+// ---------------------------------------------------------------------------
+// Determines if an image is animated or not
+// ---------------------------------------------------------------------------
+//
+TBool CScreenSaverAIWPlugin::IsAnimatedImageL( const TDesC& aFileName,
+                                               const TDesC& aMimeTypeString )
+    { 
+    TBool useImageDecoder = EFalse;
+    TBool animated = IsAnimatedMimeTypeL( aMimeTypeString, useImageDecoder );
+    
+    if (useImageDecoder)
+        {
+        animated = IsReallyAnimatedImageL(aFileName);
+        }
+        
+    return animated;
+    }
+
+// ---------------------------------------------------------------------------
+// Determines if an image file is really animated or not
+// ---------------------------------------------------------------------------
+//
+TBool CScreenSaverAIWPlugin::IsReallyAnimatedImageL( const TDesC& aFileName )
+    {    
+    CImageDecoder* decoder = CImageDecoder::FileNewL(CCoeEnv::Static()->FsSession(),aFileName);
+    CleanupStack::PushL( decoder );
+    TBool animated = (decoder->FrameCount() > 1);
+    CleanupStack::PopAndDestroy(); // decoder
+    return animated;
+    }
+    
+// ---------------------------------------------------------------------------
+// Set and activate slide-show screen saver.
+// ---------------------------------------------------------------------------
+//
+void CScreenSaverAIWPlugin::SetSlideShowScreenSaverL( const RArray<TImageFile>& aSupportedImageFiles  )
+    {
+    StoreImageListToFileL(aSupportedImageFiles);
+    
+    if (iScreensaverRepository == NULL)
+        {
+        // Setting the screensaver type & plugin name 
+        iScreensaverRepository = CRepository::NewL(KCRUidScreenSaver);
+        }
+    if (iSlideshowRepository == NULL)
+        {
+        iSlideshowRepository = CRepository::NewL(KCRUidThemes);        
+        }
+        
+    // set psln to "not random"
+    iSlideshowRepository->Set(KThemesScreenSaverSlideSetType, 0);        
+        
+    // Slideshow plugin used
+    iScreensaverRepository->Set(KScreenSaverPluginName, KPluginUidSlideshow);
+    
+    // Type 3 = plugin
+    iScreensaverRepository->Set(KScreenSaverObject, EScreensaverTypePlugin);
+    
+    // Inform screensaver that slide set has changed
+    User::LeaveIfError(
+            RProperty::Set(
+                KPSUidScreenSaver,
+                KScreenSaverPluginSettingsChanged,
+                EScreenSaverPluginSettingsChanged ) );
+    }
+    
+// ---------------------------------------------------------------------------
+// Set and activate animated screen saver.
+// ---------------------------------------------------------------------------
+//
+void CScreenSaverAIWPlugin::SetAnimatedScreenSaverL( const RArray<TImageFile>& aSupportedImageFiles  )
+    {
+    if (iScreensaverRepository == NULL)
+        {
+        // Setting the screensaver type & plugin name 
+        iScreensaverRepository = CRepository::NewL(KCRUidScreenSaver);
+        }    
+        
+    if (iAnimationRepository == NULL)
+        {
+        // Setting the screensaver type & plugin name 
+        iAnimationRepository = CRepository::NewL(KCRUidScreenSaverAnimPlugin);
+        }
+        
+    iAnimationRepository->Set(KScreenSaverAnimatedFileName, aSupportedImageFiles[0].iFileName);
+    
+    // Animation plugin used
+    iScreensaverRepository->Set(KScreenSaverPluginName, KPluginUidAnimation);
+    
+    // Type 3 = plugin
+    iScreensaverRepository->Set(KScreenSaverObject, EScreensaverTypePlugin);
+    }
+    
+// ---------------------------------------------------------------------------
+// Stores slide set image file names to file.
+// ---------------------------------------------------------------------------
+//
+void CScreenSaverAIWPlugin::StoreImageListToFileL( const RArray<TImageFile>& aSupportedImageFiles  )
+    {
+    // Get file from server.
+    RFile imgFile;
+    OpenImageFileL( imgFile, EAknsSrvInifileSSSS );
+    CleanupClosePushL( imgFile );    
+
+    // Finally, write image filenames to the file.
+    TFileText textFile;
+    textFile.Set( imgFile );
+    textFile.Seek( ESeekEnd );
+
+    for (TInt i = 0 ; i < aSupportedImageFiles.Count(); i++)
+        {
+        User::LeaveIfError( textFile.Write( aSupportedImageFiles[i].iFileName ) );
+        }
+                
+    imgFile.Flush();
+
+    CleanupStack::PopAndDestroy(); // imgFile
+    }
+
+// ---------------------------------------------------------------------------
+// Open image list file for operations.
+// ---------------------------------------------------------------------------
+//
+void CScreenSaverAIWPlugin::OpenImageFileL( RFile& aImageFile, const TInt aSlideSetType )
+    {
+    // First, connect to skin server.
+    RAknsSrvSession skinsrv;
+    User::LeaveIfError( skinsrv.Connect() );
+    CleanupClosePushL( skinsrv );
+
+    // Then get file handle.
+    TInt fileserverhandle = 0;
+    TInt filehandle = 0;
+    // Validate type and open image file.
+    if ( aSlideSetType == EAknsSrvInifileSSWP )
+        {
+        fileserverhandle = 
+            skinsrv.OpenImageInifile( EAknsSrvInifileSSWP, filehandle );
+        }
+    else
+        {
+        fileserverhandle = 
+            skinsrv.OpenImageInifile( EAknsSrvInifileSSSS, filehandle );
+
+        }
+    if ( fileserverhandle <= 0 || filehandle == 0 )
+        {
+        User::Leave( fileserverhandle );
+        }
+
+    // Finally adopt file from server.
+    User::LeaveIfError( aImageFile.AdoptFromServer( fileserverhandle, filehandle ) );
+    CleanupStack::PopAndDestroy(); // skinsrv
+    }
+
+
+    
+// ======== ECOM INITIALIZATION ========
+
+// Map the interface UIDs to implementation factory functions
+const TImplementationProxy ImplementationTable[] =
+    {
+    IMPLEMENTATION_PROXY_ENTRY(KScreenSaverAIWPluginImplementationUid, CScreenSaverAIWPlugin::NewL)
+    };
+
+// ---------------------------------------------------------
+// Exported proxy for instantiation method resolution
+// ---------------------------------------------------------
+//
+EXPORT_C const TImplementationProxy* ImplementationGroupProxy(TInt& aTableCount)
+    {
+    aTableCount = sizeof(ImplementationTable) / sizeof(TImplementationProxy);
+    return ImplementationTable;
+    }
+