installationservices/swi/source/swis/server/installserver.cpp
changeset 0 ba25891c3a9e
child 25 7333d7932ef7
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/installationservices/swi/source/swis/server/installserver.cpp	Thu Dec 17 08:51:10 2009 +0200
@@ -0,0 +1,486 @@
+/*
+* Copyright (c) 1997-2009 Nokia Corporation and/or its subsidiary(-ies).
+* All rights reserved.
+* This component and the accompanying materials are made available
+* under the terms of the License "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: 
+* SWIS implementation
+*
+*/
+
+
+/**
+ @file
+*/
+
+#include "installserver.h"
+#include "installclientserver.h"
+#include "installmachine.h"
+#include "uninstallmachine.h"
+#include "swispubsubdefs.h"
+#include "restoremachine.h"
+#include "log.h"
+#include "packageremover.h"
+
+#include <connect/sbdefs.h>
+#include <swi/pkgremover.h>
+
+namespace Swi
+{
+
+/**
+ * Local function to panic an offending client
+ * @internalTechnology
+ * @released
+ */
+static void PanicClient(const RMessagePtr2& aMessage,
+	TInstallServerPanic aPanic)
+	{
+	aMessage.Panic(KInstallServerName, aPanic);
+	}
+
+//
+// CInstallSession
+//
+
+// 2nd phase construction, called by the server framework
+void CInstallSession::CreateL()
+	{
+	Server().AddSession();
+
+#ifdef __WINSCW__
+	// For 2 minutes after initial boot, DLLs are not unloaded. If we are doing an
+	// install/uninstall/restore, we need to make sure any pending unloadeds are actioned,
+	// otherwise a previously loaded DLL could cause the rollback to fail on windows (on
+	// arm it is legal to delete a loaded DLL/EXE, whilst on windows it is not).
+	RLoader loader;
+	TInt r = loader.Connect();
+	if(r == KErrNone)
+		{
+		(void)loader.CancelLazyDllUnload();
+		loader.Close();
+		}
+#endif
+	}
+
+CInstallSession::~CInstallSession()
+	{
+	delete iMachine;
+	delete iRestoreMachine;
+	delete iRemover;
+	Server().ListRemoveInProgress(EFalse);
+	RProperty::Set(KUidSystemCategory, KUidSoftwareInstallKey, ESwisNone);
+	Server().DropSession();
+	}
+
+CInstallServer& CInstallSession::Server()
+	{
+	return *static_cast<CInstallServer*>(const_cast<CServer2*>(
+		CSession2::Server()));
+	}
+
+// Handle a client request. Leaving is handled by ServiceError() which reports 
+// the error code to the client
+void CInstallSession::ServiceL(const RMessage2& aMessage)
+	{
+	// Handle the cancel message first
+	if (aMessage.Function()==ECancel)
+		{
+		DEBUG_PRINTF(_L8("CInstallSession::ServiceL() cancel function called"));
+		// Set status as aborted
+		TInt property;
+		if (RProperty::Get(KUidSystemCategory, KUidSoftwareInstallKey, property) == KErrNone)
+			{
+			RProperty::Set(KUidSystemCategory, KUidSoftwareInstallKey, property | ESwisStatusAborted);
+			}	
+
+		if (iMachine)
+			{
+			iMachine->CancelInstallation();
+			}	
+		
+		aMessage.Complete(KErrNone);
+		return;
+		}
+	
+	TInt property = 0;
+	TInt err = RProperty::Get(KUidSystemCategory, conn::KUidBackupRestoreKey, property);
+
+	if (err != KErrNone && err != KErrNotFound)
+		{
+		User::Leave(err);
+		}
+	
+	if (iMachine != NULL)
+		{
+		DEBUG_PRINTF2(_L8("Install Server Message %d refused. Install/Uninstall in progress"), aMessage.Function());
+		aMessage.Complete(KErrInUse);
+		}
+
+	/*
+	 * We must return KErrInUse if:
+	 * 1) The Connect P&S property indicates we are doing a backup/restore
+	 * 2) We are not servicing that restore operation with this request
+	 * 3) A list/remove operation is in progress
+	 *
+	 */
+	else if ((iRemover != NULL) || Server().IsListRemoveInProgress())
+		{
+		// Remove operation in progress
+		DEBUG_PRINTF2(_L8("Install Server Message '%d' refused. List/Remove in progress"), aMessage.Function());
+		aMessage.Complete(KErrInUse);
+		}
+	else if (err != KErrNotFound && (property & (conn::KBURPartTypeMask^conn::EBURNormal)) 
+				&& aMessage.Function() != ERestore && !iRestoreMachine)
+		{
+		DEBUG_PRINTF2(_L8("Install Server Message '%d' refused. Backup/Restore in progress"), aMessage.Function());
+		aMessage.Complete(KErrInUse);
+		}
+	else
+		{
+		switch (aMessage.Function())
+			{
+			case EInstall:
+				{
+				DEBUG_PRINTF(_L8("CInstallSession::ServiceL() install function called"));
+				
+				err = RProperty::Set(KUidSystemCategory, KUidSoftwareInstallKey, ESwisInstall);
+				User::LeaveIfError(err);
+				
+				iMachine=CInstallMachine::NewL(aMessage);
+				User::LeaveIfError(iMachine->Start());
+				// The state machine will complete the client once the work 
+				// is done.
+				break;
+				}
+			#ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+			case EGetComponentInfo:
+				{
+				DEBUG_PRINTF(_L8("CInstallSession::ServiceL() get component info function called"));
+							
+				iMachine=CInstallMachine::NewL(aMessage, ETrue);
+				// Set the install machine to run on comp info collection mode.
+				User::LeaveIfError(iMachine->Start());
+				// The state machine will complete the client once the work 
+				// is done.
+				break;
+				}			
+			#endif
+			case EUninstall:
+				{
+				DEBUG_PRINTF(_L8("CInstallSession::ServiceL() uninstall function called"));
+				
+				err = RProperty::Set(KUidSystemCategory, KUidSoftwareInstallKey, ESwisUninstall);
+				User::LeaveIfError(err);
+
+				iMachine=CUninstallMachine::NewL(aMessage);
+				User::LeaveIfError(iMachine->Start());
+	
+				// The state machine will complete the client once the work 
+				// is done.
+				break;
+				}
+				
+			case ERestore:
+				{
+				
+				DEBUG_PRINTF(_L8("CInstallSession::ServiceL() restore function called"));
+				
+				err = RProperty::Set(KUidSystemCategory, KUidSoftwareInstallKey, ESwisRestore);
+				User::LeaveIfError(err);
+				
+				if (iRestoreMachine && !iRestoreMachine->IsComplete())
+					{
+					
+					aMessage.Complete(KErrInUse);
+					
+					}
+					
+				if (iRestoreMachine)
+					{
+					
+					delete iRestoreMachine;
+					iRestoreMachine = NULL;
+					
+					}
+				
+				iRestoreMachine = CRestoreMachine::NewL(aMessage);
+				break;
+				
+				}
+			case ERestoreFile:
+				{
+				
+				DEBUG_PRINTF(_L8("CInstallSession::ServiceL() restore file function called"));
+				
+				if (iRestoreMachine == NULL)
+					{
+					
+					// Should never be reached
+					aMessage.Panic(KInstallServerName, KErrNotReady);
+					
+					}
+				else
+					{
+					
+					iRestoreMachine->ServiceFileRequestL(aMessage);
+					
+					}
+				break;
+				
+				}
+			case ERestoreCommit:
+				{
+				
+				DEBUG_PRINTF(_L8("CInstallSession::ServiceL() commit function called"));
+				
+				if (iRestoreMachine == NULL)
+					{
+					
+					// Should never be reached
+					aMessage.Panic(KInstallServerName, KErrNotReady);
+					
+					}
+				else
+					{
+					
+					iRestoreMachine->ServiceCommitRequestL(aMessage);
+					
+					}
+				break;
+				
+				}
+			case EListUnInstalledPkgs:
+				{
+				Server().ListRemoveInProgress(ETrue);
+
+				iRemover = CPackageRemover::NewL(aMessage);
+				iRemover->ListL();
+				// The state will complete the client once the work 
+				// is done.
+				break;	
+				}
+			case ERemoveUnInstalledPkg:
+				{
+				Server().ListRemoveInProgress(ETrue);
+
+				iRemover = CPackageRemover::NewL(aMessage);
+				iRemover->RemoveL();
+				// The state will complete the client once the work 
+				// is done.
+				break;	
+				}
+			default:
+				{
+				DEBUG_PRINTF2(_L8("CInstallSession::ServiceL() unknown function called (%d)"), aMessage.Function());
+				PanicClient(aMessage, Swi::EPanicInstallServerIllegalFunction);
+				break;
+				}
+			}
+		}
+	}
+
+// Handle an error from ServiceL(). A bad descriptor error implies a badly 
+// programmed client, so panic it. Otherwise use the default handling (report 
+// the error to the client).
+void CInstallSession::ServiceError(const RMessage2& aMessage, TInt aError)
+	{
+	
+	// set the pubsub flag to aborted status
+	TInt property = 0;
+	TInt err = RProperty::Get(KUidSystemCategory, KUidSoftwareInstallKey, property);
+	
+	if (err == KErrNone)
+		{
+		RProperty::Set(KUidSystemCategory, KUidSoftwareInstallKey, property | ESwisStatusAborted);
+		}
+	
+	if (aError==KErrBadDescriptor)
+		PanicClient(aMessage, EPanicInstallServerBadDescriptor);
+	CSession2::ServiceError(aMessage, aError);
+	}
+
+//
+// CInstallServerShutdown
+//
+
+inline CInstallServerShutdown::CInstallServerShutdown()
+:	CTimer(-1)
+	{
+	CActiveScheduler::Add(this);
+	}
+
+CInstallServerShutdown::~CInstallServerShutdown()
+	{
+	Cancel();
+	}
+
+inline void CInstallServerShutdown::ConstructL()
+	{
+	CTimer::ConstructL();
+	}
+
+inline void CInstallServerShutdown::Start()
+	{
+	After(KShutdownDelay);
+	}
+
+// Initiate server exit when the timer expires
+void CInstallServerShutdown::RunL()
+	{
+	CActiveScheduler::Stop();
+	}
+
+//
+// CInstallServer
+//
+
+// All functions require TrustedUI capability
+const TInt CInstallServer::iRanges[iRangeCount] = 
+                {
+                0 // All connect attempts
+                };
+
+const TUint8 CInstallServer::iElementsIndex[iRangeCount] = 
+                {
+                CPolicyServer::ECustomCheck // Custom check polices for TrustedUI or SID from connect.
+                };
+
+const CPolicyServer::TPolicy CInstallServer::iPolicy =
+                {
+                CPolicyServer::ECustomCheck,					// specifies all connect attempts
+                iRangeCount,
+                iRanges,
+                iElementsIndex,
+                NULL,
+                };
+
+CInstallServer* CInstallServer::NewLC()
+	{
+	CInstallServer* self = new(ELeave) CInstallServer();
+	CleanupStack::PushL(self);
+	self->ConstructL();
+	return self;
+	}
+
+CInstallServer::~CInstallServer()
+	{
+	DEBUG_PRINTF(_L8("Install Server Shutdown"));
+	CSecurityPolicy::ReleaseResource();
+	delete iShutdown;
+	iShutdown = NULL; //required in case the server dies before the session
+	}
+
+// This server does not offer sharable sessions
+CInstallServer::CInstallServer()
+: 	CPolicyServer(EPriorityMore, iPolicy, EUnsharableSessions),
+	iListRemoveInProgress(EFalse)
+	{
+	}
+
+// Ensure the timer and server objects are running
+void CInstallServer::ConstructL()
+	{
+	DEBUG_PRINTF(_L8("Install Server Created"));
+	StartL(KInstallServerName);
+	iShutdown = new(ELeave) CInstallServerShutdown;
+	iShutdown->ConstructL();
+	// Ensure that the server still exits even if the 1st client fails to
+	// connect
+	iShutdown->Start();
+	
+#ifdef SYMBIAN_UNIVERSAL_INSTALL_FRAMEWORK
+	// Create the property used to publish SWI Progress Bar Value. Since this property is not needed
+	// if the SWI component doesn't exist, it is created here.
+	TInt err = RProperty::Define(KUidInstallServerCategory, KUidSwiProgressBarValueKey, RProperty::EInt);
+	if (err != KErrNone && err != KErrAlreadyExists)
+		{
+		DEBUG_PRINTF2(_L8("Progress Bar Property couldn't be created. Error=%d."), err);
+		User::Leave(err);
+		}
+#endif	
+	}
+	
+	
+CPolicyServer::TCustomResult CInstallServer::CustomSecurityCheckL(const RMessage2& aMsg, 
+	TInt& /*aAction*/, TSecurityInfo& aMissing)
+	{
+	
+	_LIT_SECURE_ID(secureBackupClientSID, 0x10202D56);
+	
+	if (aMsg.SecureId().iId == secureBackupClientSID.iId)
+		{
+		return CPolicyServer::EPass;
+		}
+	else if (aMsg.HasCapability(ECapabilityTrustedUI, 
+		__PLATSEC_DIAGNOSTIC_STRING("CInstallServer::CustomSecurityTest client process does not have Trusted UI Capability")))
+		{
+		// Check additional capability for listing and removing "uninstalled" packages
+		if ((aMsg.Function() == EListUnInstalledPkgs) && !aMsg.HasCapability(ECapabilityReadDeviceData, 
+			__PLATSEC_DIAGNOSTIC_STRING("CInstallServer::CustomSecurityTest client process does not have ReadDeviceData Capability")))
+			{
+			aMissing.iCaps.Set(ECapabilityReadDeviceData);
+			return CPolicyServer::EFail;
+			}
+
+		if ((aMsg.Function() == ERemoveUnInstalledPkg) && !aMsg.HasCapability(ECapabilityWriteDeviceData, 
+			__PLATSEC_DIAGNOSTIC_STRING("CInstallServer::CustomSecurityTest client process does not have WriteDeviceData Capability")))
+			{
+			aMissing.iCaps.Set(ECapabilityWriteDeviceData);
+			return CPolicyServer::EFail;
+			}
+
+		return CPolicyServer::EPass;
+		}
+	else
+		{
+		// Missing connect SID or TrustedUI capability, cannot complete connection
+		aMissing.iCaps.Set(ECapabilityTrustedUI);
+		return CPolicyServer::EFail;
+		}
+	}
+
+CSession2* CInstallServer::NewSessionL(const TVersion& aClientVersion, 
+	const RMessage2&) const
+	{
+ 
+	// Currently there is only one version of the InstallServer		
+	const TVersion serverVersion(KInstallServerVersionMajor,KInstallServerVersionMinor,KInstallServerVersionBuild);  
+
+	// Check that the version of the server requested is not greater than 
+	// that available. 	
+	if (!User::QueryVersionSupported(serverVersion, aClientVersion))
+		{
+		User::Leave(KErrNotSupported);
+		}
+		
+	return new(ELeave) CInstallSession();	
+	}
+
+void CInstallServer::AddSession()
+	{
+	++iSessionCount;
+	DEBUG_PRINTF2(_L8("Install Server Session Created (%d sessions active)"), iSessionCount);
+	iShutdown->Cancel();
+	}
+
+void CInstallServer::DropSession()
+	{
+	// if last session is dropped and server still alive start shutdown timer
+	if (--iSessionCount==0 && iShutdown)
+		{
+		iShutdown->Start();
+		DEBUG_PRINTF(_L8("Install Server Starting Shutdown Timer"));
+		}
+	DEBUG_PRINTF2(_L8("Install Server Session Destroyed (%d sessions active)"), iSessionCount);
+	}
+
+} // namespace Swi