sl@0: // Copyright (c) 2006-2009 Nokia Corporation and/or its subsidiary(-ies).
sl@0: // All rights reserved.
sl@0: // This component and the accompanying materials are made available
sl@0: // under the terms of "Eclipse Public License v1.0"
sl@0: // which accompanies this distribution, and is available
sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html".
sl@0: //
sl@0: // Initial Contributors:
sl@0: // Nokia Corporation - initial contribution.
sl@0: //
sl@0: // Contributors:
sl@0: //
sl@0: // Description:
sl@0: //
sl@0: 
sl@0: #include <e32test.h>
sl@0: #include <ecom/ecom.h>
sl@0: #include "Interface.h" // ECOM CExampleInterface class
sl@0: #include "exampleNine.h" // CRoguePlugin class
sl@0: 
sl@0: 
sl@0: //Test utils for copying plugin to C
sl@0: #include "EcomTestUtils.h"
sl@0: 
sl@0: _LIT(KTestTitle, "DEF094656 Rogue plugin should not override build-in");
sl@0: 
sl@0: LOCAL_D RTest TheTest(_L("Rogue plugin with duplicated Impl. UID"));
sl@0: 
sl@0: LOCAL_D TBool correctTypeCastPassed = EFalse;
sl@0: 
sl@0: _LIT(KRoguePluginDllOnZ,	"Z:\\RAMOnly\\exampleNine.dll");
sl@0: _LIT(KRoguePluginDllOnC,	"C:\\sys\\bin\\exampleNine.dll");
sl@0: _LIT(KRoguePluginRscOnZ,	"Z:\\RAMOnly\\exampleNine.rsc");
sl@0: _LIT(KRoguePluginRscOnC,	"C:\\resource\\plugins\\exampleNine.rsc");
sl@0: 
sl@0: /** Copy the rogue plugin to C: drive
sl@0: */
sl@0: LOCAL_C void CopyPluginsL()
sl@0:     {
sl@0: 	// Copy the dlls and .rsc files on to RAM
sl@0: 	EComTestUtils::FileManCopyFileL(KRoguePluginDllOnZ, KRoguePluginDllOnC);
sl@0: 	EComTestUtils::FileManCopyFileL(KRoguePluginRscOnZ, KRoguePluginRscOnC);
sl@0: 	// Pause in case ECOM server is already up and running and needs
sl@0: 	// time to activate the scanning timer active object.
sl@0: 	User::After(3000000);
sl@0: 	}
sl@0: 
sl@0: /** Remove resource file and dll copied to C: drive
sl@0: */
sl@0: LOCAL_C void DeleteTestPlugin()
sl@0: 	{
sl@0: 	TRAPD(ignoreErr, EComTestUtils::FileManDeleteFileL(KRoguePluginRscOnC));
sl@0: 	TRAP(ignoreErr, EComTestUtils::RLoaderDeleteFileL(KRoguePluginDllOnC));
sl@0: 	}
sl@0: 
sl@0: /**
sl@0: Test rogue plugin trying to override a ROM based plugin by
sl@0: duplicating the legitimate DLL's implementation UID (different
sl@0: interface UID so that ECOM not treat it as an update).
sl@0: 
sl@0: @SYMTestCaseID			SYSLIB-ECOM-CIT-3161
sl@0: @SYMTestCaseDesc	    Copy a rogue plugin to C drive. This plugin duplicates the
sl@0: 						implementation UID of a built-in dll. Test if the rogue
sl@0: 						plugin will over shadow the built-in dll.
sl@0: @SYMTestPriority		High
sl@0: @SYMTestActions			1. copy the rsc and dll of the rogue plugin to C:
sl@0: 						2. Use the CreateImplementation API which does not specify
sl@0: 						   the i/f UID to instantiate the built-in implementation.
sl@0: 						   Test the instance works normally.
sl@0: 						3. Repeat 2 but instantiate the pointer as the rogue plugin
sl@0: 						   class. Pass NULL as the initialising param in the call
sl@0: 						   to CreateImplementationL. Because the actual plugin returned by
sl@0: 						   ECOM needs this initParam, KERN-EXEC 3 panic occurs.
sl@0: @SYMTestExpectedResults	The test must not fail.
sl@0: @SYMDEF					DEF094656
sl@0: */
sl@0: LOCAL_C void DEF094656_TestCaseL()
sl@0: 	{
sl@0: 	// DuplicateImplUidTestL SYSLIB-ECOM-CT-3157 is similar to this testcase.
sl@0: 	// CT-3157 tests higher driver letter > lower driver letter,
sl@0: 	// and lower i/f UID > higher i/f UID.
sl@0: 
sl@0: 	// Note that this function is expected to panic. Hence not bother
sl@0: 	// with __UHEAP_MARK.
sl@0: 
sl@0: 	//Check if the rogue plugin is in the registry.
sl@0: 	TheTest.Next(_L(" @SYMTestCaseID:SYSLIB-ECOM-CIT-3161 "));
sl@0: 	RImplInfoPtrArray ifArray;
sl@0: 	REComSession::ListImplementationsL(KRogueInterfaceUid, ifArray);
sl@0: 
sl@0: 	TInt count = ifArray.Count();
sl@0: 	TheTest.Printf(_L("Found %d implementations of I/f 0x%X"), count, KRogueInterfaceUid.iUid);
sl@0: 
sl@0: 	TheTest(count == 1);
sl@0: 	TheTest(KRogueImplUid == ifArray[0]->ImplementationUid());
sl@0: 
sl@0: 	ifArray.ResetAndDestroy();
sl@0: 
sl@0: 	TUid dtor_key;
sl@0: 	// Initialisation parameter needed by CImplementationClassOne
sl@0: 	CExampleInterface::TExampleInterfaceInitParams initParams;
sl@0: 	initParams.integer		= 0;
sl@0: 	initParams.descriptor	= NULL;
sl@0: 
sl@0: 	// First test creating the correct class.
sl@0: 	CExampleInterface* correctDll = reinterpret_cast<CExampleInterface*>(
sl@0: 		REComSession::CreateImplementationL(KRogueImplUid,
sl@0: 											dtor_key,
sl@0: 											&initParams) );
sl@0: 	TheTest(correctDll != NULL);
sl@0: 
sl@0: 	TUid testUid = correctDll->ImplId();
sl@0: 	// the example plugins should return the value 10009DC3.
sl@0: 	TheTest(testUid == KRogueImplUid);
sl@0: 
sl@0: 	REComSession::DestroyedImplementation(dtor_key);
sl@0: 	delete correctDll;
sl@0: 
sl@0: 	// Indicate to thread creator that first stage test passed.
sl@0: 	correctTypeCastPassed = ETrue;
sl@0: 
sl@0: 	// This create should crash because the plugin returned by
sl@0: 	// ECOM is really CImplementationClassOne which needs a properly
sl@0: 	// constructed initParam.
sl@0: 	CRoguePlugin* wrongDll = reinterpret_cast<CRoguePlugin*>(
sl@0: 		REComSession::CreateImplementationL(KRogueImplUid,
sl@0: 											dtor_key,
sl@0: 											NULL) );
sl@0: 
sl@0: 	// If gets here then someone has changed CImplementationClassOne::NewL
sl@0: 	// or 10009DC3 has been updated by another implementation.
sl@0: 	if (wrongDll)
sl@0: 		{
sl@0: 		REComSession::DestroyedImplementation(dtor_key);
sl@0: 		delete wrongDll;
sl@0: 		}
sl@0: 
sl@0: 	REComSession::FinalClose();
sl@0: 
sl@0: 	TheTest(EFalse);
sl@0: 	}
sl@0: 
sl@0: LOCAL_C void ThreadMainL()
sl@0: 	{
sl@0: 	CConsoleBase* newConsole = Console::NewL(KTestTitle,
sl@0: 		TSize(KConsFullScreen, KConsFullScreen));
sl@0: 
sl@0: 	// Thread creator needs to save the original console because this
sl@0: 	// thread is expected to crash, hence cannot cleanup.
sl@0: 	TheTest.SetConsole(newConsole);
sl@0: 	DEF094656_TestCaseL();
sl@0: 	TheTest.SetConsole(NULL);
sl@0: 
sl@0: 	delete newConsole;
sl@0: 	}
sl@0: 
sl@0: LOCAL_C TInt ThreadFunc(TAny*)
sl@0: 	{
sl@0: 	__UHEAP_MARK;
sl@0: 	CTrapCleanup* threadcleanup = CTrapCleanup::New();
sl@0: 	TRAPD(err, ThreadMainL());
sl@0: 	delete threadcleanup;
sl@0: 	__UHEAP_MARKEND;
sl@0: 	return err;
sl@0: 	}
sl@0: 
sl@0: LOCAL_C void RunTestThreadL()
sl@0: 	{
sl@0: 	__UHEAP_MARK;
sl@0: 
sl@0: 	CopyPluginsL();
sl@0: 
sl@0: 	_LIT(KThreadName, "RoguePluginTest");
sl@0: 
sl@0: 	TBool jit = User::JustInTime();
sl@0: 	User::SetJustInTime(EFalse);
sl@0: 
sl@0: 	TheTest.Start(KTestTitle);
sl@0: 
sl@0: 	// Save the console because the created thread must use its own
sl@0: 	// console.
sl@0: 	CConsoleBase* savedConsole = TheTest.Console();
sl@0: 
sl@0: 	RThread tt;
sl@0: 	TInt err = tt.Create(KThreadName, &ThreadFunc, KDefaultStackSize,
sl@0: 		KMinHeapSize, 0x100000, 0);
sl@0: 	User::LeaveIfError(err);
sl@0: 
sl@0: 	TRequestStatus status;
sl@0: 	tt.Logon(status);
sl@0: 	tt.Resume();
sl@0: 
sl@0: 	User::WaitForRequest(status);
sl@0: 
sl@0: 	// restore console
sl@0: 	TheTest.SetConsole(savedConsole);
sl@0: 
sl@0: 	TExitCategoryName exitcategory = tt.ExitCategory();
sl@0: 	TExitType exittype = tt.ExitType();
sl@0: 	TInt exitReason = tt.ExitReason();
sl@0: 	tt.Close();
sl@0: 
sl@0: 	TheTest.Printf(_L("Thread exit type %d, reason %d, category %S"), exittype, exitReason, &exitcategory);
sl@0: 
sl@0: 	User::SetJustInTime(jit);
sl@0: 	DeleteTestPlugin();
sl@0: 
sl@0: 	// Check if tt thread passes this checkpoint
sl@0: 	TheTest(correctTypeCastPassed);
sl@0: 
sl@0: 	// Check if tt thread die of KERN-EXEC.
sl@0: 	_LIT(KKernExec, "KERN-EXEC");
sl@0: 	TheTest(exitcategory.CompareF(KKernExec) == 0);
sl@0: 
sl@0: 	TheTest.End();
sl@0: 	TheTest.Close();
sl@0: 
sl@0: 	__UHEAP_MARKEND;
sl@0: 	}
sl@0: 
sl@0: GLDEF_C TInt E32Main()
sl@0: 	{
sl@0: 	__UHEAP_MARK;
sl@0: 
sl@0: 	CTrapCleanup* cleanup = CTrapCleanup::New();
sl@0: 	CActiveScheduler* scheduler = new(ELeave)CActiveScheduler;
sl@0: 	CActiveScheduler::Install(scheduler);
sl@0: 
sl@0: 	TRAP_IGNORE( RunTestThreadL() );
sl@0: 
sl@0: 	delete scheduler;
sl@0: 	delete cleanup;
sl@0: 
sl@0: 	__UHEAP_MARKEND;
sl@0: 	return KErrNone;
sl@0: 	}