mmlibs/mmfw/src/ControllerFramework/MMFControllerFramework.cpp
changeset 0 b8ed18f6c07b
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mmlibs/mmfw/src/ControllerFramework/MMFControllerFramework.cpp	Thu Oct 07 22:34:12 2010 +0100
@@ -0,0 +1,1575 @@
+// Copyright (c) 2002-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 <e32math.h>
+#include <mmf/server/mmfdrmpluginserverproxy.h>
+#include "mmfcontrollerframework.h"
+#include "mmfcontroller.h"
+#include "mmfcontrollerheap.h"
+#include "mmfcontrollerframeworkpriv.h"
+#include "mmfcontrollerpatchdata.h"
+
+#ifdef SYMBIAN_ENABLE_SPLIT_HEADERS
+#include <mmf/common/mmfcontrollerextendeddata.h>
+#include <mmf/common/mmfcustomcommandparsermanager.h>
+#include <mmf/common/mmfcontrollerframeworkclasses.h>
+#endif
+
+// Panic
+   
+enum
+	{
+	EPanicHeapHalfOpen=1,
+	EPanicHeapOpenWithoutTls,
+	EPanicReleaseWithoutRegister,
+	EPanicBadInvariant
+	};
+	
+#ifdef _DEBUG
+static void Panic(TInt aReason)
+	{
+	_LIT(KControllerFramework, "ControllerFramework");
+	User::Panic(KControllerFramework, aReason);
+	}
+#endif
+
+EXPORT_C RMMFControllerProxy::RMMFControllerProxy() :
+	iDestinationPckg(TMMFMessageDestination(KUidInterfaceMMFControllerProxy, KMMFObjectHandleControllerProxy)),
+	iLogonAO(NULL), iThreadPriority(static_cast<TThreadPriority>(KDefaultMMFControllerThreadPriority)), iFlags(0)
+	{
+	iSubThread.Close();//iSubThread is automatically initialised to be a handle to this thread!
+	}
+
+TInt RMMFControllerProxy::LoadController(
+	TUid aControllerUid, 
+ 	const CMMFControllerImplementationInformation& aControllerInfo,
+ 	TBool aUseSharedHeap,
+ 	TBool aNoDRMCap)
+	{
+	// First check that we haven't already created the subthread
+	if (iSubThread.Handle() != 0)
+		return KErrAlreadyExists;
+	
+#ifdef SYMBIAN_FORCE_USE_SHARED_HEAP
+	aUseSharedHeap = ETrue;
+#endif
+
+	//determine what maximum heap size this thread should be created with
+	TUint maxHeapSize =0;
+	TInt error = KErrNone;
+	maxHeapSize = aControllerInfo.HeapSpaceRequired();
+	TUint stackSize = aControllerInfo.StackSize();
+	
+	ASSERT(!iLogonAO);
+	TRAP(error, iLogonAO = CLogonMonitor::NewL(this));
+	
+	if (!error)
+		{
+		if (aNoDRMCap && aControllerInfo.SupportsSecureDRMProcessMode())
+			{
+			error = DoCreateSessionForNoDRMCapClient(maxHeapSize, aUseSharedHeap, stackSize);
+			}
+		else
+			{
+			// server2 will be set in this function call
+			error = DoCreateSubThread(&iLogonAO->Server(), maxHeapSize, aUseSharedHeap, stackSize);
+		
+			// Now create a session with the controller proxy server running in the subthread
+			if (!error)
+				{
+				// create a session with iServer2 (local server)
+				error = CreateSession(iLogonAO->Server(), KMMFControllerProxyVersion);
+				}
+			}
+		}
+
+	// Finally, tell the controller proxy server to load the relevant plugin
+	if (!error)
+		{
+		TMMFUidPckg uidPckg(aControllerUid);
+		error = SendSync(iDestinationPckg, 
+						 EMMFControllerProxyLoadControllerPluginByUid, 
+						 uidPckg, 
+						 KNullDesC8);
+		}
+
+	// If an error occurred with any of the above, close all the handles
+	if (error)
+		Close();
+
+	return error;
+	}
+
+
+EXPORT_C TInt RMMFControllerProxy::LoadController(TUid aControllerUid, TBool aUseSharedHeap)
+	{
+ 	CMMFControllerImplementationInformation* controllerInfo = NULL;
+ 	
+ 	TRAPD(err, controllerInfo = CMMFControllerImplementationInformation::NewL(aControllerUid));
+	if (!err && controllerInfo)
+		{
+		err = LoadController(aControllerUid, *controllerInfo, aUseSharedHeap, EFalse);
+		delete controllerInfo;
+		}
+ 	return err;
+	}
+
+EXPORT_C TInt RMMFControllerProxy::LoadController(const CMMFControllerImplementationInformation& aControllerInfo, TBool aUseSharedHeap)
+	{
+	return LoadController(aControllerInfo.Uid(), aControllerInfo, aUseSharedHeap, EFalse);
+	}
+
+EXPORT_C TInt RMMFControllerProxy::LoadControllerInSecureDRMProcess(TUid aControllerUid, TBool aUseSharedHeap)
+	{
+	CMMFControllerImplementationInformation* controllerInfo = NULL;
+	
+	TRAPD(err, controllerInfo = CMMFControllerImplementationInformation::NewL(aControllerUid));
+	if (!err && controllerInfo)
+		{
+		err = LoadController(aControllerUid, *controllerInfo, aUseSharedHeap, ETrue);
+		delete controllerInfo;
+		}
+	return err;
+	}
+	
+EXPORT_C TInt RMMFControllerProxy::LoadControllerInSecureDRMProcess(const CMMFControllerImplementationInformation& aControllerInfo, TBool aUseSharedHeap)
+	{
+	return LoadController(aControllerInfo.Uid(), aControllerInfo, aUseSharedHeap, ETrue);
+	}
+
+TUint RMMFControllerProxy::ControllersMaxHeapSizeL(TUid aControllerUid)
+	{
+	CMMFControllerImplementationInformation* controllerInfo = NULL;
+
+	TRAPD(err, controllerInfo = CMMFControllerImplementationInformation::NewL(aControllerUid));
+
+
+	TUint maxHeapSize = KMMFDefaultControllerThreadHeapSize;
+	
+	if((err != KErrNone) && (err != KErrCorrupt))
+		{
+		delete controllerInfo;
+		User::Leave(err);
+		}
+
+
+	if(controllerInfo && (err == KErrNone))
+		maxHeapSize = controllerInfo->HeapSpaceRequired();
+
+	delete controllerInfo;
+
+	return maxHeapSize;
+	}
+
+
+TInt RMMFControllerProxy::DoCreateSubThread(RServer2* aServer2, TUint aMaxHeapSize, TBool aUseSharedHeap, TUint aStackSize)
+	{
+	TInt error = KErrNone;
+
+	TControllerProxyServerParams params;
+	params.iServer = aServer2;
+	params.iUsingSharedHeap = aUseSharedHeap;
+
+#ifdef SYMBIAN_USE_CLIENT_HEAP
+	// controller threads share the *client* heap (intended for out of memory testing)
+	error = iSubThread.Create(_L(""), &CMMFControllerProxyServer::StartThread, 
+			aStackSize, NULL, &params, EOwnerThread);
+#else
+	if( aUseSharedHeap )
+		{
+		//controller threads all share a controller heap
+		CMMFControllerHeap* contHeap = static_cast<CMMFControllerHeap*>(Dll::Tls());
+		if(contHeap == NULL)
+			{
+			TRAP(error, contHeap = CMMFControllerHeap::NewL());
+			if(error)
+				{			
+				return error;	
+				}
+				
+			Dll::SetTls(contHeap);
+			}
+			
+		__ASSERT_DEBUG((iFlags&EFlagOpenedSharedHeap)==0, Panic(EPanicHeapHalfOpen));
+			
+		RHeap* sharedHeap = contHeap->RegisterHeap();
+		// We've registered, so record the fact so can "unregister" on close or error
+		iFlags |= EFlagOpenedSharedHeap; 
+		
+		error = iSubThread.Create(KNullDesC, &CMMFControllerProxyServer::StartThread,
+				aStackSize, sharedHeap, 						
+				&params, EOwnerThread);		
+		}
+	else
+		{	
+		// Threads create own heap (default behaviour)
+		if(aMaxHeapSize < static_cast<TUint>(KMinHeapSize))
+			aMaxHeapSize = KMinHeapSize; //else raises a USER 111 panic
+		else if(aMaxHeapSize >  static_cast<TUint>(KMMFControllerProxyMaxHeapSize))
+			aMaxHeapSize = KMMFControllerProxyMaxHeapSize;
+		
+		TThreadCreateInfo threadSettings (KNullDesC, &CMMFControllerProxyServer::StartThread,
+										  aStackSize, &params);
+		threadSettings.SetCreateHeap(KMinHeapSize, aMaxHeapSize);
+		threadSettings.SetOwner(EOwnerThread);
+		threadSettings.SetPaging(TThreadCreateInfo::EUnpaged);
+		
+		error = iSubThread.Create(threadSettings);
+		}
+#endif
+
+	if (error)
+		{
+		return error;
+		}
+
+	TRequestStatus rendezvous;
+	iSubThread.Rendezvous(rendezvous);
+	if (rendezvous != KRequestPending)
+		{
+		iSubThread.Kill(0);
+		}
+	else
+		{
+		iLogonAO->StartMonitoring(iSubThread);
+		if (iLogonAO->iStatus != KRequestPending)
+			{
+			// Failed to logon
+			iSubThread.RendezvousCancel(rendezvous);
+			User::WaitForRequest(rendezvous);
+			iSubThread.Kill(0);
+			iSubThread.Close();
+			return iLogonAO->iStatus.Int();
+			}
+		else
+			{
+			iSubThread.SetPriority(iThreadPriority);
+			iSubThread.Resume();
+			}
+		}
+		
+	User::WaitForRequest(rendezvous); // wait for startup or death
+	
+	if (rendezvous != KErrNone)
+		{
+		iLogonAO->Cancel();
+		iSubThread.Close();
+		// if open failed, but we registered the heap, need to release
+		if((iFlags&EFlagOpenedSharedHeap))
+			{
+			ReleaseHeap();
+			}		
+		}
+		
+	return rendezvous.Int();
+	}
+
+EXPORT_C void RMMFControllerProxy::Close()
+	{
+#ifdef _DEBUG
+	_LIT(KMMFClientThreadPanic, "MMFClientThread");
+#endif
+	// check if thread was created
+	TBool subThreadCreated = EFalse;
+	TRequestStatus logoffStatus;
+	TBool logoffFailed = EFalse;
+	if (iSubThread.Handle() != KNullHandle)
+		{
+		subThreadCreated = ETrue;
+		iLogonAO->Cancel();
+		iSubThread.Logon(logoffStatus);
+		
+		if (logoffStatus == KErrNoMemory && iSubThread.ExitType() == EExitPending)
+			{
+			// Logon() call has failed because of a lack of memory
+			logoffFailed = ETrue;
+			}
+		}
+
+	// Close the controller and wait for its exit.
+	// Close the session to signal the controller proxy server to shut down.
+	RHandleBase::Close();
+	
+	// Now wait for the death of the subthread if we have a valid handle...
+	if (subThreadCreated)
+		{
+		RProcess thisProcess;
+		RProcess controllerProcess;
+		iSubThread.Process(controllerProcess);	// ignore error, best try
+		TBool secureDrmMode = thisProcess.Id() != controllerProcess.Id();
+		thisProcess.Close();
+		controllerProcess.Close();
+				
+		RTimer timer;
+		TInt err = timer.CreateLocal();
+		// If we managed to create the timer and logon to the thread, 
+		// wait for both the death and the timeout to minimise the risk of deadlock
+		if (!err && !logoffFailed)
+			{
+			TRequestStatus timeout;
+			timer.After(timeout, KMmfControllerThreadShutdownTimeout);
+			User::WaitForRequest(logoffStatus, timeout);
+			if (logoffStatus == KRequestPending)
+				{
+				// we have timed out.  Kill the controller thread
+				iSubThread.LogonCancel(logoffStatus);
+				User::WaitForRequest(logoffStatus);
+				
+				if (!secureDrmMode)
+					{
+					// Controller server thread is created in current process
+				#ifdef _DEBUG
+					iSubThread.Panic(KMMFClientThreadPanic,KErrDied);
+				#else
+					iSubThread.Kill(KErrDied);
+				#endif
+					}
+				else
+					{
+					// Controller server thread is created through DRM plugin server
+					RMMFDRMPluginServerProxy server;
+					// ignore all RMMFDRMPluginServerProxy errors, best try
+					err = server.Open();
+					if (err == KErrNone)
+						{
+					#ifdef _DEBUG
+						server.PanicControllerThread(iSubThread.Id(), KMMFClientThreadPanic, KErrDied);
+					#else
+						server.KillControllerThread(iSubThread.Id(), KErrDied);
+					#endif
+						server.Close();
+						}
+					}
+				}
+			else
+				{
+				// subthread has exited. Cancel the timer.
+				timer.Cancel();
+				User::WaitForRequest(timeout);
+				}
+			}
+		else
+			{
+			// We have no timer or we can't logon to the thread so we'll just poll the thread status a maximum
+			// of 10 times and kill the thread if it hasn't exited after the polling
+			for (TInt i=0; i<10 && iSubThread.ExitType() == EExitPending; ++i)
+				{
+				User::After(KMmfControllerThreadShutdownTimeout/10);	// wait for a while
+				}
+				
+			if (iSubThread.ExitType() == EExitPending)
+				{
+				// The polling hasn't been succesful so we kill the thread
+				if (!secureDrmMode)
+					{
+					iSubThread.Kill(KErrDied);
+					}
+				else
+					{
+					// Controller server thread is created through DRM plugin server
+					RMMFDRMPluginServerProxy server;
+					// ignore all RMMFDRMPluginServerProxy errors, best try
+					err = server.Open();
+					if (err == KErrNone)
+						{
+						server.KillControllerThread(iSubThread.Id(), KErrDied);
+						}
+					}
+				}
+				
+			User::WaitForRequest(logoffStatus);
+			}
+		timer.Close();
+		}
+
+	// Close the handle to the controller thread
+	iSubThread.Close();
+	// Delete the Logon AO
+	if (iLogonAO)
+		{
+		delete iLogonAO;
+		iLogonAO = NULL;
+		}
+	// if this is last thread to be killed delete shared heap
+	if((iFlags&EFlagOpenedSharedHeap))
+		{
+		ReleaseHeap();
+		}	
+	}
+
+// Release the shared heap, should only be called if has previously been registered
+// by this thread
+void RMMFControllerProxy::ReleaseHeap()
+	{
+	__ASSERT_DEBUG((iFlags&EFlagOpenedSharedHeap), Panic(EPanicReleaseWithoutRegister));
+
+	CMMFControllerHeap* contHeap = static_cast<CMMFControllerHeap*>(Dll::Tls());
+	__ASSERT_DEBUG(contHeap!=NULL, Panic(EPanicHeapOpenWithoutTls));
+	
+	if(contHeap != NULL)
+		{
+		TInt refCount = contHeap->ReleaseHeap();
+		if(refCount == 0)
+			{  //no other controllers using the heap
+			delete contHeap;
+			Dll::SetTls(NULL);
+			}
+		}
+		
+	iFlags &= ~EFlagOpenedSharedHeap; // clear flag since we've released the heap
+	}
+
+EXPORT_C TInt RMMFControllerProxy::SendSync(const TMMFMessageDestinationPckg& aDestination, TInt aFunction, const TDesC8& aDataTo1, const TDesC8& aDataTo2, TDes8& aDataFrom) const
+	{
+	// Make sure we have been opened
+	if (iSubThread.Handle() == 0)
+		{
+		return KErrNotReady;
+		}
+	else
+		return SendReceiveResult(aFunction, aDestination, aDataTo1, aDataTo2, aDataFrom);
+	}
+
+
+EXPORT_C TInt RMMFControllerProxy::SendSync(TInt aFunction, const TIpcArgs& aIpcArgs) const
+	{
+	// Make sure we have been opened
+	if (iSubThread.Handle() == 0)
+		{
+		return KErrNotReady;
+		}
+	else
+		return RSessionBase::SendReceive(aFunction, aIpcArgs);
+	}
+	
+EXPORT_C void RMMFControllerProxy::SendAsync(TInt aFunction, const TIpcArgs& aIpcArgs, TRequestStatus& aStatus) const
+	{
+	// Make sure we have been opened
+	if (iSubThread.Handle() == 0)
+		{
+		TRequestStatus* status = &aStatus;
+		User::RequestComplete(status, KErrNotReady);
+		}
+	else
+		RSessionBase::SendReceive(aFunction, aIpcArgs, aStatus);
+	}
+
+
+
+EXPORT_C TInt RMMFControllerProxy::SendSync(const TMMFMessageDestinationPckg& aDestination, TInt aFunction, const TDesC8& aDataTo1, const TDesC8& aDataTo2) const
+	{
+	// Make sure we have been opened
+	if (iSubThread.Handle() == 0)
+		{
+		return KErrNotReady;
+		}
+	else
+		return SendReceive(aFunction, aDestination, aDataTo1, aDataTo2);
+	}
+
+EXPORT_C void RMMFControllerProxy::SendAsync(const TMMFMessageDestinationPckg& aDestination, TInt aFunction, const TDesC8& aDataTo1, const TDesC8& aDataTo2, TDes8& aDataFrom, TRequestStatus& aStatus) const
+	{
+	if (iSubThread.Handle() == 0)
+		{
+		TRequestStatus* stat = &aStatus;
+		User::RequestComplete(stat, KErrNotReady);
+		}
+	else
+		SendReceiveResult(aFunction, aDestination, aDataTo1, aDataTo2, aDataFrom, aStatus);
+	}
+
+EXPORT_C void RMMFControllerProxy::SendAsync(const TMMFMessageDestinationPckg& aDestination, TInt aFunction, const TDesC8& aDataTo1, const TDesC8& aDataTo2, TRequestStatus& aStatus) const
+	{
+	if (iSubThread.Handle() == 0)
+		{
+		TRequestStatus* stat = &aStatus;
+		User::RequestComplete(stat, KErrNotReady);
+		}
+	else
+		SendReceive(aFunction, aDestination, aDataTo1, aDataTo2, aStatus);
+	}
+
+EXPORT_C void RMMFControllerProxy::ReceiveEvents(TMMFEventPckg& aEvent, TRequestStatus& aStatus)
+	{
+	SendAsync(iDestinationPckg, EMMFControllerProxyReceiveEvents, KNullDesC8, KNullDesC8, aEvent, aStatus);
+	}
+
+EXPORT_C TInt RMMFControllerProxy::CancelReceiveEvents()
+	{
+	return SendSync(iDestinationPckg, EMMFControllerProxyCancelReceiveEvents, KNullDesC8, KNullDesC8);
+	}
+
+EXPORT_C TInt RMMFControllerProxy::SetThreadPriority(const TThreadPriority& aPriority) const
+	{
+	TInt err = KErrNone;
+
+	if (iSubThread.Handle() == 0)
+		{
+		err = KErrNotReady;
+		}
+	else
+		{
+		if (iThreadPriority != aPriority)
+			{
+			// This is a const method so cast it away to store the priority
+			RMMFControllerProxy* nonConstThis = const_cast<RMMFControllerProxy*>(this);
+			nonConstThis->iThreadPriority = aPriority;
+			}
+			
+		// check controller thread creation location
+		RProcess thisProcess;
+		RProcess controllerProcess;
+		err = iSubThread.Process(controllerProcess);
+		
+		if (err == KErrNone)
+			{
+			if (thisProcess.Id() == controllerProcess.Id())
+				{
+				// Controller server thread is created in current process
+				if (iSubThread.Priority() != iThreadPriority)
+					{
+					iSubThread.Suspend();
+					iSubThread.SetPriority(iThreadPriority);
+					iSubThread.Resume();
+					}
+				}
+			else
+				{
+				// Controller server thread is created through DRM plugin server
+				RMMFDRMPluginServerProxy server;
+				err = server.Open();
+				if (err == KErrNone)
+					{
+					err = server.SetThreadPriority(iSubThread.Id(), iThreadPriority);
+					server.Close();
+					}
+				}
+			}
+		thisProcess.Close();
+		controllerProcess.Close();
+		}
+	return err;
+	}
+	
+void RMMFControllerProxy::ThreadTerminated()
+	{
+	// The controller subthread has died and the controller should be closed
+	iSubThread.Close();
+	}
+
+TInt RMMFControllerProxy::DoCreateSessionForNoDRMCapClient(TUint aMaxHeapSize, TBool aUseSharedHeap, TUint aStackSize)
+	{
+	TThreadId tid;
+	RMMFDRMPluginServerProxy server;
+    TInt error = server.Open();
+    
+    if(!error)
+    	{
+    	error = server.LaunchControllerServer(aMaxHeapSize, aUseSharedHeap, tid, aStackSize);
+    	}		    
+    if(!error)
+		{
+		error = iSubThread.Open(tid, EOwnerThread);
+		if(!error)
+			{
+			iLogonAO->StartMonitoring(iSubThread);
+			if (iLogonAO->iStatus != KRequestPending)
+				{
+				// Failed to logon
+				server.KillControllerThread(tid, 0);
+				iSubThread.Close();
+				error = iLogonAO->iStatus.Int();
+				}
+			}
+		else
+			{
+			// Failed to open thread handle
+			server.KillControllerThread(tid, 0);
+			}
+		}
+	if(!error)
+		{
+		error = server.SetThreadPriority(tid, iThreadPriority);
+		if(!error)
+			{
+			error = SetReturnedHandle(server.GetControllerSessionHandle());	
+			}
+		if(error)
+			{
+			// Failed to create session with controller
+			iLogonAO->Cancel();
+			server.KillControllerThread(tid, 0);
+			iSubThread.Close();
+			}
+		}
+    server.Close();
+    return error;
+	}
+
+
+// RMMFCustomCommandsBase
+
+/**
+Constructor.
+
+@param  aController
+        A reference to the controller client class that will be used to send
+        custom commands to the controller plugin.
+@param  aInterfaceId
+        The UID of the custom command interface that is provided by this client
+        API class.
+
+@since 7.0s
+*/
+EXPORT_C RMMFCustomCommandsBase::RMMFCustomCommandsBase(RMMFController& aController, TUid aInterfaceId)
+	: iController(aController), iDestinationPckg(aInterfaceId)
+	{
+	}
+
+
+// TMMFMessageDestination
+EXPORT_C TMMFMessageDestination::TMMFMessageDestination()
+	: iInterfaceId(KNullUid), iDestinationHandle(KMMFObjectHandleController)
+	{
+	}
+
+EXPORT_C TMMFMessageDestination::TMMFMessageDestination(TUid aInterfaceId)
+	: iInterfaceId(aInterfaceId), iDestinationHandle(KMMFObjectHandleController)
+	{
+	}
+
+EXPORT_C TMMFMessageDestination::TMMFMessageDestination(TUid aInterfaceId, TInt aDestinationHandle)
+	: iInterfaceId(aInterfaceId), iDestinationHandle(aDestinationHandle)
+	{
+	}
+
+EXPORT_C TMMFMessageDestination::TMMFMessageDestination(const TMMFMessageDestination& aOther)
+	: iInterfaceId(aOther.iInterfaceId), iDestinationHandle(aOther.iDestinationHandle)
+	{
+	}
+
+EXPORT_C TUid TMMFMessageDestination::InterfaceId() const
+	{
+	return iInterfaceId;
+	}
+
+EXPORT_C TInt TMMFMessageDestination::DestinationHandle() const
+	{
+	return iDestinationHandle;
+	}
+
+EXPORT_C TBool TMMFMessageDestination::operator==(const TMMFMessageDestination& aOther) const
+	{
+	return ((iInterfaceId==aOther.iInterfaceId) && (iDestinationHandle==aOther.iDestinationHandle));
+	}
+
+
+
+// CMMFControllerProxySession
+CMMFControllerProxySession* CMMFControllerProxySession::NewL()
+	{
+	CMMFControllerProxySession* s = new(ELeave) CMMFControllerProxySession;
+	return s;
+	}
+
+void CMMFControllerProxySession::CreateL(const CMmfIpcServer& aServer)
+	{
+	CMmfIpcSession::CreateL(aServer);
+	iServer = STATIC_CAST(CMMFControllerProxyServer*, (CONST_CAST(CMmfIpcServer*, &aServer)));
+	iServer->SessionCreated();
+	}
+
+CMMFControllerProxySession::~CMMFControllerProxySession()
+	{
+	delete iController;
+	delete iEventReceiver;
+	iEvents.Close();
+	iServer->SessionDestroyed();
+	}
+
+
+
+void CMMFControllerProxySession::ServiceL(const RMmfIpcMessage& aMessage)
+	{
+	TMMFMessage message(aMessage);
+	// Get the destination info from the client.
+	message.FetchDestinationL();
+
+	if (message.Destination().InterfaceId() == KUidInterfaceMMFControllerProxy)
+		{
+		// Message for controller proxy so decode here
+		TBool complete = EFalse;
+		switch (message.Function())
+			{
+		case EMMFControllerProxyReceiveEvents:
+			complete = ReceiveEventsL(message);
+			break;
+		case EMMFControllerProxyCancelReceiveEvents:
+			complete = CancelReceiveEvents(message);
+			break;
+		case EMMFControllerProxyLoadControllerPluginByUid:
+			complete = LoadControllerL(message);
+			break;
+		default:
+			User::Leave(KErrNotSupported);
+			}
+		if (complete)
+			message.Complete(KErrNone);
+		}
+	else
+		{
+		// Message for controller so forward on to controller baseclass
+		if (iController)
+			iController->HandleRequestL(message);
+		else
+			User::Leave(KErrNotReady);
+		}
+	}
+
+CMMFControllerProxySession::CMMFControllerProxySession()
+	{
+	}
+
+TBool CMMFControllerProxySession::ReceiveEventsL(TMMFMessage& aMessage)
+	{
+	if (iEventReceiver)
+		User::Leave(KErrAlreadyExists);
+	iEventReceiver = CMMFEventReceiver::NewL(aMessage);
+	//send the next cached event (if any) to the client
+	if (iEvents.Count() > 0)
+		{
+		TMMFEvent& event = iEvents[0];
+		iEventReceiver->SendEvent(event);
+		delete iEventReceiver;
+		iEventReceiver=NULL;
+		iEvents.Remove(0);
+		}
+	return EFalse;
+	}
+
+TBool CMMFControllerProxySession::CancelReceiveEvents(TMMFMessage& /*aMessage*/)
+	{
+	delete iEventReceiver;
+	iEventReceiver = NULL;
+	return ETrue;
+	}
+
+TInt CMMFControllerProxySession::SendEventToClient(const TMMFEvent& aEvent)
+	{
+	TInt error = KErrNone;
+	if (iEventReceiver)
+		{
+		//send event to client now
+		iEventReceiver->SendEvent(aEvent);
+		delete iEventReceiver;
+		iEventReceiver=NULL;
+		error = KErrNone;
+		}
+	else
+		{
+		//queue the request for later
+		TMMFEvent event(aEvent);
+		//if we've exceeded the max number of cached messages, delete the first and append this one to the end
+		if (iEvents.Count() >= KMMFControllerProxyMaxCachedMessages)
+			iEvents.Remove(0);
+		error = iEvents.Append(event);
+		}
+	return error;
+	}
+
+TBool CMMFControllerProxySession::LoadControllerL(TMMFMessage& aMessage)
+	{
+	TMMFUidPckg pckg;
+	aMessage.ReadData1FromClientL(pckg);
+	
+	RThread clientThread;
+	aMessage.iMessage.ClientL(clientThread);
+	CleanupClosePushL(clientThread);
+	iController = CMMFController::NewL(pckg(), *this, clientThread.Id());
+	CleanupStack::PopAndDestroy(&clientThread);
+	return ETrue;
+	}
+
+
+
+CMMFControllerProxyServer* CMMFControllerProxyServer::NewL(RServer2* aServer2)
+	{
+	CMMFControllerProxyServer* s = new(ELeave) CMMFControllerProxyServer();
+	CleanupStack::PushL(s);
+	s->ConstructL(aServer2);
+	CleanupStack::Pop(s);
+	return s;
+	}
+
+CMMFControllerProxyServer::CMMFControllerProxyServer() :
+	CMmfIpcServer(EPriorityStandard, EGlobalSharableSessions)
+	{
+	}
+
+void CMMFControllerProxyServer::ConstructL(RServer2* aServer2)
+	{
+	SetPinClientDescriptors(ETrue);
+	
+	StartL(KNullDesC);
+	*aServer2 = CServer2::Server();
+	
+	iShutdownTimer = CMMFControllerProxyShutdown::NewL();
+	iShutdownTimer->Start();
+	}
+
+CMMFControllerProxyServer::~CMMFControllerProxyServer()
+	{
+	delete iShutdownTimer;
+	}
+
+EXPORT_C TInt CMMFControllerProxyServer::StartThread(TAny* aParam)
+	{
+	TInt err = KErrNone;
+	//create cleanupstack
+	CTrapCleanup* cleanup=CTrapCleanup::New(); // get clean-up stack
+	if (!cleanup)
+		err = KErrNoMemory;
+	if (!err)
+		{
+		TRAP(err, DoStartThreadL(aParam));
+		}
+	delete cleanup;
+	return err;
+	}
+	
+void CMMFControllerProxyServer::RenameControllerProxyThread()
+	{
+	RThread thread;
+	TThreadId threadId;
+	TName name;
+	name.Append(KMMFControllerProxyServerName);
+	threadId = thread.Id();
+	name.AppendNum(threadId.Id(),EHex);
+	User::RenameThread(name);
+	}
+
+void CMMFControllerProxyServer::DoStartThreadL(TAny* aParam)
+	{
+	TControllerProxyServerParams* params = static_cast<TControllerProxyServerParams*>(aParam);
+	
+	//Rename Current thread to unique name
+	RenameControllerProxyThread();
+	
+#ifndef SYMBIAN_USE_CLIENT_HEAP
+	TBool usingSharedHeap = params->iUsingSharedHeap; // take copy since params invalid after Rendezvous
+	
+	if( ! usingSharedHeap )
+		{
+		__UHEAP_MARK;
+		}
+
+#endif
+	// create and install the active scheduler we need
+	CActiveScheduler* s=new(ELeave) CActiveScheduler;
+	CleanupStack::PushL(s);
+	CActiveScheduler::Install(s);
+	// create the server (leave it on the cleanup stack)
+	CleanupStack::PushL(CMMFControllerProxyServer::NewL( params->iServer ) );
+	// Initialisation complete, now signal the client
+	RThread::Rendezvous(KErrNone);
+	// Ready to run
+	CActiveScheduler::Start();
+	
+	REComSession::FinalClose();
+	
+	// Cleanup the server and scheduler
+	CleanupStack::PopAndDestroy(2, s);
+#ifndef SYMBIAN_USE_CLIENT_HEAP
+	if( ! usingSharedHeap )
+		{
+		__UHEAP_MARKEND;
+		}
+#endif
+	}
+
+TInt CMMFControllerProxyServer::RunError(TInt aError)
+	{
+	// Send error to the client
+	Message().Complete(aError);
+	ReStart();
+	return KErrNone;
+	}
+
+CMmfIpcSession* CMMFControllerProxyServer::NewSessionL(const TVersion& aVersion) const
+	{
+	// Only one session is allowed to connect to us
+	if (iHaveSession)
+		User::Leave(KErrAlreadyExists);
+	// Check that the version number of the client is correct
+	if (!User::QueryVersionSupported(KMMFControllerProxyVersion, aVersion))
+		User::Leave(KErrNotSupported);
+
+	return CMMFControllerProxySession::NewL();
+	}
+
+void CMMFControllerProxyServer::SessionCreated()
+	{
+	iHaveSession = ETrue;
+	// Stop the shutdown timer
+	iShutdownTimer->Cancel();
+	}
+
+void CMMFControllerProxyServer::SessionDestroyed()
+	{
+	// Need to shut down
+	iShutdownTimer->ShutdownNow();
+	}
+
+CMMFControllerProxyShutdown* CMMFControllerProxyShutdown::NewL() 
+	{
+	CMMFControllerProxyShutdown* s = new(ELeave) CMMFControllerProxyShutdown();
+	CleanupStack::PushL(s);
+	s->ConstructL();
+	CleanupStack::Pop(s);
+	return s;
+	}
+
+CMMFControllerProxyShutdown::CMMFControllerProxyShutdown() : 
+	CTimer(EPriorityLow)
+	{
+	CActiveScheduler::Add(this);
+	}
+
+void CMMFControllerProxyShutdown::ConstructL()
+	{
+	CTimer::ConstructL();
+	}
+
+void CMMFControllerProxyShutdown::Start()
+	{
+	After(EMMFControllerProxyShutdownDelay);
+	}
+
+void CMMFControllerProxyShutdown::RunL()
+	{
+	ShutdownNow();
+	}
+
+void CMMFControllerProxyShutdown::ShutdownNow()
+	{
+	CActiveScheduler::Stop();
+	}
+
+
+
+
+
+
+
+CMMFEventReceiver* CMMFEventReceiver::NewL(const TMMFMessage& aMessage)
+	{
+	return new(ELeave) CMMFEventReceiver(aMessage);
+	}
+
+CMMFEventReceiver::~CMMFEventReceiver()
+	{
+	if (!(iMessage.IsCompleted()))
+		iMessage.Complete(KErrDied);
+	}
+
+void CMMFEventReceiver::SendEvent(const TMMFEvent& aEvent)
+	{
+	TMMFEventPckg eventpckg(aEvent);
+	TInt err = iMessage.WriteDataToClient(eventpckg);
+	iMessage.Complete(err);
+	}
+
+CMMFEventReceiver::CMMFEventReceiver(const TMMFMessage& aMessage) : iMessage(aMessage)
+	{
+	}
+
+
+
+// TMMFMessage
+EXPORT_C TMMFMessage::TMMFMessage(const TMMFMessage& aMessage) :
+	iMessage(aMessage.iMessage), 
+#ifdef __MMF_USE_IPC_V2__
+	iFunction(aMessage.iFunction),
+#endif  // __MMF_USE_IPC_V2__
+	iDestination(aMessage.iDestination), 
+	iAmCompleted(aMessage.iAmCompleted)
+	{
+	}
+
+EXPORT_C const TMMFMessageDestination& TMMFMessage::Destination()
+	{
+	return iDestination;
+	}
+
+EXPORT_C TInt TMMFMessage::Function()
+	{
+#ifdef __MMF_USE_IPC_V2__
+	return iFunction;
+#else
+	return iMessage.Function();
+#endif // __MMF_USE_IPC_V2__
+	}
+
+EXPORT_C TInt TMMFMessage::SizeOfData1FromClient()
+	{
+#ifdef __MMF_USE_IPC_V2__
+	return iMessage.GetDesLength(1);
+#else
+	return iMessage.Client().GetDesLength(iMessage.Ptr1());
+#endif // __MMF_USE_IPC_V2__
+	}
+
+EXPORT_C void TMMFMessage::ReadData1FromClientL(TDes8& aDes)
+	{
+#ifdef __MMF_USE_IPC_V2__
+	iMessage.ReadL(1, aDes);
+#else
+	iMessage.ReadL(iMessage.Ptr1(), aDes);
+#endif // __MMF_USE_IPC_V2__
+	}
+
+EXPORT_C TInt TMMFMessage::ReadData1FromClient(TDes8& aDes)
+	{
+	TRAPD(err, ReadData1FromClientL(aDes));
+	return err;
+	}
+
+EXPORT_C TInt TMMFMessage::SizeOfData2FromClient()
+	{
+#ifdef __MMF_USE_IPC_V2__
+	return iMessage.GetDesLength(2);
+#else
+	return iMessage.Client().GetDesLength(iMessage.Ptr2());
+#endif // __MMF_USE_IPC_V2__
+	}
+
+EXPORT_C void TMMFMessage::ReadData2FromClientL(TDes8& aDes)
+	{
+#ifdef __MMF_USE_IPC_V2__
+	iMessage.ReadL(2, aDes);
+#else
+	iMessage.ReadL(iMessage.Ptr2(), aDes);
+#endif // __MMF_USE_IPC_V2__
+	}
+
+EXPORT_C TInt TMMFMessage::ReadData2FromClient(TDes8& aDes)
+	{
+	TRAPD(err, ReadData2FromClientL(aDes));
+	return err;
+	}
+
+EXPORT_C void TMMFMessage::WriteDataToClientL(const TDesC8& aDes)
+	{
+#ifdef __MMF_USE_IPC_V2__
+	iMessage.WriteL(3, aDes);
+#else
+	iMessage.WriteL(iMessage.Ptr3(), aDes);
+#endif // __MMF_USE_IPC_V2__
+	}
+
+EXPORT_C TInt TMMFMessage::WriteDataToClient(const TDesC8& aDes)
+	{
+	TRAPD(err, WriteDataToClientL(aDes));
+	return err;
+	}
+
+EXPORT_C void TMMFMessage::Complete(TInt aReason)
+	{
+	iMessage.Complete(aReason);
+	iAmCompleted = ETrue;
+	}
+
+EXPORT_C TBool TMMFMessage::IsCompleted()
+	{
+	return iAmCompleted;
+	}
+	
+EXPORT_C void TMMFMessage::AdoptFileHandleFromClientL(TInt aFsHandleIndex, TInt aFileHandleIndex, RFile& aFile)
+	{
+	User::LeaveIfError(aFile.AdoptFromClient(RMessage2(iMessage) , aFsHandleIndex, aFileHandleIndex));
+	}
+
+EXPORT_C TMMFMessage::TMMFMessage(const RMmfIpcMessage& aMessage) :
+	iMessage(aMessage), 
+#ifdef __MMF_USE_IPC_V2__
+	iFunction(aMessage.Function()),
+#endif // __MMF_USE_IPC_V2__
+	iAmCompleted(EFalse)
+	{
+	}
+
+EXPORT_C void TMMFMessage::FetchDestinationL()
+	{
+	// Read the destination info from the client
+	TMMFMessageDestinationPckg pckg;
+#ifdef __MMF_USE_IPC_V2__
+	iMessage.ReadL(0, pckg);
+#else
+	iMessage.ReadL(iMessage.Ptr0(), pckg);
+#endif // __MMF_USE_IPC_V2__
+	iDestination = pckg();
+	}
+
+
+// CMMFObject
+
+/**
+Constructor.
+
+@param  aInterfaceId
+        The UID of the interface provided by this object.
+@since 7.0s
+*/
+EXPORT_C CMMFObject::CMMFObject(TUid aInterfaceId)
+	: iHandle(aInterfaceId, KMMFObjectHandleNull)
+	{
+	}
+
+/**
+Destructor.
+*/
+EXPORT_C CMMFObject::~CMMFObject()
+	{
+	}
+
+/**
+Returns the handle of the object.
+
+@return The handle of this object.
+
+@since  7.0s
+*/
+EXPORT_C const TMMFMessageDestination& CMMFObject::Handle()
+	{
+	return iHandle;
+	}
+
+/**
+Compares two CMMFObjects by comparing their handles.
+
+@param  aOther
+        The object to be compared with this object.
+
+@return A boolean indicating if the two CMMFObjects are the same. ETrue if they are the same,
+        EFalse if the objects are different.
+@since  7.0s
+*/
+EXPORT_C TBool CMMFObject::operator==(const CMMFObject& aOther)
+	{
+	return (iHandle==aOther.iHandle);
+	}
+
+void CMMFObject::SetHandle(const TMMFMessageDestination& aNewHandle)
+	{
+	iHandle = aNewHandle;
+	}
+
+
+// CMMFDataSourceHolder
+
+/**
+Constructor.
+
+@param  aDataSource
+        The data source to be wrapped.
+
+@since  7.0s
+*/
+EXPORT_C CMMFDataSourceHolder::CMMFDataSourceHolder(MDataSource& aDataSource)
+	: CMMFObject(KUidInterfaceMMFDataSourceHolder), iDataSource(&aDataSource)
+	{
+	}
+
+/**
+Destructor.
+
+Note: This deletes the data source.
+
+@since 7.0s
+*/
+EXPORT_C CMMFDataSourceHolder::~CMMFDataSourceHolder()
+	{
+	delete iDataSource;
+	}
+
+/**
+Returns a reference to the data source.
+
+@return The data source.
+
+@since  7.0s
+*/
+EXPORT_C MDataSource& CMMFDataSourceHolder::DataSource()
+	{
+	return *iDataSource;
+	}
+
+/**
+Implementation of the pure virtual function inherited from CMMFObject.
+
+Passes the request directly to the data source.
+
+@param  aMessage
+        The message to be handled.
+
+@since  7.0s
+*/
+EXPORT_C void CMMFDataSourceHolder::HandleRequest(TMMFMessage& aMessage)
+	{
+	iDataSource->SourceCustomCommand(aMessage);
+	}
+
+
+// CMMFDataSinkHolder
+
+/**
+Constructor.
+
+@param  aDataSink
+        The data sink to be wrapped.
+@since 7.0s
+*/
+EXPORT_C CMMFDataSinkHolder::CMMFDataSinkHolder(MDataSink& aDataSink)
+	: CMMFObject(KUidInterfaceMMFDataSinkHolder), iDataSink(&aDataSink)
+	{
+	}
+
+/**
+Destructor.
+
+Note: This deletes the data sink.
+
+@since  7.0s
+*/
+EXPORT_C CMMFDataSinkHolder::~CMMFDataSinkHolder()
+	{
+	delete iDataSink;
+	}
+
+/**
+Returns a reference to the data sink.
+
+@return The data sink.
+@since 7.0s
+*/
+EXPORT_C MDataSink& CMMFDataSinkHolder::DataSink()
+	{
+	return *iDataSink;
+	}
+
+/**
+Implementation of the pure virtual function inherited from CMMFObject.
+
+Passes the request directly to the data sink.
+
+@param  aMessage
+        The message to be handled.
+
+@since  7.0s
+*/
+EXPORT_C void CMMFDataSinkHolder::HandleRequest(TMMFMessage& aMessage)
+	{
+	iDataSink->SinkCustomCommand(aMessage);
+	}
+
+
+// CMMFCustomCommandParserBase
+EXPORT_C TUid CMMFCustomCommandParserBase::InterfaceId()
+	{
+	return iInterfaceId;
+	}
+
+EXPORT_C CMMFCustomCommandParserBase::~CMMFCustomCommandParserBase()
+	{
+	}
+
+EXPORT_C CMMFCustomCommandParserBase::CMMFCustomCommandParserBase(TUid aInterfaceId)
+	: iInterfaceId(aInterfaceId)
+	{
+	}
+
+
+// CMMFObjectContainer
+
+/**
+Constructor.
+
+@since  7.0s
+*/
+EXPORT_C CMMFObjectContainer::CMMFObjectContainer()
+	{
+	iNextObjectHandle = KMMFObjectHandleFirstValid;
+	}
+
+/**
+Destructor.
+
+Deletes all objects owned by the container.
+
+@since  7.0s
+*/
+EXPORT_C CMMFObjectContainer::~CMMFObjectContainer()
+	{
+	iObjects.ResetAndDestroy();
+	iObjects.Close();
+	}
+
+/**
+Add an object to the container.
+
+Once the object has been added, its ownership is transferred to the container.
+
+@param  aObject
+        A reference to the object to be added to the container.
+
+@return	An error code indicating if the function call was successful. If the return code is not KErrNone, then
+		ownership of the object still remains with the caller.
+@since  7.0s
+*/
+EXPORT_C TInt CMMFObjectContainer::AddMMFObject(CMMFObject& aObject)
+	{
+	// Check the object isn't already added
+	if (aObject.Handle().DestinationHandle() != KMMFObjectHandleNull)
+		return KErrAlreadyExists;
+
+	TMMFMessageDestination newHandle(aObject.Handle().InterfaceId(), GenerateObjectHandle());
+	// Set the object's handle
+	aObject.SetHandle(newHandle);
+	// Append the object to the array
+	TInt error = iObjects.Append(&aObject);
+	// If error occurred, reset object handle to NULL
+	if (error)
+		{
+		TMMFMessageDestination evenNewerHandle(aObject.Handle().InterfaceId(), KMMFObjectHandleNull);
+		aObject.SetHandle(evenNewerHandle);
+		}
+	return error;
+	}
+
+/**
+Removes and destroys an object from the container.
+
+This method ensures that the object is no longer in the container, and that it gets deleted.
+Even if the object is not found in the container's array of objects, it will be deleted.
+
+@param  aObject
+        A reference to the object to be deleted.
+
+@since  7.0s
+*/
+EXPORT_C void CMMFObjectContainer::RemoveAndDestroyMMFObject(CMMFObject& aObject)
+	{
+	TInt positionOfObjectInArray;
+	TInt error = FindMMFObject(aObject, positionOfObjectInArray);
+	if (!error)
+		{
+		iObjects.Remove(positionOfObjectInArray);
+		}
+	//else, we don't care since we're just saying we'll make sure the object
+	//isn't in the array, and that it gets deleted.
+	delete (&aObject);
+	}
+
+/**
+Removes and destroys all objects from the container.
+
+@since	7.0s
+*/
+EXPORT_C void CMMFObjectContainer::DeleteAllObjects()
+	{
+	iObjects.ResetAndDestroy();
+	}
+
+/**
+Finds an object in the container using a handle.
+
+@param  aObjectHandle
+        The handle of the object to be located.
+@param  aObjectFound
+        A reference to a pointer to the object found in the container.
+
+@return An error code indicating if the function call was successful. KErrNone on success, otherwise
+        another of the system-wide error codes.
+@since	7.0s
+*/
+EXPORT_C TInt CMMFObjectContainer::FindMMFObject(const TMMFMessageDestination& aObjectHandle, CMMFObject*& aObjectFound)
+	{
+	// Need to find the appropriate object in the array of CMMFObjects
+	TInt error = KErrNotFound;
+	for (TInt i=0; i<iObjects.Count(); i++)
+		{
+		CMMFObject* obj = iObjects[i];
+		if (obj->Handle() == aObjectHandle)
+			{
+			error = KErrNone;
+			aObjectFound = obj;
+			break;
+			}
+		}
+	return error;
+	}
+
+const RPointerArray<CMMFObject>& CMMFObjectContainer::MMFObjects()
+	{
+	return iObjects;
+	}
+	
+TInt CMMFObjectContainer::FindMMFObject(const CMMFObject& aObject, TInt& aPositionInArray)
+	{
+	TInt error = KErrNotFound;
+	for (TInt i=0; i<iObjects.Count(); i++)
+		{
+		CMMFObject* obj = iObjects[i];
+		if (*obj == aObject)
+			{
+			error = KErrNone;
+			aPositionInArray = i;
+			break;
+			}
+		}
+	return error;
+	}
+
+TInt CMMFObjectContainer::GenerateObjectHandle()
+	{
+	return iNextObjectHandle++;
+	}
+
+
+CLogonMonitor::CLogonMonitor(MLogonMonitorObserver* aLogonMonitorObserver) 
+: CActive(EPriorityStandard)
+	{
+	iLogonMonitorObserver = aLogonMonitorObserver;
+	}
+	
+void CLogonMonitor::ConstructL()
+	{
+	if (CActiveScheduler::Current()==0)
+		{
+		iScheduler = new (ELeave) CActiveScheduler;
+		CActiveScheduler::Install(iScheduler);
+		}
+		
+	CActiveScheduler::Add(this);
+	}
+	
+CLogonMonitor* CLogonMonitor::NewL(MLogonMonitorObserver* aLogonMonitorObserver)
+	{
+	CLogonMonitor* self = new (ELeave) CLogonMonitor(aLogonMonitorObserver);
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	CleanupStack::Pop(self);
+	return self;
+	}
+
+CLogonMonitor::~CLogonMonitor()
+	{
+	Cancel();
+	
+	if (iScheduler)
+		{
+		CActiveScheduler::Install(NULL);
+		delete iScheduler;
+		}
+	}
+
+void CLogonMonitor::StartMonitoring(RThread& aThread)
+	{
+	ASSERT(!iThread);
+	
+	iThread = &aThread;
+	iThread->Logon(iStatus);
+	SetActive();
+	}
+
+void CLogonMonitor::RunL()
+	{
+	iServer.Close();
+	iLogonMonitorObserver->ThreadTerminated();
+	}
+
+void CLogonMonitor::DoCancel()
+	{
+	ASSERT(iThread);
+	
+	iThread->LogonCancel(iStatus);
+	iThread = NULL;
+	}
+
+RServer2& CLogonMonitor::Server()
+	{
+	return iServer;
+	}
+	
+CMMFControllerExtendedData::CMMFControllerExtendedData()
+	: CMMFObject(KUidMMFControllerExtendedDataHolder), iSourceSinkInitData(NULL)
+	{
+	iClientThreadId = 0;
+	iSecureDrmMode = EFalse;
+	}
+
+CMMFControllerExtendedData::~CMMFControllerExtendedData()
+	{
+	ResetSourceSinkInitData();
+	}
+	
+void CMMFControllerExtendedData::SetSourceSinkInitData(HBufC8* aSourceSinkInitData)
+	{
+	ResetSourceSinkInitData();
+	iSourceSinkInitData = aSourceSinkInitData;
+	}
+
+HBufC8* CMMFControllerExtendedData::SourceSinkInitData() const
+	{
+	return iSourceSinkInitData;
+	}
+
+void CMMFControllerExtendedData::ResetSourceSinkInitData()
+	{
+	if (iSourceSinkInitData)
+		{
+		delete iSourceSinkInitData;
+		iSourceSinkInitData = NULL;
+		}
+	}
+
+void CMMFControllerExtendedData::SetClientThreadId(TThreadId aClientThreadId)
+	{
+	iClientThreadId = aClientThreadId;
+	}
+
+TThreadId CMMFControllerExtendedData::ClientThreadId() const
+	{
+	return iClientThreadId;
+	}
+
+void CMMFControllerExtendedData::SetSecureDrmMode(TBool aSecureDrmMode)
+	{
+	iSecureDrmMode = aSecureDrmMode;
+	}
+
+TBool CMMFControllerExtendedData::SecureDrmMode() const
+	{
+	return iSecureDrmMode;
+	}
+
+void CMMFControllerExtendedData::HandleRequest(TMMFMessage& /*aMessage*/)
+	{
+	// This function is not suppose to be called.
+#ifdef _DEBUG
+	Panic(EPanicBadInvariant);
+#endif
+	}
+