diff -r 000000000000 -r a41df078684a userlibandfileserver/fileserver/etshell/ts_deps.cpp --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/userlibandfileserver/fileserver/etshell/ts_deps.cpp Mon Oct 19 15:55:17 2009 +0100 @@ -0,0 +1,668 @@ +// 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: +// f32\etshell\ts_deps.cpp +// +// + +#include "ts_std.h" +#include "f32image.h" +#include +#include "sf_deflate.h" +#include "sf_image.h" + +//#define _DETAILED_CHECK // Select for detailed dependency check + +#if defined(_DETAILED_CHECK) // Prints information to screen +#define __PRINT(t) {CShell::TheConsole->Printf(t);} +#define __PRINT1(t,a) {CShell::TheConsole->Printf(t,a);} +#define __PRINT2(t,a,b) {CShell::TheConsole->Printf(t,a,b);} +#define __PRINTWAIT(t){CShell::TheConsole->Printf(t);CShell::TheConsole->Getch();} +#else +#define __PRINT(t) +#define __PRINT1(t,a) +#define __PRINT2(t,a,b) +#define __PRINTWAIT(t) +#endif + +/* + +CDllChecker::GetImportDataL(aFilename) reads the Image Header, Import Section +and all import data for aFilename. If aFilename is a ROM dll, and thus has no +import data, or if the file contains no import data for some other reason the +function leaves with KErrGeneral. If a file is compressed, function calls +appropriate decompression routine to inflate the import data. +The function then calls GetDllTableL function which +reads the first import block and enters a "for" loop. The Dll's name and Uid3 are obtained +from CDllChecker::GetFileNameAndUid(). If the Dll name does not occur in the +array of previously checked Dlls, CDllChecker::FindDll() is called. If the Dll +is found,the function then calls CDllChecker::GetImportDataL on the filename acquired by +GetFileNameAndUid()(recursive call). + +If the Dll contains no import data or cannot be found, or if the Uid is invalid, +the next import is checked. + +The Uid3 value is checked by calling CDllChecker::CheckUid. This compares the +Uid3 value found in the image header of the file, with that found by +GetFileNameAndUid(). If there are any discrepancies,these are noted. + +Each potential import is added to the array by dllAppendL(TResultCheck) to +indicate its import status. + +CDllChecker::ListArray() lists the contents of the array when all imports +have been checked. +*/ + + +CDllChecker::CDllChecker() +// +// Constructor +// + { + iDllArray=NULL; + iCalls=0; + } + + + +void CDllChecker::ConstructL() +// +// Creates an array to hold DLLs referenced by this executable +// + { + iDllArray = new(ELeave)CArrayFixFlat(4); + __PRINT(_L(" Successfully created iDllArray\n")); + } + + +CDllChecker::~CDllChecker() +// +// Destructor +// + { + delete iDllArray; + } + + +GLDEF_C void Get16BitDllName(TDes8& aDllName,TDes& aFileName) +// +// Convert an 8 bit name to a 16 bit name - zero padded automatically +// No effect in 8 bit builds - just sets aFileName to aDllName +// + { + aFileName.SetLength(aDllName.Length()); + aFileName.Copy(aDllName); + } + +void FileCleanup(TAny* aPtr) + { + TFileInput* f=(TFileInput*)aPtr; + f->Cancel(); + delete f; + } + +void CDllChecker::LoadFileInflateL(E32ImageHeaderComp* aHeader,TUint8* aRestOfFileData,TUint32 aRestOfFileSize) + { + TInt pos = aHeader->TotalSize(); + User::LeaveIfError(iFile.Seek(ESeekStart,pos)); // Start at beginning of compressed data + + TFileInput* file = new (ELeave) TFileInput(iFile); + CleanupStack::PushL(TCleanupItem(&FileCleanup,file)); + CInflater* inflater=CInflater::NewLC(*file); + + if (aHeader->iCodeSize) + { + TUint8* CodeData = (TUint8*)User::AllocLC(aHeader->iCodeSize ); + TInt count=inflater->ReadL((TUint8*)CodeData ,aHeader->iCodeSize,&Mem::Move); + if(count!=aHeader->iCodeSize) + User::Leave(KErrCorrupt); + CleanupStack::PopAndDestroy(CodeData); + } + + if (aRestOfFileSize) + { + TUint32 count=inflater->ReadL(aRestOfFileData,aRestOfFileSize,&Mem::Move); + if(count!=aRestOfFileSize) + User::Leave(KErrCorrupt); + } + CleanupStack::PopAndDestroy(2,file); + } + +void CDllChecker::LoadFileNoCompressL(E32ImageHeaderComp* aHeader,TUint8* aRestOfFileData,TUint32 aRestOfFileSize) + { + TInt pos = (aHeader->TotalSize()+aHeader->iCodeSize); + if (aRestOfFileSize) + { + User::LeaveIfError(iFile.Seek(ESeekStart,pos)); // Start at beginning of import table + TPtr8 ptrToData((TText8*)(aRestOfFileData),aRestOfFileSize,aRestOfFileSize); + User::LeaveIfError(iFile.Read(ptrToData, (TInt)aRestOfFileSize)); + } + } +//function loads file's import information calling decompression routine if needed +TInt CDllChecker::LoadFile(TUint32 aCompression,E32ImageHeaderComp* aHeader,TUint8* aRestOfFileData,TUint32 aRestOfFileSize) + { + TInt r=KErrNone; + if(aCompression==KFormatNotCompressed) + { + TRAP(r,LoadFileNoCompressL(aHeader,aRestOfFileData,aRestOfFileSize)); + } + else if(aCompression==KUidCompressionDeflate) + { + TRAP(r,LoadFileInflateL(aHeader,aRestOfFileData,aRestOfFileSize)); + } + else + r=KErrNotSupported; + + return r; + } + +//function iterates through the list of libraries the current executable depends on +//for each dependency in the list the function checks whether the .dll being checked is already added to the array of dependencies +//if not, the function adds dependency being checked to the array of dependencies and calls GetImportDataL function recursively +void CDllChecker::GetDllTableL(TUint8* aImportData, TInt aDllRefTableCount,TUint aFlags) + { + E32ImportBlock* block = (E32ImportBlock*)((TUint8*)aImportData+sizeof(E32ImportSection)); + + //*********Beginning of the loop********* + for (TInt i=0; iiOffsetOfDllName); + TPtrC8 dllNamePtr(dllName, User::StringLength(dllName)); + GetFileNameAndUid(dllInfo,dllNamePtr);//Gets name and Uid of dependency + TUid* pointer=&dllInfo.iUid; + __PRINT(_L(" Check Dll has not already been imported\n")); + TKeyArrayFix key(0,ECmpFolded); + TInt pos; + TInt r=iDllArray->Find(dllInfo,key,pos);// Search array by Dll Name + if (r==KErrNone) // **********IT IS ALREADY IN THE ARRAY*********** + { + __PRINT1(_L(" Dll %S has already been checked\n"),&dllInfo.iDllName); + + //Check its Uid3 against that noted in the array + if (iDllArray->At(pos).iUid!=dllInfo.iUid) + { + // Uid3 is different to that of the same named Dll + // Add it to the array for comparative purposes + __PRINT2(_L(" Uid3 [%08x] for %S is different from that noted previously\n"),dllInfo.iUid, &dllInfo.iDllName); + dllInfo.iResult=EUidDifference; + + // Add this entry to iDllArray + DllAppendL(dllInfo); + } + }// Run to the end of the "for" loop for this i value + else // **********THE FILE IS NOT YET IN THE ARRAY********** + { + __PRINT(_L(" Dll has not previously been checked\n")); + + // Check through it and add the relevant information to the array + + // Search for the DLL + TPath aPath=(TPath)CShell::currentPath; + TFileName fileName; + TName dll16BitName; + +#if defined(UNICODE) + Get16BitDllName(dllInfo.iDllName,dll16BitName); +#else + dll16BitName=(dllInfo.iDllName); +#endif + r=FindDll(dll16BitName,fileName,aPath); + + __PRINT1(_L("dll16BitName=%S\n"),&dll16BitName); + __PRINTWAIT(_L(" Press any key to continue\n")); + + if (r==KErrNotFound) // Could not find Dll + { + dllInfo.iResult=ENotFound; + }// Run to the end of the "for" loop for this i value + + else // File was located + +// Go recursive. Call GetImportDataL on the new dll, if it imports anything. +// ROM dlls have no import data so this is never called for ROM dlls. +// This *will* terminate. It is only called on "new" dlls not in the array. + + { + __PRINT(_L(" ****Go recursive****\n")); + __PRINTWAIT(_L(" Press any key to continue\n")); + + iCalls++; + + TRAP(r,GetImportDataL(fileName, pointer)); + // Pass in (parsed) fileName and Uid3 (from file header) + switch(r) + { + case(KErrGeneral): // No import data + { + dllInfo.iResult=ENoImportData; + break; + // Run to the end of the for loop for this i value + } + case(EUidNotSupported): + { + dllInfo.iResult=EUidNotSupported; + break; + } + case(KErrNone): // Import data was read + { + dllInfo.iResult=EFileFoundAndUidSupported; + break; + // Run to the end of the for loop for this i value + } + case(KErrInUse): + { + __PRINT2(_L(" File %S is already open\n"),&fileName,r); + dllInfo.iResult=EAlreadyOpen; + break; + } + case(KErrCorrupt): + { + __PRINT2(_L(" File %S has unexpected format\n"),&fileName,r); + dllInfo.iResult=EAlreadyOpen; + break; + } + default: + { + __PRINT1(_L(" File %S could not be opened \n"),&fileName); + dllInfo.iResult=ECouldNotOpenFile; + break; + } + // Run to the end of the for loop for this i value + } + } + + // Add the information about the dependency to iDllArray + DllAppendL(dllInfo); + } +// Runs to here when all import data has been read for this i value + + __PRINT(_L(" Go to next dll to be imported...\n")); + __PRINTWAIT(_L(" Press any key to continue\n")); + + block = (E32ImportBlock*)block->NextBlock(E32ImageHeader::ImpFmtFromFlags(aFlags)); + + }// The end of the loop. Every DLL has been located + + } + + +void CDllChecker::GetImportDataL(const TDesC& aFileName, TUid* aPointer) + { + TInt cleanupCount=0; + // Check that the file is not a ROM dll. These have no import data + if (ShellFunction::TheShell->TheFs.IsFileInRom(aFileName)) + { + User::Leave(KErrGeneral); + } + + //open file for reading and push it to autoclose stack + TAutoClose autoFile; + User::LeaveIfError(autoFile.iObj.Open(CShell::TheFs,aFileName,EFileStream)); + autoFile.PushL(); + cleanupCount++; + iFile=autoFile.iObj; + + //Create a pointer to an Image Header + //reserve enough memory for compressed file header because we don't know whether the file is compressed or not + E32ImageHeaderComp* imageHeader=new(ELeave)E32ImageHeaderComp; + CleanupStack::PushL(imageHeader); + cleanupCount++; + + //read file header + TPtr8 ptrToImageHeader((TText8*)(imageHeader),sizeof(E32ImageHeaderComp),sizeof(E32ImageHeaderComp)); + User::LeaveIfError(iFile.Read(ptrToImageHeader,sizeof(E32ImageHeaderComp))); + + if (imageHeader->iImportOffset==0)// File contains no import data + { + User::Leave(KErrGeneral); + } + + TUint32 compression = imageHeader->CompressionType(); + TInt restOfFileSize=0; + TUint8* restOfFileData=NULL; + //detect the size of import information + if (compression != KFormatNotCompressed) + { + // Compressed executable + // iCodeOffset = header size for format V or above + // = sizeof(E32ImageHeader) for format J + restOfFileSize = imageHeader->UncompressedFileSize() - imageHeader->iCodeOffset; + } + else + { + TInt FileSize; + iFile.Size(FileSize); + restOfFileSize = FileSize-imageHeader->TotalSize(); + } + restOfFileSize -= imageHeader->iCodeSize; // the size of the exe less header & code + + //allocate memory for import information + if (restOfFileSize >0) + { + restOfFileData = (TUint8*)User::AllocLC(restOfFileSize ); + cleanupCount++; + } + + User::LeaveIfError(LoadFile(compression,imageHeader,restOfFileData,restOfFileSize)); // Read import information in + + TInt32 uid3=imageHeader->iUid3; + if(iCalls!=0) // Only check Uid3 of dependencies (ie only after first + { // call of recursive function) + TInt r=CheckUid3(uid3,*aPointer); + + if (r!=KErrNone) // Dll's Uid3 is not valid + User::Leave(EUidNotSupported); + } + + TInt bufferOffset=imageHeader->iImportOffset-(imageHeader->iCodeOffset + imageHeader->iCodeSize); + if( TInt(bufferOffset+sizeof(E32ImportSection))>restOfFileSize) + User::Leave(KErrCorrupt); + //get the table of dependencies + GetDllTableL(restOfFileData+bufferOffset,imageHeader->iDllRefTableCount,imageHeader->iFlags); + + CleanupStack::PopAndDestroy(cleanupCount); + } + + +TUint8* CDllChecker::NextBlock(TUint8* aBlock) + { + E32ImportBlock* block; + // Advance the pointer to the next block + block=(E32ImportBlock*)aBlock; + aBlock=(aBlock+sizeof(E32ImportBlock)+((block->iNumberOfImports)*sizeof(TUint))); + return (aBlock); + } + + +TFileNameInfo::TFileNameInfo() + { + memclr(this, sizeof(TFileNameInfo)); + } + +TInt TFileNameInfo::Set(const TDesC8& aFileName, TUint aFlags) + { + iUid = 0; + iVersion = 0; + iPathPos = 0; + iName = aFileName.Ptr(); + iLen = aFileName.Length(); + iExtPos = aFileName.LocateReverse('.'); + if (iExtPos<0) + iExtPos = iLen; + TInt osq = aFileName.LocateReverse('['); + TInt csq = aFileName.LocateReverse(']'); + if (!(aFlags & EAllowUid) && (osq>=0 || csq>=0)) + { + return KErrBadName; + } + if (osq>=iExtPos || csq>=iExtPos) + { + return KErrBadName; + } + TInt p = iExtPos; + if ((aFlags & EAllowUid) && p>=10 && iName[p-1]==']' && iName[p-10]=='[') + { + TPtrC8 uidstr(iName + p - 9, 8); + TLex8 uidlex(uidstr); + TUint32 uid = 0; + TInt r = uidlex.Val(uid, EHex); + if (r==KErrNone && uidlex.Eos()) + iUid = uid, p -= 10; + } + iUidPos = p; + TInt ob = aFileName.LocateReverse('{'); + TInt cb = aFileName.LocateReverse('}'); + if (ob>=iUidPos || cb>=iUidPos) + { + return KErrBadName; + } + if (ob>=0 && cb>=0 && p-1==cb) + { + TPtrC8 p8(iName, p); + TInt d = p8.LocateReverse('.'); + TPtrC8 verstr(iName+ob+1, p-ob-2); + TLex8 verlex(verstr); + if (ob==p-10 && dob && p-1>d && (aFlags & EAllowDecimalVersion)) + { + TUint32 maj = 0; + TUint32 min = 0; + TInt r = verlex.Val(maj, EDecimal); + TUint c = (TUint)verlex.Get(); + TInt r2 = verlex.Val(min, EDecimal); + if (r==KErrNone && c=='.' && r2==KErrNone && verlex.Eos() && maj<32768 && min<32768) + iVersion = (maj << 16) | min, p = ob; + } + } + iVerPos = p; + if (iLen>=2 && iName[1]==':') + { + TUint c = iName[0]; + if (c!='?' || !(aFlags & EAllowPlaceholder)) + { + c |= 0x20; + if (c<'a' || c>'z') + { + return KErrBadName; + } + } + iPathPos = 2; + } + TPtrC8 pathp(iName+iPathPos, iVerPos-iPathPos); + if (pathp.Locate('[')>=0 || pathp.Locate(']')>=0 || pathp.Locate('{')>=0 || pathp.Locate('}')>=0 || pathp.Locate(':')>=0) + { + return KErrBadName; + } + iBasePos = pathp.LocateReverse('\\') + 1 + iPathPos; + return KErrNone; + } + +void TFileNameInfo::GetName(TDes8& aName, TUint aFlags) const + { + if (aFlags & EIncludeDrive) + aName.Append(Drive()); + if (aFlags & EIncludePath) + { + if (PathLen() && iName[iPathPos]!='\\') + aName.Append('\\'); + aName.Append(Path()); + } + if (aFlags & EIncludeBase) + aName.Append(Base()); + if ((aFlags & EForceVer) || ((aFlags & EIncludeVer) && VerLen()) ) + { + aName.Append('{'); + aName.AppendNumFixedWidth(iVersion, EHex, 8); + aName.Append('}'); + } + if ((aFlags & EForceUid) || ((aFlags & EIncludeUid) && UidLen()) ) + { + aName.Append('['); + aName.AppendNumFixedWidth(iUid, EHex, 8); + aName.Append(']'); + } + if (aFlags & EIncludeExt) + aName.Append(Ext()); + } + + +void CDllChecker::GetFileNameAndUid(SDllInfo &aDllInfo, const TDesC8 &aExportName) +// +// Gets filename and UID +// + { + TFileNameInfo filename; + filename.Set(aExportName,TFileNameInfo::EAllowUid|TFileNameInfo::EAllowDecimalVersion); + filename.GetName(aDllInfo.iDllName,TFileNameInfo::EIncludeBaseExt); + aDllInfo.iUid=TUid::Uid(filename.Uid()); + } + + +TInt CDllChecker::CheckUid3(TInt32 aUid3,TUid aUid) +// +// Check that Uid3 is the same in the iDllName and as noted by the Image Header +// aUid3 is the value found by the image header +// aUid is the value found by parsing the result of block->dllname +// using GetFileNameAndUid() + { + + if ((aUid.iUid)==aUid3) + { + + __PRINT(_L(" Uid3 is valid\n")); + + return KErrNone; + } + else + { + + __PRINT(_L(" Uid3 value is not supported\n")); + + return (EUidNotSupported); + } + } + + + +TInt CDllChecker::FindDll(TDes& aDllName,TFileName& aFileName, TPath& aPath) +// +// Search for a dll in the following sequence ... +// 1. Supplied path parameter +// 2. System directories on all drives +// + { + TFindFile findFile(CShell::TheFs); + TInt r=findFile.FindByPath(aDllName,&aPath); + if (r==KErrNone) + { + aFileName=findFile.File(); + + __PRINT1(_L(" Dependency %S was found (supplied path)\n"),&aFileName); + + return(r); + } + + r=findFile.FindByDir(aDllName,_L("\\Sys\\Bin\\")); + if (r==KErrNone) + { + aFileName=findFile.File(); + + __PRINT1(_L(" Dependency %S was found (system directory)\n"),&aFileName); + + return(r); + } + + if(!PlatSec::ConfigSetting(PlatSec::EPlatSecEnforceSysBin)) + { + r=findFile.FindByDir(aDllName,_L("\\System\\Bin\\")); + if (r==KErrNone) + { + aFileName=findFile.File(); + + __PRINT1(_L(" Dependency %S was found (system directory)\n"),&aFileName); + + return(r); + } + } + + __PRINT1(_L(" Dependency %S was not found\n"),&aDllName); + + return(KErrNotFound); + } + + + + +void CDllChecker::DllAppendL(const SDllInfo& aDllInfo) + { + TInt leaveCode=KErrNone; + TRAP(leaveCode,iDllArray->AppendL(aDllInfo)); // Add it to iDllArray + + if (leaveCode!=KErrNone) + { + __PRINT(_L(" Could not add Dll to the array\n")); + __PRINTWAIT(_L(" Press any key to continue\n")); + + User::Leave(leaveCode); + } + else + { + __PRINT(_L(" Added this information to the array\n")); + __PRINT1(_L(" Number of elements in array=%d\n"),iDllArray->Count()); + + } + } + + + +void CDllChecker::ListArray() + { + TInt elements=iDllArray->Count(); + + CShell::TheConsole->Printf(_L(" Number of dependencies checked = %d\n"),elements); + + for (TInt i=0;iAt(i).iDllName,filename); + CShell::TheConsole->Printf(_L(" %d: %-15S Uid3: [%08x] "),(i+1),&(filename),(iDllArray->At(i).iUid)); +#else + CShell::TheConsole->Printf(_L(" %d: %-15S Uid3: [%08x] "),(i+1),&(iDllArray->At(i).iDllName),(iDllArray->At(i).iUid)); +#endif + switch(iDllArray->At(i).iResult) + { + case(ENoImportData): + CShell::TheConsole->Printf(_L("--- No import data\n")); + break; + + case(EUidNotSupported): + CShell::TheConsole->Printf(_L("--- Uid3 is not supported\n")); + break; + + case(ENotFound): + CShell::TheConsole->Printf(_L("--- File was not found\n")); + break; + + case(ECouldNotOpenFile): + CShell::TheConsole->Printf(_L("--- File could not be opened\n")); + break; + + case(EUidDifference): + CShell::TheConsole->Printf(_L("--- File already noted with different Uid\n")); + break; + + case(EAlreadyOpen): + CShell::TheConsole->Printf(_L("--- File already open\n")); + break; + + case(EFileFoundAndUidSupported): + CShell::TheConsole->Printf(_L("--- File was found, Uid3 is supported\n")); + break; + default: // Will never reach here + CShell::TheConsole->Printf(_L("--- Undefined\n")); + break; + } + } + } +