kerneltest/f32test/loader/security/t_ldrcheck.cpp
author Tom Cosgrove <tom.cosgrove@nokia.com>
Fri, 28 May 2010 16:29:07 +0100
changeset 30 8aab599e3476
parent 0 a41df078684a
child 41 0ffb4e86fcc9
permissions -rw-r--r--
Fix for bug 2283 (RVCT 4.0 support is missing from PDK 3.0.h) Have multiple extension sections in the bld.inf, one for each version of the compiler. The RVCT version building the tools will build the runtime libraries for its version, but make sure we extract all the other versions from zip archives. Also add the archive for RVCT4.

// Copyright (c) 1999-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:
// f32test\loader\t_ldrcheck.cpp
// 
//


#include "dlltree.h"
#include <e32uid.h>
#include <hal.h>
#include <e32wins.h>
#include <e32svr.h>
#include <e32test.h>
#include <f32file.h>
#include <f32dbg.h>
#include <f32image.h>
#include "t_hash.h"

#if defined (WIN32) && !defined (__X86GCC__)
#include <emulator.h>
#include <stdlib.h>
#endif


RTest test(_L("T_LDRCheck"));
RFs TheFs;
GLDEF_D TChar gDriveToTest;


/**
    Copy modules from z:\\sys\\bin to c:\\sys\\bin
*/
void CopyModules()
	{
	test.Next(_L("Copy Modules from ROM to disk"));

	TInt r;
	TTime modtime;

	r=TheFs.MkDirAll(KSystemLibs);
	test(r==KErrNone || r==KErrAlreadyExists);

	CFileMan* fileMan=NULL;
	TRAP(r,fileMan=CFileMan::NewL(TheFs));
	test(r==KErrNone);

	TBuf<40> dllfilenames;
	TBuf<40> dlldestination;
	
	for(TInt i=0;i<14;i++)
		{
		dllfilenames=KDllfilename;
		dllfilenames.AppendNum(i);
		dllfilenames +=KDllExt;
		dlldestination=KNewDllName;
		dlldestination.AppendNum(i);
		dlldestination+=KDllExt;
#ifndef WIN32
		r=fileMan->Copy(dllfilenames,dlldestination, 0);
		test(r==KErrNone || r==KErrAlreadyExists);

		r=fileMan->Attribs(dlldestination,0, KEntryAttReadOnly,modtime,0);
		test(r==KErrNone);
#endif
		}

	TBuf<40> exefilenames;
	TBuf<40> exedestination;

	for(TInt j=14;j<16;j++)
		{
		exefilenames=KExefilename;
		exefilenames.AppendNum(j);
		exefilenames +=KExeExt;
		exedestination=KNewExeName;
		exedestination.AppendNum(j);
		exedestination+=KExeExt;
#ifndef WIN32
		r=fileMan->Copy(exefilenames,exedestination,0);
		test(r==KErrNone || r==KErrAlreadyExists);

		r=fileMan->Attribs(exedestination, 0, KEntryAttReadOnly, modtime, 0);
		test(r==KErrNone);
#endif
		}
	delete fileMan;
	}



#ifndef WIN32
/*
void ModifyModuleCapabilties(TUint32 aNewCap, TInt aModuleNumber)
//
//	Assign new capabilties to a module using raw disk write
//
	{
//	test.Next(_L("Modify Module Capabilities"));
	
	test(aModuleNumber<=15 && aModuleNumber>=0);	
	
	TBuf<40> dlldestination;
	RFile modFile;
	TInt r=0;

	SCapabilitySet caps;
	memset(&caps,0,sizeof(caps));
	caps[0] = aNewCap;
	TPtrC8 theNewCaps((TUint8*)(&caps),sizeof(caps));

	if(aModuleNumber < 14)
		{
		dlldestination=KNewDllName;
		dlldestination.AppendNum(aModuleNumber);
		dlldestination+=KDllExt;
		}
	else
		{
		dlldestination=KNewExeName;
		dlldestination.AppendNum(aModuleNumber);
		dlldestination+=KExeExt;
		}

	r=modFile.Open(TheFs, dlldestination, EFileWrite);
	test(r==KErrNone);
	r=modFile.Write(_FOFF(E32ImageHeaderV,iS.iCaps), theNewCaps,4);
	test(r==KErrNone);
	modFile.Close();	

	RLibrary lib;
	TCapabilitySet theCaps;
	RLibrary::TInfoBuf info;

	lib.GetInfo(dlldestination, info);
	theCaps=info().iSecurityInfo.iCaps;

	lib.Close();
	test(theCaps==aNewCap);

	}
*/
#else
/*
void ModifyModuleCapabilties(TUint32 aNewCap, TInt aModuleNumber)
//
//	Wins version (poking values is not quite so simple
//
	{
//	test.Next(_L("Modify Module Capabilities"));
	test(aModuleNumber<=15 && aModuleNumber>=0);	
	
	TBuf<40> dlldestination;
	TInt r=0;

	TPtrC8 theNewCaps((TUint8*)(&aNewCap),sizeof(TUint32));

	
	if(aModuleNumber < 14)
		{
		dlldestination=KNewDllName;
		dlldestination.AppendNum(aModuleNumber);
		dlldestination+=KDllExt;
		}
	else
		{
		dlldestination=KNewExeName;
		dlldestination.AppendNum(aModuleNumber);
		dlldestination+=KExeExt;
		}

	RLibrary lib2;
	TCapabilitySet theCaps2;
	RLibrary::TInfoBuf info;

	lib2.GetInfo(dlldestination, info);
	theCaps2=info().iSecurityInfo.iCaps;

	lib2.Close();
			
	TBuf<MAX_PATH> fileName;
	r = MapEmulatedFileName(fileName, dlldestination);

	HANDLE hFile=Emulator::CreateFile((LPCTSTR)fileName.PtrZ(),GENERIC_READ|GENERIC_WRITE,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_EXISTING,0,NULL);
	if (hFile==INVALID_HANDLE_VALUE)
		return;
	DWORD ret;
	TBuf8<sizeof(TCheckedUid)> checkedUidBuf;
	checkedUidBuf.SetLength(sizeof(TCheckedUid));
	ReadFile(hFile,&checkedUidBuf[0],sizeof(TCheckedUid),&ret,NULL);
	if (ret!=sizeof(TCheckedUid))
		goto close;

		//Look at PE file for UID section
		{
		const TInt KPeHeaderAddrAddr=0x3c;
		const TInt KPeHeaderAddrSize=0x01;
		const TInt KNumberOfSectionsOffset=0x06;
		const TInt KNumberOfSectionsSize=0x02;
		const TInt KSectionTableOffset=0xf8;
		const TInt KSectionHeaderSize=0x28;
		const TInt KSectionNameLength=0x08;
		const TInt KPtrToRawDataOffset=0x14;
		const TInt KPtrToRawDataSize=0x04;
		const TText8 peText[4]={'P','E',0,0};
		const TText8 uidText[8]={'.','S','Y','M','B','I','A','N'};
		
	//Read address of start of PE header
		if (SetFilePointer(hFile,KPeHeaderAddrAddr,0,FILE_BEGIN)==0xFFFFFFFF)
			goto close;
		TInt peAddr=0;
		ReadFile(hFile,&peAddr,KPeHeaderAddrSize,&ret,NULL);
		if (ret!=KPeHeaderAddrSize)
			goto close;
		
	//Check it really is the start of PE header
		if (SetFilePointer(hFile,peAddr,0,FILE_BEGIN)==0xFFFFFFFF)
			goto close;
		TText8 text[4];
		ReadFile(hFile,text,4,&ret,NULL);
		if (*(TInt32*)text!=*(TInt32*)peText)
			goto close;
		
	//Read number of sections
		if (SetFilePointer(hFile,peAddr+KNumberOfSectionsOffset,0,FILE_BEGIN)==0xFFFFFFFF)
			goto close;
		TInt sections=0;
		ReadFile(hFile,&sections,KNumberOfSectionsSize,&ret,NULL);
		if (ret!=KNumberOfSectionsSize)
			goto close;

	//Go through section headers looking for UID section
		if (SetFilePointer(hFile,peAddr+KSectionTableOffset,0,FILE_BEGIN)==0xFFFFFFFF)
			goto close;
		TInt i=0;
		for(;i<sections;i++)
			{
			TText8 name[KSectionNameLength];
			ReadFile(hFile,name,KSectionNameLength,&ret,NULL);
			if (ret!=KSectionNameLength)
				goto close;
			if (*(TInt64*)name==*(TInt64*)uidText)
				break;
			if (SetFilePointer(hFile,KSectionHeaderSize-KSectionNameLength,0,FILE_CURRENT)==0xFFFFFFFF)
				goto close;
			}
		if (i==sections)
			goto close;

	//Read RVA/Offset
		if (SetFilePointer(hFile,KPtrToRawDataOffset-KSectionNameLength,0,FILE_CURRENT)==0xFFFFFFFF)
			goto close;
		TInt uidOffset;
		ReadFile(hFile,&uidOffset,KPtrToRawDataSize,&ret,NULL);
		if (ret!=KPtrToRawDataSize)
			goto close;

	//SYMBIAN Header
		if (SetFilePointer(hFile,uidOffset,0,FILE_BEGIN)==0xFFFFFFFF)
			goto close;

		TEmulatorImageHeader header;

		ReadFile(hFile,&header,sizeof(header),&ret,NULL);
		if (ret!=sizeof(header))
			goto close;
		
// DON'T modify, for now		header.iS.iCaps[0] = aNewCap;		//assign new caps to binary


		if (SetFilePointer(hFile,uidOffset,0,FILE_BEGIN)==0xFFFFFFFF)
			goto close;

		BOOL b = WriteFile(hFile,&header,sizeof(header),&ret,NULL);
		if (b==FALSE)
			goto close;
		CloseHandle(hFile);
		
		RLibrary lib;
		TCapabilitySet theCaps;
		RLibrary::TInfoBuf info;
		lib.GetInfo(dlldestination, info);
		theCaps=info().iSecurityInfo.iCaps;

		lib.Close();

		SCapabilitySet& realCaps = (SCapabilitySet&) theCaps;
// broke!		test(realCaps[0] == aNewCap && realCaps[1] == 0);
		return;
		}

//Close file
close:
	CloseHandle(hFile);
	test(0);
	} 
*/
#endif

/*
void TestGetCapability()
//
//	test RLibrary::GetCapabilites
//
	{
	RLibrary library;
	TInt r;
	test.Next(_L("Test RLibrary::GetCapabilities()"));

// These tests check the error code returned by the (deprecated) GetCapability method
// and now serve no useful purpose
//	TCapability theCaps;
//	r=library.GetCapability(theCaps,_L("Z:\\Mongolia"));
//	test(r==KErrNotFound);
//	r=library.GetCapability(theCaps,_L("C:\\Malawi.Fip"));
//	test(r==KErrNotFound);

	TCapabilitySet theCaps;
	RLibrary::TInfoBuf info;
#if defined __WINS__

	


	test.Next(_L("Get caps of an existing library"));
//	r=lib1.GetCapability(theCaps,_L("ECONS"));
//	test(r==KErrNone);
	RLibrary lib1;
//	r=lib1.GetInfo(_L("ECONS"), info);
	r=lib1.GetInfo(_L("Z:\\SYS\\BIN\\ECONS"), info);
	test(r==KErrNone);
	theCaps=info().iSecurityInfo.iCaps;

	test.Next(_L("And again"));
//	r=lib2.GetCapability(theCaps,_L("ECONS.DLL"));
//	test(r==KErrNone);
	RLibrary lib2;
	lib2.GetInfo(_L("ECONS.DLL"), info);
	theCaps=info().iSecurityInfo.iCaps;
	
#else
// This test checks for the correct return value from the (deprecated)
// method GetCapability, and now serves no useful purpose??
//	r=library.GetCapability(theCaps,_L("Malawi.Fip"));
//	test(r==KErrNotSupported);
	library.GetInfo(_L("Malawi.Fip"), info);
	theCaps=info().iSecurityInfo.iCaps;

//TODO uncomment when in ssytem bin
//	RLibrary lib1;
//	test.Next(_L("Get caps of an existing library"));
//	r=lib1.GetCapability(theCaps,_L("ECONS"));
//	r=lib1.GetCapability(theCaps,_L("Z:\\Sys\\Bin\\ECONS"));
//	RDebug::Print(_L("r====%d"),r);
//	test(r==KErrNone);
	
//	RLibrary lib2;
//	test.Next(_L("And again"));
//	r=lib2.GetCapability(theCaps,_L("Z:\\Sys\\Bin\\ECONS.DLL"));
//	r=lib2.GetCapability(theCaps,_L("ECONS.DLL"));
//	test(r==KErrNone);
	
	RLibrary lib3;
	test.Next(_L("And again, but searching"));
	r=lib3.GetCapability(theCaps,_L("ECONS.DLL"));
	test(r==KErrNotSupported);
	lib3.Close();
	
#endif

	test.Next(_L("Search through DLLs from t_ldrcheck"));

	// Not sure of the benefit of this test ??

	TBuf<40> dllfilenames;
	RLibrary tlib;
//	TCapability deecaps;
	TCapabilitySet deecaps;
	for(TInt i=0;i<13;i++)
		{
		dllfilenames=KDllfilename;
		dllfilenames.AppendNum(i);
		dllfilenames +=KDllExt;
//		r=tlib.GetCapability(deecaps,dllfilenames);		
		tlib.GetInfo(dllfilenames, info);
		theCaps=info().iSecurityInfo.iCaps;
		}

	test.Next(_L("Close()"));
	tlib.Close();
	library.Close();
//	lib1.Close();
//	lib2.Close();
	}
*/

TInt LoadExe(TInt aModuleNum,  RProcess& aProcess)
//
//	Load executable
//
	{
	TFileName fn;
//#ifndef WIN32
//	fn =KSystemLibs();
//#endif
	TBuf<16> cmd;
	fn += MODULE_FILENAME(aModuleNum);
	TInt r=aProcess.Create(fn, cmd);
	return r;
	}


void TestLoad(TInt aSequence)
//
// Test doing the loads using sequence number to get the results
//
	{
	test.Next(_L("Test all single EXE/DLL combinations\n"));
	TInt r=0;
	test.Next(_L("New EXE"));
	RProcess p;

	r=LoadExe(14,p);
	test.Printf(_L("LoadExe(14)->%d, Expected %d, seq %d \n"),r,ModuleResultsA[aSequence], aSequence);
	test(r==ModuleResultsA[aSequence]);
	if (r==KErrNone)
		p.Terminate(0);
	p.Close();

	r=LoadExe(15,p);
	test.Printf(_L("LoadExe(15)->%d, seq %d\n"),r,aSequence);
	test(r==ModuleResultsA[aSequence]);
	if (r==KErrNone)
		p.Terminate(0);
	p.Close();
	}

/*
void TestLoadLibrary()
//
//	test using load library to load dlls with out rom time dependancies
//
	{
	test.Next(_L("Test loading libraries fromn this exe"));
	
	RLibrary lib;
	TInt r=0;
	//I want to load 6 7 and 11 as these	are of most interest

	for(TInt i=0;i<KTestCases;i++)
		{
		for(TInt mod=0 ; mod < 16 ; mod++)	//each module
			{
			ModifyModuleCapabilties(ModuleCaps[mod][i],mod);
			}
		r=lib.Load(KDll11);
		test.Printf(_L("mod11, iter=%d, ret=%d, exp=%d"),i,r,ModuleResultsB[i]);
		test(r==ModuleResultsB[i]);
		lib.Close();
		r=lib.Load(KDll6);
		test.Printf(_L("mod6, iter=%d, ret=%d, exp=%d"),i,r,ModuleResultsB[i]);
		test(r==ModuleResultsB[i]);
		lib.Close();
		r=lib.Load(KDll7);
		test.Printf(_L("mod7, iter=%d, ret=%d, exp=%d"),i,r,ModuleResultsC[i]);
		test(r==ModuleResultsC[i]);
		lib.Close();
		}

	}
*/
/*
void TestLoading()
//
//	test loading various dependancies
//
	{
	for(TInt tstcase=0; tstcase < KTestCases; tstcase++)	//each test case
		{
		for(TInt mod=0 ; mod < 16 ; mod++)	//each module
			{
			ModifyModuleCapabilties(ModuleCaps[mod][tstcase],mod);
			}
			TestLoad(tstcase);	
		}
	}
*/


_LIT(KSysHash,"?:\\Sys\\Hash\\");
const TInt KSlash='\\';

/**
    Creates a hash file in c:\\sys\\hash for a given file
    
    @param aFileName full path to the file, which hash is to be created
*/
void CreateFileHash(const TDesC& aFileName)
	{

	test.Printf(_L("Create Hash for the file %S\n"), &aFileName);

	TInt readsize = 1024*2;//to go into header
	HBufC8* block0 = HBufC8::NewL(readsize); 

	TPtr8 fileblock0(block0->Des());
	CSHA1* hasher=CSHA1::NewL(); 
	
	RFile fTarget;
	TInt r= fTarget.Open(TheFs, aFileName, EFileRead);
	test(r==KErrNone);
	TInt size;
	r=fTarget.Size(size);
	TInt offset=0;
	do	{
		if((size - offset) < readsize)
			readsize = (size - offset);
		r=fTarget.Read(offset, fileblock0, readsize);
		test(r==KErrNone);
		hasher->Update(fileblock0);
		offset+=readsize;
		}
	while(offset < size); 

	r=fTarget.Read(fileblock0, (size - offset));			
	test(r==KErrNone);
	hasher->Update(fileblock0);

	TBuf8<20> hash;//only outputs a 20 byte hash
	hash = hasher->Final();
	fTarget.Close();
		
//	const TUint8 * hptr=hash.Ptr();
//	for(TInt i=0;i<20;i++)
//		{
//		RDebug::Print(_L("install hash byte %d = 0x%x\n"),i,hptr[i]);
//		}
	
	delete block0;
	delete hasher;
	TEntry entry;
	r=TheFs.Entry(aFileName,entry);
	test(r==KErrNone);
	RFile fHash;
	TBuf<50> hashfile;
	hashfile = KSysHash;
	hashfile[0] = (TUint8) RFs::GetSystemDriveChar();
	TInt slashpos = aFileName.LocateReverse(KSlash);
	hashfile += aFileName.Mid(slashpos+1);
	
	//-- create directory for dll hashes
	r=TheFs.MkDirAll(hashfile);
	test(r==KErrNone || r==KErrAlreadyExists);
	
    //-- copy / replace given dll hash 
	r=fHash.Replace(TheFs, hashfile, EFileWrite);
	test(r==KErrNone);
	r=fHash.Write(hash);
	test(r==KErrNone);
	r=fHash.Size(size);
	test(r==KErrNone);
	test.Printf(_L("hash file size=%d\n"),size);
	fHash.Close();
	
    }


/**
    Corrups a file.
    
    @param  aFileName   a full path to the file to corrupt
    @return KErrNone on success
*/
static TInt CorruptFile(const TDesC& aFileName)
{
	test.Printf(_L("Corrupting file %S\n"), &aFileName);

    RFile corrFile;
    CleanupClosePushL(corrFile);	

    TInt r=corrFile.Open(TheFs, aFileName, EFileWrite);
	if(r != KErrNone)
        return r;
	
    TInt size;
	r=corrFile.Size(size);
	if(r != KErrNone)
        return r;
	
    TBuf8<2> dat;
	r=corrFile.Read(size - 5, dat);
	if(r != KErrNone)
        return r;

	dat[0] = (TUint8) ~dat[0];
	
    r=corrFile.Write(size - 5, dat);
	if(r != KErrNone)
        return r;

    CleanupStack::PopAndDestroy(1); //-- corrFile

    return KErrNone;
}


#ifndef WIN32
void TestRemovableMediaWithHash()
//
//	test loading from removable media and substed drives Both should fail
//
	{
	test.Next(_L("Testing Removable Media with hashing\n"));
	TInt r=0;
	CFileMan* fileMan=NULL;
	TRAP(r,fileMan=CFileMan::NewL(TheFs));
	test(r==KErrNone);

	TBuf<30> dllfilenames;
	TBuf<30> dlldestination;
	RLibrary lib;
	
    for(TInt i=0;i<14;i++)
		{
		dllfilenames=KNewDllName;
		dllfilenames.AppendNum(i);
		dllfilenames +=KDllExt;
		
		dlldestination=KNewDllName;
		dlldestination[0]=gDriveToTest;
		dlldestination.AppendNum(i);
		dlldestination+=KDllExt;
		
		r=TheFs.MkDirAll(dlldestination);
		test.Printf(_L("MkDirAll(%S) returned %d\n"), &dlldestination, r);
		test(r==KErrNone || r==KErrAlreadyExists);
		r=fileMan->Copy(dllfilenames,dlldestination, 0); 
        test(r==KErrNone || r==KErrAlreadyExists);	


		//take hash of binary
		CreateFileHash(dlldestination);

		//load binary as is
		r=lib.Load(dlldestination);
		RDebug::Print(_L("t_ldrcheck: loading  %S returned %d\n"),&dlldestination, r);

		User::After(100000);
		test(r==KErrNone);
		lib.Close();
		test.Printf(_L("Close lib on untouched load\n"));

        //-- corrupt dll
        r = CorruptFile(dlldestination);
        test(r==KErrNone);
		test.Printf(_L("Binary %S now corrupted\n"), &dlldestination);

		//load should fail
		test.Printf(_L("loading %S\n"),&dlldestination);
		r=lib.Load(dlldestination);
		test.Printf(_L("load of %S returned %d\n"),&dlldestination,r);
		test(r==KErrPermissionDenied);//as this process has Root caps and the dlls should be loaded with non
		lib.Close();
		test.Printf(_L("Lib close 1\n"));

		r=TheFs.Delete(dlldestination);
		test.Printf(_L("Delete ret=%d\n"),r);
		test(r==KErrNone);
		}//for(TInt i=0;i<14;i++)


	TBuf<30> exefilenames;
	TBuf<30> exedestination;
	RProcess p;
	TBuf<16> cmd;

	for(TInt j=14;j<16;j++)
		{
		exefilenames=KNewExeName;;
		exefilenames.AppendNum(j);
		exefilenames +=KExeExt;
		
		exedestination=KNewExeName;
		exedestination[0]=gDriveToTest;
		exedestination.AppendNum(j);
		exedestination+=KExeExt;

		r=fileMan->Copy(exefilenames,exedestination,0);
		test(r==KErrNone || r==KErrAlreadyExists);

		CreateFileHash(exedestination);

		r=p.Create(exedestination, cmd);
		test(r==KErrNone);
		p.Terminate(0);
		p.Close();

        r = CorruptFile(exedestination);
        test(r==KErrNone);
		
		test.Printf(_L("Binary %S now corrupted\n"), &exedestination);

		r=p.Create(exedestination, cmd);
		test(r==KErrPermissionDenied);
//		p.Terminate(0);	DON'T DO THIS SINCE CREATION FAILED - HANDLE NOT OPENED
		p.Close();
		
		r=TheFs.Delete(exedestination);
		test(r==KErrNone);

		}
	delete fileMan;
	}

/*
void TestRemovableMedia()
//
//	test loading from removable media and substed drives Both should fail
//
	{
	test.Next(_L("Testing Removeable Media"));
	TInt r=0;
	CFileMan* fileMan=NULL;
	TRAP(r,fileMan=CFileMan::NewL(TheFs));
	test(r==KErrNone);

	TBuf<30> dllfilenames;
	TBuf<30> dlldestination;
	RLibrary lib;
	for(TInt i=0;i<14;i++)
		{
		dllfilenames=KNewDllName;
		dllfilenames.AppendNum(i);
		dllfilenames +=KDllExt;
		
		dlldestination=KNewDllName;
		dlldestination[0]='D';
		dlldestination.AppendNum(i);
		dlldestination+=KDllExt;
		
		r=TheFs.MkDirAll(dlldestination);
		test(r==KErrNone || r==KErrAlreadyExists);

		r=fileMan->Copy(dllfilenames,dlldestination, 0);
		test(r==KErrNone || r==KErrAlreadyExists);	
		
		r=lib.Load(dlldestination);
		test.Printf(_L("load %S ret=%d"),&dlldestination,r);
		RDebug::Print(_L("r=%d"),r);
		test(r==KErrPermissionDenied);//as this process has Root caps and the dlls should be loaded with non
		lib.Close();
		}

	TBuf<30> exefilenames;
	TBuf<30> exedestination;
	RProcess p;
	TBuf<16> cmd;

	for(TInt j=14;j<16;j++)
		{
		exefilenames=KNewExeName;;
		exefilenames.AppendNum(j);
		exefilenames +=KExeExt;
		
		exedestination=KNewExeName;
		exedestination[0]='D';
		exedestination.AppendNum(j);
		exedestination+=KExeExt;

		r=fileMan->Copy(exefilenames,exedestination,0);
		test(r==KErrNone || r==KErrAlreadyExists);

		r=p.Create(exedestination, cmd);
		test(r==KErrPermissionDenied);
		p.Close();
		}
	delete fileMan;
	}
*/

void TestNonSystemSubsted()
//
//	Test an internal drive on non system dir
//
	{
	test.Next(_L("Testing Non System and Subst"));
	TInt r=0;
	CFileMan* fileMan=NULL;
	TRAP(r,fileMan=CFileMan::NewL(TheFs));
	test(r==KErrNone);

	TBuf<50> dllfilenames;
	TBuf<50> dlldestination;
	TBuf<50> substed;
	RLibrary lib;
	for(TInt i=0;i<14;i++)
		{
		dllfilenames=KNewDllName;
		dllfilenames.AppendNum(i);
		dllfilenames +=KDllExt;

		dlldestination=KAnyDirDll;
      dlldestination+=_L("_X");
		dlldestination.AppendNum(i);
		dlldestination+=KDllExt;

		if(i==0)
			{
			r=TheFs.MkDirAll(dlldestination);
			test(r==KErrNone || r==KErrAlreadyExists);
			r=TheFs.SetSubst(KAnyDirShort(), EDriveN);	//set up n as the substed drive
			test(r==KErrNone);
			}
		
		RDebug::Print(_L("copying from %S to %S"),&dllfilenames,&dlldestination);
		r=fileMan->Copy(dllfilenames,dlldestination, 0);
		test(r==KErrNone || r==KErrAlreadyExists);	

      //
      // Test that loading from fully qualified path fails
      // (ie - C:\Anyoldname\sys\bin\DLLTS_X0.DLL)
      //
      r=lib.Load(dlldestination);
      RDebug::Print(_L("RLibrary::Load(%S) : r=%d"), &dlldestination, r);
      test(r==KErrNotFound);

      //
      // Test that loading from substituted drive fails
      // (ie - N:\sys\bin\DLLTS_X0.DLL, where N:\ == C:\Anyoldname\)
      //
		substed=KJDllName;
      substed+=_L("_X");
		substed.AppendNum(i);
		substed+=KDllExt;
		
		r=lib.Load(substed);
      RDebug::Print(_L("RLibrary::Load(%S) : r=%d"), &substed, r);
      test(r==KErrNotFound);

      //
      // Test that loader search does not find substituted drives when
      // loading library with no drive or path specified.
      //
      substed=KJDllNameOnly;
      substed+=_L("_X");
      substed.AppendNum(i);
      substed+=KDllExt;

      r=lib.Load(substed);
      RDebug::Print(_L("RLibrary::Load(%S) : r=%d"), &substed, r);
      test(r==KErrNotFound);
		}

	TBuf<50> exefilenames;
	TBuf<50> exedestination;
	RProcess p;
	TBuf<16> cmd;

	for(TInt j=14;j<16;j++)
		{
		exefilenames=KNewExeName;;
		exefilenames.AppendNum(j);
		exefilenames +=KExeExt;

		exedestination=KAnyDirExe;
      exedestination+=_L("_X");
		exedestination.AppendNum(j);
		exedestination+=KExeExt;

		RDebug::Print(_L("copying from %S to %S"),&exefilenames,&exedestination);
		r=fileMan->Copy(exefilenames,exedestination,0);
		test(r==KErrNone || r==KErrAlreadyExists);

      //
      // Test that loading from fully qualified path fails
      // (ie - C:\Anyoldname\sys\bin\EXETS_X14.EXE)
      //
      r=p.Create(exedestination, cmd);
      RDebug::Print(_L("RProcess::Create(%S) : r=%d"), &exedestination, r);
      test(r==KErrNotFound);

      //
      // Test that loading from substituted drive fails
      // (ie - N:\sys\bin\EXETS_X14.EXE, where N:\ == C:\Anyoldname\)
      //
		substed=KJExeName;
      substed+=_L("_X");
		substed.AppendNum(j);
		substed+=KExeExt;

		r=p.Create(substed, cmd);
      RDebug::Print(_L("RProcess::Create(%S) : r=%d"), &substed, r);
      test(r==KErrNotFound);

      //
      // Test that loader search does not find substituted drives when
      // loading process with no drive or path specified.
      //
      substed=KJExeNameOnly;
      substed+=_L("_X");
      substed.AppendNum(j);
      substed+=KExeExt;

      r=p.Create(substed, cmd);
      RDebug::Print(_L("RProcess::Create(%S) : r=%d"), &substed, r);
      test(r==KErrNotFound);
		}
	delete fileMan;

	// Clear the substituted drive
	r=TheFs.SetSubst(KNullDesC, EDriveN);	
	test(r==KErrNone);
	}

/*
void TestSystemBinSubsted()
//
//	Test an internal drive on system dir
//
	{
	test.Next(_L("Testing System bin -> Subst"));
	TInt r=0;
	CFileMan* fileMan=NULL;
	TRAP(r,fileMan=CFileMan::NewL(TheFs));
	test(r==KErrNone);

	TBuf<50> dllfilenames;
	TBuf<50> substed;
	RLibrary lib;
	r=TheFs.SetSubst(KSystemLibs, 14);	//set up O as the substed drive
	test(r==KErrNone);
	for(TInt i=0;i<14;i++)
		{
		RDebug::Print(_L("doing modify caps = %d"),i);
		ModifyModuleCapabilties(KCapabilityRoot,i);
		dllfilenames=KNewDllName;
		dllfilenames.AppendNum(i);
		dllfilenames +=KDllExt;
		
		RDebug::Print(_L("Module = %S"),&dllfilenames);
		r=lib.Load(dllfilenames);
		test(r==KErrNone);//as this process has Root caps and the dlls should be loaded with non
		substed=_L("O:\\DLLTS");
		substed.AppendNum(i);
		substed+=KDllExt;
	
		r=lib.Load(substed);
		test(r==KErrNone);
		lib.Close();
		}
	TBuf<50> exefilenames;
	RProcess p;
	TBuf<16> cmd;

	for(TInt j=14;j<16;j++)
		{
		exefilenames=KNewExeName;
		exefilenames.AppendNum(j);
		exefilenames +=KExeExt;
		ModifyModuleCapabilties(KCapabilityRoot,j);
		r=p.Create(exefilenames, cmd);
		test(r==KErrNone);
		p.Terminate(0);
		p.Close();


		substed=_L("O:\\EXETS");
		substed.AppendNum(j);
		substed+=KExeExt;
		RDebug::Print(_L("substed=%S"),&substed);
		r=p.Create(substed, cmd);
		test(r==KErrNone);
		p.Terminate(0);
		p.Close();
		}
	delete fileMan;
	}
*/
#endif



void HashBM()
//
//	time how long to load a small dll 100 times and one large one
//
	{
	test.Next(_L("Next Do Bench Mark\n"));
	TBuf<30> dlldestination;
	dlldestination=KNewDllName;
	dlldestination[0]='D';
	dlldestination.AppendNum(1);
	dlldestination+=KDllExt;
	RLibrary lib;
	TInt r=0;
	TUint32 startcount = User::NTickCount();
	for (TInt i=0;i<100;i++)
		{
		r=lib.Load(dlldestination);
		lib.Close();
		}
	TUint32 endcount = User::NTickCount();
	test(r==KErrNone);
	RDebug::Print(_L("100 * 4k dll \n"));
	RDebug::Print(_L("start count=%d, end count=%d, dif=%d\n"),startcount,endcount,endcount-startcount);

	startcount = User::NTickCount();
	r=lib.Load(_L("D:\\sys\\bin\\euser.dll"));
	lib.Close();
	endcount = User::NTickCount();
	RDebug::Print(_L("r=%d")); 
//	test(r==KErrNone);
	RDebug::Print(_L("1 * 233k dll \n"));
	RDebug::Print(_L("start count=%d, end count=%d, dif=%d\n"),startcount,endcount,endcount-startcount);
	}

//-------------------------------------------------------

/**
    testing RLoader::CheckLibraryHash() API
*/
void  TestCheckLibraryHash()
{
    test.Next(_L("Testing CheckLibraryHash API\n"));

	TInt r=0;
	CFileMan* pFileMan=NULL;
	TRAP(r,pFileMan=CFileMan::NewL(TheFs));
	test(r==KErrNone);

    RLoader loader;
	r=loader.Connect();
	test(r==KErrNone);
    
    //-- 1. copy test DLL to the specified drive and create hash file for it.
	TBuf<40> dllFileName;
	TBuf<40> dllDestination;
	
	const TInt KDllNumber = 0;

    dllFileName=KDllfilename;
	dllFileName.AppendNum(KDllNumber);
	dllFileName+=KDllExt;
	
	dllDestination=KNewDllName;
	dllDestination[0]=(TUint16)gDriveToTest;
	dllDestination.AppendNum(KDllNumber);
	dllDestination+=KDllExt;

    test.Printf(_L("Copy %S to %S\n"), &dllFileName, &dllDestination);

	r=TheFs.MkDirAll(dllDestination);
	test(r==KErrNone || r==KErrAlreadyExists);

	r=pFileMan->Copy(dllFileName, dllDestination);
	test(r==KErrNone || r==KErrAlreadyExists);

	r=pFileMan->Attribs(dllDestination, 0, KEntryAttReadOnly, TTime(0) ,0);
	test(r==KErrNone);

    test.Printf(_L("Creating Dll hash.\n"));
    CreateFileHash(dllDestination);

    //-- 2. check if the hash exists
    r=loader.CheckLibraryHash(dllDestination);
    test(r==KErrNone);
    test.Printf(_L("Dll hash exists.\n"));

    //-- 2.1 check if the hash exists and valid
    r=loader.CheckLibraryHash(dllDestination, ETrue);
    test(r==KErrNone);
    
    test.Printf(_L("Dll hash exists and valid.\n"));

    //-- 3. corrupt dll
    r = CorruptFile(dllDestination);
    test(r==KErrNone);

    //-- 3.1 check that the hash exists, but is incorrect.
    r=loader.CheckLibraryHash(dllDestination);
    test(r==KErrNone);
    test.Printf(_L("Dll hash exists.\n"));

    r=loader.CheckLibraryHash(dllDestination, ETrue);
    test(r==KErrCorrupt);
    
    test.Printf(_L("Dll hash exists and INVALID.\n"));

    //-- 4. try to locte hash fo the unexisting dll.
    r=loader.CheckLibraryHash(_L("Z:\\sys\\bin\\NotExist.dll"));
    test(r==KErrNotFound);

    loader.Close();

    delete pFileMan;
}

//-------------------------------------------------------

void ParseCommandArguments()
//
//
//
	{
	TBuf<0x100> cmd;
	User::CommandLine(cmd);
	TLex lex(cmd);
	TPtrC token=lex.NextToken();
	TFileName thisfile=RProcess().FileName();
	if (token.MatchF(thisfile)==0)
		{
		token.Set(lex.NextToken());
		}
	test.Printf(_L("CLP=%S"),&token);

	if(token.Length()!=0)		
		{
		gDriveToTest=token[0];
		gDriveToTest.UpperCase();
		}
	else						
		gDriveToTest='D';	//default to D:
	}


//-------------------------------------------------------

void TestExes()
{
    test.Next(_L("Testing Exes presence.\n"));
	
    TInt r;

    RProcess ap;
	r=LoadExe(14,ap);
	test(r==KErrNone);
	ap.Terminate(0);
	ap.Close();
	
    r=LoadExe(15,ap);
	test(r==KErrNone);
	ap.Terminate(0);
	ap.Close();
}


//-------------------------------------------------------

static void CallTestsL(void)
{

#ifdef __WINS__
        test.Printf(_L("Not testing on WINS !\n"));
        return;
#else

        TestExes();
    //	TestGetCapability();
	    CopyModules();				//copies modules from ROM to disk so they may be modified
    //	TestLoading();
    //	TestLoadLibrary();
	

#ifndef WIN32
	    if(PlatSec::ConfigSetting(PlatSec::EPlatSecEnforceSysBin))
		    TestRemovableMediaWithHash();

    //	TestSystemBinSubsted();
    //	TestRemovableMedia();
	    TestNonSystemSubsted();
#endif //WIN32
    //	HashBM();

        TestCheckLibraryHash();

#endif //#ifndef __WINS__
    
}

//-------------------------------------------------------
//
//	main
//
GLDEF_C TInt E32Main()
	{
	ParseCommandArguments(); //need this for drive letter to test

	test.Title();
	test.Start(_L("Setup\n"));
	CTrapCleanup* cleanup;
	cleanup=CTrapCleanup::New();
	__UHEAP_MARK;

	TBuf<20> sessPath;
	TInt r=0;	
	r=TheFs.Connect();
	test(r==KErrNone);
	r=TheFs.SessionPath(sessPath);
	test(r==KErrNone);

	TInt drive;
	RFs::CharToDrive(gDriveToTest, drive);
	TDriveInfo info;
	r=TheFs.Drive(info, drive);
	test(r==KErrNone);
	
    if((info.iDriveAtt & KDriveAttRemovable) == 0)
	{
        test.Printf(_L("Not testing on non-removable media !\n"));
    }
    else
    {//-- testing on removable media
        TRAP(r,CallTestsL());
    }

	TheFs.Close();
	test.End();
	test.Close();

	__UHEAP_MARKEND;
	delete cleanup;

	return KErrNone;
	}