imgtools/romtools/rofsbuild/r_obey.cpp
changeset 2 39c28ec933dd
child 5 301c3edbdaa1
equal deleted inserted replaced
1:820b22e13ff1 2:39c28ec933dd
       
     1 /*
       
     2 * Copyright (c) 1995-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     3 * All rights reserved.
       
     4 * This component and the accompanying materials are made available
       
     5 * under the terms of the License "Eclipse Public License v1.0"
       
     6 * which accompanies this distribution, and is available
       
     7 * at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     8 *
       
     9 * Initial Contributors:
       
    10 * Nokia Corporation - initial contribution.
       
    11 *
       
    12 * Contributors:
       
    13 *
       
    14 * Description: 
       
    15 * @internalComponent * @released
       
    16 * Rofsbuild Obey file class and its reader class.
       
    17 *
       
    18 */
       
    19 
       
    20 
       
    21 #include <string.h>
       
    22 
       
    23 #ifdef __VC32__
       
    24  #ifdef __MSVCDOTNET__
       
    25   #include <strstream>
       
    26   #include <iomanip>
       
    27  #else //__MSVCDOTNET__
       
    28   #include <strstrea.h>
       
    29   #include <iomanip.h>
       
    30  #endif  //__MSVCDOTNET__
       
    31 #else // !__VC32__
       
    32 #ifdef __TOOLS2__
       
    33 	#include <sstream>
       
    34 	#include <iomanip>
       
    35 	#include <sys/stat.h>
       
    36 	using namespace std;
       
    37 #else
       
    38 	#include <strstrea.h>
       
    39 	#include <iomanip.h>
       
    40 #endif
       
    41  
       
    42 #endif //__VC32__
       
    43 
       
    44 
       
    45 #include <stdlib.h>
       
    46 #include <stdio.h>
       
    47 #include <time.h>
       
    48 #include <assert.h>
       
    49 #include <errno.h>
       
    50 
       
    51 #include <e32std.h>
       
    52 #include <e32std_private.h>
       
    53 #include <e32rom.h>
       
    54 #include <u32std.h>
       
    55 #include <f32file.h>
       
    56 
       
    57 #include "h_utl.h"
       
    58 #include "r_obey.h"
       
    59 #include "r_coreimage.h"
       
    60 #include "patchdataprocessor.h"
       
    61 #include "filesysteminterface.h" 
       
    62 #include "r_driveimage.h"
       
    63 
       
    64 extern TInt gCodePagingOverride;
       
    65 extern TInt gDataPagingOverride;
       
    66 extern ECompression gCompress;
       
    67 extern TBool gEnableStdPathWarning; // Default to not warn if destination path provided for a file is not in standard path.
       
    68 
       
    69 
       
    70 
       
    71 #define _P(word)	word, sizeof(word)-1	// match prefix, optionally followed by [HWVD]
       
    72 #define _K(word)	word, 0					// match whole word
       
    73 
       
    74 const ObeyFileKeyword ObeyFileReader::iKeywords[] =
       
    75 {
       
    76 	{_K("file"),		2,-2, EKeywordFile, "File to be copied into ROFS"},
       
    77 	{_K("data"),		2,-2, EKeywordData, "same as file"},
       
    78 
       
    79 	{_K("rofsname"),	1, 1, EKeywordRofsName, "output file for ROFS image"},
       
    80 	{_K("romsize"),		1, 1, EKeywordRomSize, "size of ROM image"}, 
       
    81 	{_P("hide"),	    2, -1, EKeywordHide, "Exclude named file from ROM directory structure"},
       
    82 	{_P("alias"),	    2, -2, EKeywordAlias, "Create alias for existing file in ROM directory structure"},
       
    83 	{_P("rename"),	    2, -2, EKeywordRename, "Change the name of a file in the ROM directory structure"},
       
    84 	{_K("rofssize"),		1, 1, EKeywordRofsSize, "maximum size of ROFS image"},
       
    85 	{_K("romchecksum"),	1, 1, EKeywordRofsChecksum, "desired 32-bit checksum value for the whole image"},
       
    86 	{_K("version"),		1, 1, EKeywordVersion, "ROFS image version number"},
       
    87 	{_K("time"),	    1,-1, EKeywordTime, "ROFS image timestamp"},
       
    88 	{_K("extensionrofs"),1+2, 1, EKeywordExtensionRofs, "Start of definition of optional Extension ROFS"},
       
    89 	{_K("extensionrofsname"),1, 1, EKeywordCoreRofsName, "ROFS image on which extension ROFS is based"},
       
    90 	{_K("rem"),			0, 0, EKeywordNone, "comment"},
       
    91 	{_K("stop"),		0, 0, EKeywordNone, "Terminates OBEY file prematurely"},
       
    92 	{_K("romchecksum"),	1, 1, EKeywordRomChecksum, "desired 32-bit checksum value for the whole ROFS image"},
       
    93 	{_K("coreimage"),	1, 1, EKeywordCoreImage, "Core image to be used for extension directory structure"},
       
    94 	{_K("autosize"),	1, 1, EKeywordRofsAutoSize, "Automatically adjust maximum image size to actual used"},
       
    95 	{_K("pagingoverride"),	1, 1, EKeywordPagingOverride, "Overide the demand paging attributes for every file in ROM, NOPAGING|DEFAULTUNPAGED|DEFAULTPAGED"},
       
    96 	{_K("codepagingoverride"),	1, 1, EKeywordCodePagingOverride, "Overide the code paging attributes for every file in ROM, NOPAGING|DEFAULTUNPAGED|DEFAULTPAGED"},
       
    97 	{_K("datapagingoverride"),	1, 1, EKeywordDataPagingOverride, "Overide the data paging attributes for every file in ROM, NOPAGING|DEFAULTUNPAGED|DEFAULTPAGED"},
       
    98 	{_K("dataimagename"),1, 1,EKeywordDataImageName, "Data Drive image file name"},
       
    99 	{_K("dataimagefilesystem"),1, 1,EKeywordDataImageFileSystem, "Drive image file system format"},
       
   100 	{_K("dataimagesize"),1, 1,EKeywordDataImageSize, "Maximum size of Data Drive image"},
       
   101 	{_K("volume"),1, -1,EKeywordDataImageVolume, "Volume Label of Data Drive image"},
       
   102 	{_K("sectorsize"),1, 1,EKeywordDataImageSectorSize, "Sector size(in bytes) of Data Drive image"},
       
   103 	{_K("fattable"),1, 1,EKeywordDataImageNoOfFats, "Number of FATs in the Data Drive image"},
       
   104 	// things we don't normally report in the help information
       
   105 	{_K("trace"),		1, 1, EKeywordTrace, "(ROMBUILD activity trace flags)"},
       
   106 	{_K("filecompress"),2, -2,EKeywordFileCompress,"Non-XIP Executable to be loaded into the ROM compressed" },
       
   107 	{_K("fileuncompress"),2, -2,EKeywordFileUncompress,"Non-XIP Executable to be loaded into the ROM uncompressed" },
       
   108 	{_K("patchdata"),2, 5,EKeywordPatchDllData, "Patch exported data"},
       
   109 	{_K("imagename"), 1, 1, EKeywordSmrImageName, "output file for SMR image"},
       
   110 	{_K("hcrdata"), 1, 1, EKeywordSmrFileData, "file data for HCR SMR image"},
       
   111 	{_K("formatversion"), 1, 1, EKeywordSmrFormatVersion, "format version for HCR SMR image"},
       
   112 	{_K("payloadflags"), 1, 1, EKeywordSmrFlags, "payload flags for the HCR SMR image"},
       
   113 	{_K("payloaduid"), 1, 1, EKeywordSmrUID, "payload UID for the HCR SMR image"},
       
   114 	{0,0,0,0,EKeywordNone,""}
       
   115 };
       
   116 
       
   117 extern TInt isNumber(TText *aString);
       
   118 extern TInt getNumber(TText *aStr);
       
   119 
       
   120 void ObeyFileReader::KeywordHelp() // static
       
   121 	{
       
   122 	cout << "Obey file keywords:\n";
       
   123 
       
   124 	const ObeyFileKeyword* k=0;
       
   125 	for (k=iKeywords; k->iKeyword!=0; k++)
       
   126 		{
       
   127 		if (k->iHelpText==0)
       
   128 			continue;
       
   129 		if (k->iHelpText[0]=='(' && !H.iVerbose)
       
   130 			continue;	// don't normally report things in (parentheses)
       
   131 
       
   132 		char buf[32];
       
   133 		sprintf(buf, "%-20s", k->iKeyword);
       
   134 		if (k->iKeywordLength)
       
   135 			memcpy(buf+k->iKeywordLength,"[HWVD]",6);
       
   136 		if (H.iVerbose)
       
   137 			sprintf(buf+20,"%2d",k->iNumArgs);
       
   138 		cout << "    " << buf << " " << k->iHelpText << endl;
       
   139 		}
       
   140 	cout << endl;
       
   141 
       
   142 	cout << "File attributes:\n";
       
   143 
       
   144 	const FileAttributeKeyword* f=0;
       
   145 	for (f=iAttributeKeywords; f->iKeyword!=0; f++)
       
   146 		{
       
   147 		if (f->iHelpText==0)
       
   148 			continue;
       
   149 		if (f->iHelpText[0]=='(' && !H.iVerbose)
       
   150 			continue;	// don't normally report things in (parentheses)
       
   151 
       
   152 		char buf[32];
       
   153 		sprintf(buf, "%-20s", f->iKeyword);
       
   154 		if (H.iVerbose)
       
   155 			sprintf(buf+20,"%2d",k->iNumArgs);
       
   156 		cout << "    " << buf << " " << f->iHelpText << endl;
       
   157 		}
       
   158 	cout << endl;
       
   159 	}
       
   160 
       
   161 ObeyFileReader::ObeyFileReader(TText* aFileName):
       
   162 iObeyFile(0),iMark(0), iMarkLine(0), iCurrentMark(0), iCurrentLine(0), imaxLength(0)
       
   163 	{
       
   164 
       
   165 	iFileName = new TText[strlen((const char *)aFileName)+1];
       
   166 	strcpy((char *)iFileName,(const char *)aFileName);
       
   167 	iNumWords = 0 ;
       
   168 	for(unsigned int i = 0 ; i < KNumWords ; i++)
       
   169 		iWord[i] = 0 ;
       
   170 	iSuffix = new TText();
       
   171 	iLine = 0 ;
       
   172 	iCurrentObeyStatement = 0 ;
       
   173 	 }
       
   174 
       
   175 
       
   176 ObeyFileReader::~ObeyFileReader()
       
   177 	{
       
   178 	if (iObeyFile)
       
   179 		fclose(iObeyFile);
       
   180 	iObeyFile=0;
       
   181 	delete [] iFileName;
       
   182 	delete [] iLine;
       
   183 	delete [] iCurrentObeyStatement;
       
   184 	}
       
   185 
       
   186 TBool ObeyFileReader::Open()
       
   187 //
       
   188 // Open the file & return a status
       
   189 //
       
   190 {
       
   191     if (!iFileName)
       
   192     {
       
   193         return EFalse;
       
   194     }
       
   195 
       
   196     iObeyFile = fopen((const char *)iFileName,"r");
       
   197     if (!iObeyFile)
       
   198     {
       
   199         Print(EError,"Cannot open obey file %s\n",iFileName);
       
   200         return EFalse;
       
   201     }
       
   202     if (SetLineLengthBuffer() != KErrNone)
       
   203     {
       
   204         Print(EError,"Insufficent Memory to Continue.");	
       
   205         return EFalse;
       
   206     }
       
   207     return ETrue;
       
   208 }
       
   209    
       
   210  TInt ObeyFileReader::SetLineLengthBuffer()
       
   211  // Get the Max Line length for the given obey file and allocate the buffer.
       
   212  	{
       
   213 	char ch = '\0';
       
   214  	TInt length = 0;
       
   215 		
       
   216 	Rewind();
       
   217  	while ((ch = (char)fgetc(iObeyFile)) != EOF)
       
   218  		{
       
   219  		length++;
       
   220 		if (ch == '\n')
       
   221 			{
       
   222  			if (length > imaxLength)
       
   223  				imaxLength = length;
       
   224  			length = 0;				
       
   225  			}
       
   226  		}
       
   227 	
       
   228 	if (length > imaxLength)
       
   229  		imaxLength = length;
       
   230 		
       
   231 	if (0 == imaxLength)
       
   232 		{
       
   233 		Print(EError,"Empty obey file passed as input.");
       
   234 		exit(-1);
       
   235 		}			
       
   236 	else if (imaxLength < 2)
       
   237 		{
       
   238 		Print(EError,"Invalid obey file passed as input.");
       
   239 		exit(-1);
       
   240 		}
       
   241 		
       
   242 	Rewind();
       
   243  	iLine = new TText[imaxLength+1];
       
   244  	
       
   245  	if(!iLine)
       
   246  		return KErrNoMemory;
       
   247  
       
   248  	return KErrNone;
       
   249  	}
       
   250 
       
   251 void ObeyFileReader::Mark()
       
   252 	{
       
   253 
       
   254 	iMark = iCurrentMark;
       
   255 	iMarkLine = iCurrentLine-1;
       
   256 	}
       
   257 
       
   258 void ObeyFileReader::MarkNext()
       
   259 	{
       
   260 
       
   261 	iMark = ftell(iObeyFile);
       
   262 	iMarkLine = iCurrentLine;
       
   263 	}
       
   264 
       
   265 void ObeyFileReader::Rewind()
       
   266 	{
       
   267 	
       
   268 	fseek(iObeyFile,iMark,SEEK_SET);
       
   269 	iCurrentMark = iMark;
       
   270 	iCurrentLine = iMarkLine;
       
   271 	}
       
   272 
       
   273 void ObeyFileReader::CopyWord(TInt aIndex, TText*& aString)
       
   274 	{
       
   275 	aString = new TText[strlen((const char *)iWord[aIndex])+1];
       
   276 	strcpy((char *)aString, (const char *)iWord[aIndex]);
       
   277 	}
       
   278 
       
   279 TInt ObeyFileReader::ReadAndParseLine()
       
   280 	{
       
   281 	if (feof(iObeyFile))
       
   282 		return KErrEof;
       
   283 	iCurrentLine++;
       
   284 	iCurrentMark = ftell(iObeyFile);
       
   285 	iLine[0]='\0';
       
   286 	char *cp = fgets((char*)iLine,imaxLength+1,iObeyFile); (void)cp;
       
   287 	iCurrentObeyStatement = new TText[imaxLength+1];
       
   288 	strcpy((char*)iCurrentObeyStatement,(char*)iLine);
       
   289 	iNumWords = Parse();
       
   290 	return KErrNone;
       
   291 	}
       
   292 
       
   293 TInt ObeyFileReader::NextLine(TInt aPass, enum EKeyword& aKeyword)
       
   294 	{
       
   295 
       
   296 NextLine:
       
   297 	TInt err = ReadAndParseLine();
       
   298 	if (err == KErrEof)
       
   299 		return KErrEof;
       
   300 	if (iNumWords == 0 || stricmp((const char*)iWord[0], "rem")==0)
       
   301 		goto NextLine;
       
   302 	if (stricmp((const char*)iWord[0], "stop")==0)
       
   303 		return KErrEof;
       
   304 
       
   305 	const ObeyFileKeyword* k=0;
       
   306 	for (k=iKeywords; k->iKeyword!=0; k++)
       
   307 		{
       
   308 		if (k->iKeywordLength == 0)
       
   309 			{
       
   310 			// Exact case-insensitive match on keyword
       
   311 			if (stricmp((const char*)iWord[0], k->iKeyword) != 0)
       
   312 				continue;
       
   313 			iSuffix = 0;
       
   314 			}
       
   315 		else
       
   316 			{
       
   317 			// Prefix match
       
   318 			if (strnicmp((const char*)iWord[0], k->iKeyword, k->iKeywordLength) != 0)
       
   319 				continue;
       
   320 			// Suffix must be empty, or a variant number in []
       
   321 			iSuffix = iWord[0]+k->iKeywordLength;
       
   322 			if (*iSuffix != '\0' && *iSuffix != '[')
       
   323 				continue;
       
   324 			}
       
   325 		// found a match
       
   326 		if ((k->iPass & aPass) == 0)
       
   327 			goto NextLine;
       
   328 		if (k->iNumArgs>=0 && (1+k->iNumArgs != iNumWords))
       
   329 			{
       
   330 			Print(EError, "Incorrect number of arguments for keyword %s on line %d.\n",
       
   331 				iWord[0], iCurrentLine);
       
   332 			goto NextLine;
       
   333 			}
       
   334 		if (k->iNumArgs<0 && (1-k->iNumArgs > iNumWords))
       
   335 			{
       
   336 			Print(EError, "Too few arguments for keyword %s on line %d.\n",
       
   337 				iWord[0], iCurrentLine);
       
   338 			goto NextLine;
       
   339 			}
       
   340 		
       
   341 		aKeyword = k->iKeywordEnum;
       
   342 		return KErrNone;
       
   343 		}
       
   344 	if (aPass == 1)
       
   345 		Print(EWarning, "Unknown keyword '%s'.  Line %d ignored\n", iWord[0], iCurrentLine);
       
   346 	goto NextLine;
       
   347 	}
       
   348 
       
   349 inline TBool ObeyFileReader::IsGap(char ch)
       
   350 	{
       
   351 	return (ch==' ' || ch=='=' || ch=='\t');
       
   352 	}
       
   353 
       
   354 TInt ObeyFileReader::Parse()
       
   355 //
       
   356 // splits a line into words, and returns the number of words found
       
   357 //
       
   358 	{
       
   359 
       
   360 	TInt i;
       
   361 	TText *letter=iLine;
       
   362 	TText *end=iLine+strlen((char *)iLine);
       
   363 	for (i=0; (TUint)i<KNumWords; i++)
       
   364 		iWord[i]=end;
       
   365 
       
   366 	enum TState {EInWord, EInQuotedWord, EInGap};
       
   367 	TState state=EInGap;
       
   368 
       
   369 	i=0;
       
   370 	while ((TUint)i<KNumWords && letter<end)
       
   371 		{
       
   372 		char ch=*letter;
       
   373 		if (ch==0)
       
   374 			break;
       
   375 		if (ch=='\n')
       
   376 			{
       
   377 			*letter='\0';	// remove trailing newline left by fgets
       
   378 			break;
       
   379 			}
       
   380 		switch (state)
       
   381 			{
       
   382 		case EInGap:
       
   383 			if (ch=='\"')
       
   384 				{
       
   385 				if (letter[1]!=0 && letter[1]!='\"')
       
   386 					iWord[i++]=letter+1;
       
   387 				state=EInQuotedWord;
       
   388 				}
       
   389 			else if (!IsGap(ch))
       
   390 				{
       
   391 				iWord[i++]=letter;
       
   392 				state=EInWord;
       
   393 				}
       
   394 			else
       
   395 				*letter=0;
       
   396 			break;
       
   397 		case EInWord:
       
   398 			if (ch=='\"')
       
   399 				{
       
   400 				*letter=0;
       
   401 				if (letter[1]!=0 && letter[1]!='\"')
       
   402 					iWord[i++]=letter+1;
       
   403 				state=EInQuotedWord;
       
   404 				}
       
   405 			else if (IsGap(ch))
       
   406 				{
       
   407 				*letter=0;
       
   408 				state=EInGap;
       
   409 				}
       
   410 			break;
       
   411 		case EInQuotedWord:
       
   412 			if (ch=='\"')
       
   413 				{
       
   414 				*letter=0;
       
   415 				state=EInGap;
       
   416 				}
       
   417 			break;
       
   418 			}
       
   419 		letter++;
       
   420 		}
       
   421 	return i;
       
   422 	}
       
   423 
       
   424 
       
   425 void ObeyFileReader::ProcessTime(TInt64& aTime)
       
   426 //
       
   427 // Process the timestamp
       
   428 //
       
   429 	{
       
   430 	char timebuf[256];
       
   431 	if (iNumWords>2)
       
   432 		sprintf(timebuf, "%s_%s", iWord[1], iWord[2]);
       
   433 	else
       
   434 		strcpy(timebuf, (char*)iWord[1]);
       
   435 
       
   436 	TInt r=StringToTime(aTime, timebuf);
       
   437 	if (r==KErrGeneral)
       
   438 		{
       
   439 		Print(EError, "incorrect format for time keyword on line %d\n", iCurrentLine);
       
   440 		exit(0x670);
       
   441 		}
       
   442 	if (r==KErrArgument)
       
   443 		{
       
   444 		Print(EError, "Time out of range on line %d\n", iCurrentLine);
       
   445 		exit(0x670);
       
   446 		}
       
   447 	}
       
   448 
       
   449 TInt64 ObeyFileReader::iTimeNow=0;
       
   450 void ObeyFileReader::TimeNow(TInt64& aTime)
       
   451 	{
       
   452 	if (iTimeNow==0)
       
   453 		{
       
   454 		TInt sysTime=time(0);					// seconds since midnight Jan 1st, 1970
       
   455 		sysTime-=(30*365*24*60*60+7*24*60*60);	// seconds since midnight Jan 1st, 2000
       
   456 		TInt64 daysTo2000AD=730497;
       
   457 		TInt64 t=daysTo2000AD*24*3600+sysTime;	// seconds since 0000
       
   458 		t=t+3600;								// BST (?)
       
   459 		iTimeNow=t*1000000;						// milliseconds
       
   460 		}
       
   461 	aTime=iTimeNow;
       
   462 	}
       
   463 
       
   464 /**
       
   465 Funtion to get the current oby file line
       
   466 */
       
   467 TText* ObeyFileReader::GetCurrentObeyStatement() const
       
   468 { 
       
   469 	return iCurrentObeyStatement;
       
   470 }
       
   471 
       
   472 // File attributes.
       
   473 
       
   474 
       
   475 const FileAttributeKeyword ObeyFileReader::iAttributeKeywords[] =
       
   476 {
       
   477 	{"attrib",3			,0,1,EAttributeAtt, "File attributes in ROM file system"},
       
   478 	{"exattrib",3		,0,1,EAttributeAttExtra, "File extra attributes in ROM file system"},
       
   479 //	{_K("compress")		,1,1,EAttributeCompress, "Compress file"},
       
   480 	{"stack",3			,1,1,EAttributeStack, "?"},
       
   481 	{"fixed",3			,1,0,EAttributeFixed, "Relocate to a fixed address space"},
       
   482 	{"priority",3		,1,1,EAttributePriority, "Override process priority"},
       
   483 	{_K("uid1")			,1,1,EAttributeUid1, "Override first UID"},
       
   484 	{_K("uid2")			,1,1,EAttributeUid2, "Override second UID"},
       
   485 	{_K("uid3")			,1,1,EAttributeUid3, "Override third UID"},
       
   486 	{_K("heapmin")		,1,1,EAttributeHeapMin, "Override initial heap size"},
       
   487 	{_K("heapmax")		,1,1,EAttributeHeapMax, "Override maximum heap size"},
       
   488 	{_K("capability")	,1,1,EAttributeCapability, "Override capabilities"},
       
   489 	{_K("unpaged")		,1,0,EAttributeUnpaged, "Don't page code or data for this file"},
       
   490 	{_K("paged")		,1,0,EAttributePaged, "Page code and data for this file"},
       
   491 	{_K("unpagedcode")	,1,0,EAttributeUnpagedCode, "Don't page code for this file"},
       
   492 	{_K("pagedcode")	,1,0,EAttributePagedCode, "Page code for this file"},
       
   493 	{_K("unpageddata")	,1,0,EAttributeUnpagedData, "Don't page data for this file"},
       
   494 	{_K("pageddata")	,1,0,EAttributePagedData, "Page data for this file"},
       
   495 	{0,0,0,0,EAttributeAtt,0}
       
   496 };
       
   497 
       
   498 TInt ObeyFileReader::NextAttribute(TInt& aIndex, TInt aHasFile, enum EFileAttribute& aKeyword, TText*& aArg)
       
   499 	{
       
   500 NextAttribute:
       
   501 	if (aIndex >= iNumWords)
       
   502 		return KErrEof;
       
   503 	TText* word=iWord[aIndex++];
       
   504 	const FileAttributeKeyword* k;
       
   505 	for (k=iAttributeKeywords; k->iKeyword!=0; k++)
       
   506 		{
       
   507 		if (k->iKeywordLength == 0)
       
   508 			{
       
   509 			// Exact match on keyword
       
   510 			if (stricmp((const char*)word, k->iKeyword) != 0)
       
   511 				continue;
       
   512 			}
       
   513 		else
       
   514 			{
       
   515 			// Prefix match
       
   516 			if (strnicmp((const char*)word, k->iKeyword, k->iKeywordLength) != 0)
       
   517 				continue;
       
   518 			}
       
   519 		// found a match
       
   520 		if (k->iNumArgs>0)
       
   521 			{
       
   522 			TInt argIndex = aIndex;
       
   523 			aIndex += k->iNumArgs;		// interface only really supports 1 argument
       
   524 			if (aIndex>iNumWords)
       
   525 				{
       
   526 				Print(EError, "Missing argument for attribute %s on line %d\n", word, iCurrentLine);
       
   527 				return KErrArgument;
       
   528 				}
       
   529 			aArg=iWord[argIndex];
       
   530 			}
       
   531 		if (k->iIsFileAttribute && !aHasFile)
       
   532 			{
       
   533 			Print(EError, "File attribute %s applied to non-file on line %d\n", word, iCurrentLine);
       
   534 			return KErrNotSupported;
       
   535 			}
       
   536 		aKeyword=k->iAttributeEnum;
       
   537 		return KErrNone;
       
   538 		}
       
   539 	Print(EWarning, "Unknown attribute '%s' skipped on line %d\n", word, iCurrentLine);
       
   540 	goto NextAttribute;
       
   541 	}
       
   542 
       
   543 
       
   544 
       
   545 /**
       
   546 Constructor:
       
   547 1.Obey file instance.
       
   548 2.used by both rofs and datadrive image.
       
   549 
       
   550 @param aReader - obey file reader object.
       
   551 */
       
   552 CObeyFile::CObeyFile(ObeyFileReader& aReader):
       
   553 	iRomFileName(NULL),
       
   554 	iExtensionRofsName(0),
       
   555 	iKernelRofsName(0),
       
   556 	iRomSize(0),
       
   557 	iVersion(0,0,0),
       
   558 	iCheckSum(0),
       
   559 	iNumberOfFiles(0),
       
   560 	iTime(0),
       
   561 	iRootDirectory(0),
       
   562 	iNumberOfDataFiles(0),
       
   563 	iDriveFileName(0),
       
   564 	iDataSize(0),
       
   565 	iDriveFileFormat(0),
       
   566 	iConfigurableFatAttributes(new ConfigurableFatAttributes),
       
   567 	iReader(aReader), 
       
   568 	iMissingFiles(0), 
       
   569 	iLastExecutable(0),
       
   570 	iFirstFile(0), 	
       
   571 	iCurrentFile(0),
       
   572 	iAutoSize(EFalse),
       
   573 	iAutoPageSize(4096),
       
   574 	iPagingOverrideParsed(0),
       
   575 	iCodePagingOverrideParsed(0),
       
   576 	iDataPagingOverrideParsed(0),
       
   577 	iPatchData(new CPatchDataProcessor)
       
   578 	{
       
   579 		iNextFilePtrPtr = &iFirstFile ;
       
   580 	}
       
   581 
       
   582 /**
       
   583 Obey file Destructor.
       
   584 1.Release the tree memory.
       
   585 2.Release all allocated memory if any.
       
   586 */
       
   587 CObeyFile::~CObeyFile()
       
   588 //
       
   589 // Destructor
       
   590 //
       
   591 	{
       
   592 	if(iDriveFileName)
       
   593 		delete[] iDriveFileName;					
       
   594 	if(iDriveFileFormat)
       
   595 		delete[] iDriveFileFormat;
       
   596 	iRootDirectory->deleteTheFirstNode();                
       
   597 	iRootDirectory->InitializeCount();
       
   598 
       
   599 	Release();
       
   600 	delete [] iRomFileName;
       
   601 	if (iRootDirectory)
       
   602 		iRootDirectory->Destroy();
       
   603 
       
   604 	delete iConfigurableFatAttributes;
       
   605 	delete iPatchData;
       
   606 	}
       
   607 
       
   608 TBool CObeyFile::AutoSize()
       
   609 {
       
   610 	return iAutoSize;
       
   611 }
       
   612 
       
   613 TUint32 CObeyFile::AutoPageSize()
       
   614 {
       
   615 	return iAutoPageSize;
       
   616 }
       
   617 
       
   618 void CObeyFile::Release()
       
   619 //
       
   620 // Free resources not needed after building a ROM
       
   621 //
       
   622 	{
       
   623 	iFirstFile = 0;
       
   624 	iNextFilePtrPtr = &iFirstFile;
       
   625 	}
       
   626 
       
   627 TRomBuilderEntry *CObeyFile::FirstFile()
       
   628 	{
       
   629 	iCurrentFile = iFirstFile;
       
   630 	return iCurrentFile;
       
   631 	}
       
   632 
       
   633 TRomBuilderEntry *CObeyFile::NextFile()
       
   634 	{
       
   635 	iCurrentFile = iCurrentFile ? iCurrentFile->iNext : 0;
       
   636 	return iCurrentFile;
       
   637 	}
       
   638 
       
   639 TText* CObeyFile::ProcessCoreImage()
       
   640 	{
       
   641 	// check for coreimage keyword and return filename
       
   642 	iReader.Rewind();
       
   643 	enum EKeyword keyword;
       
   644 	TText* coreImageFileName = 0;
       
   645 	while (iReader.NextLine(1,keyword) != KErrEof)
       
   646 		{
       
   647 		if (keyword == EKeywordCoreImage)
       
   648 			{
       
   649 			istringstream val(iReader.Word(1),ios_base::in|ios_base::out);	  
       
   650 			iReader.CopyWord(1, coreImageFileName);
       
   651 			iReader.MarkNext(); // ready for processing extension
       
   652 			break;
       
   653 			}
       
   654 		}
       
   655 		return coreImageFileName;
       
   656 	}
       
   657 
       
   658 void CObeyFile::SkipToExtension()
       
   659 	{
       
   660 	iReader.Rewind();
       
   661 	enum EKeyword keyword;
       
   662 	while (iReader.NextLine(1,keyword) != KErrEof)
       
   663 		{
       
   664 		  if (keyword == EKeywordExtensionRofs)
       
   665 			  {
       
   666 			  iReader.Mark(); // ready for processing extension
       
   667 			  break;
       
   668 			  }
       
   669 		}
       
   670 	}
       
   671 TInt CObeyFile::ProcessRofs()
       
   672 	{
       
   673 	//
       
   674 	// First pass through the obey file to set up key variables
       
   675 	//
       
   676 
       
   677 	iReader.Rewind();
       
   678 
       
   679 	TInt count=0;
       
   680 	enum EKeyword keyword;
       
   681 	while (iReader.NextLine(1,keyword) != KErrEof)
       
   682 		{
       
   683 		  if (keyword == EKeywordExtensionRofs)
       
   684 		    {
       
   685 		      if (count==0)
       
   686 			return KErrNotFound;		// no core ROFS, just extension ROFSs.
       
   687 		      break;
       
   688 		    }
       
   689 
       
   690 		count++;
       
   691 		if (! ProcessKeyword(keyword))
       
   692 			return KErrGeneral;
       
   693 		}
       
   694 
       
   695 	if (!GotKeyVariables())
       
   696 		return KErrGeneral;
       
   697 
       
   698 	//
       
   699 	// second pass to process the file specifications in the obey file building
       
   700 	// up the TRomNode directory structure and the TRomBuilderEntry list
       
   701 	//
       
   702 	iReader.Rewind();
       
   703 
       
   704 	iRootDirectory = new TRomNode((TText*)"");
       
   705 	iLastExecutable = iRootDirectory;
       
   706 
       
   707 	TInt align=0;
       
   708 	while (iReader.NextLine(2,keyword)!=KErrEof)
       
   709 		{
       
   710 		if (keyword == EKeywordExtensionRofs)
       
   711 			break;
       
   712 
       
   713 		if (keyword == EKeywordHide)
       
   714 			keyword = EKeywordHideV2;
       
   715 
       
   716 		switch (keyword)
       
   717 			{
       
   718 			  
       
   719 		case EKeywordHide:
       
   720 		case EKeywordAlias:
       
   721 		case EKeywordRename:
       
   722 			if (!ProcessRenaming(keyword))
       
   723 				return KErrGeneral;
       
   724 			break;
       
   725 		case EKeywordPatchDllData:
       
   726 		{
       
   727 			// Collect patchdata statements to process at the end
       
   728 			StringVector patchDataTokens;
       
   729 			SplitPatchDataStatement(patchDataTokens); 
       
   730 			iPatchData->AddPatchDataStatement(patchDataTokens);									
       
   731 			break;
       
   732 		}
       
   733 		default:
       
   734 		        if (!ProcessFile(align, keyword))
       
   735 		        return KErrGeneral;
       
   736 		        align=0;
       
   737 		        break;
       
   738 			}
       
   739 		}
       
   740 
       
   741 	if(!ParsePatchDllData())
       
   742 		return KErrGeneral;
       
   743 	iReader.Mark();			// ready for processing the extension rom(s)
       
   744 
       
   745 	if (iMissingFiles!=0)
       
   746 		{
       
   747 		return KErrGeneral;
       
   748 		}
       
   749 	if ( 0 == iNumberOfFiles )
       
   750 		{
       
   751 		Print(EError, "No files specified.\n");
       
   752 		return KErrGeneral;
       
   753 		}
       
   754 
       
   755 	return KErrNone;
       
   756 	}
       
   757 
       
   758 TBool CObeyFile::Process()
       
   759 {
       
   760 	TBool result = ETrue;
       
   761 	iReader.Rewind();
       
   762 	enum EKeyword keyword;
       
   763 	while(iReader.NextLine(1, keyword) != KErrEof)
       
   764 	{
       
   765 		String key = iReader.Word(0);
       
   766 		String value = iReader.Word(1);
       
   767 		if(iKeyValues.find(key) != iKeyValues.end())
       
   768 		{
       
   769 			iKeyValues[key].push_back(value);
       
   770 		}
       
   771 		else
       
   772 		{
       
   773 			StringVector values;
       
   774 			values.push_back(value);
       
   775 			iKeyValues[key]=values;
       
   776 		}
       
   777 
       
   778 
       
   779 	}
       
   780 	return result;
       
   781 }
       
   782 StringVector CObeyFile::getValues(const String& aKey)
       
   783 {
       
   784 	StringVector values;
       
   785 	if(iKeyValues.find(aKey) != iKeyValues.end())
       
   786 	{
       
   787 		values = iKeyValues[aKey];
       
   788 	}
       
   789 	return values;
       
   790 }
       
   791 
       
   792 /**
       
   793 Process drive obey file and construct the tree.
       
   794 
       
   795 @return - Return the status,
       
   796           'KErrnone' for Success,
       
   797           'KErrGeneral' for failure (required keywords not there in obey file or failed
       
   798 									 to construct the tree).
       
   799 */
       
   800 TInt CObeyFile::ProcessDataDrive()
       
   801 	{
       
   802 
       
   803 	iReader.Rewind();
       
   804 	enum EKeyword keyword;
       
   805 
       
   806 	// First pass through the obey file to set up key variables
       
   807 	while (iReader.NextLine(1,keyword) != KErrEof)	
       
   808 		{
       
   809 		if (!ProcessDriveKeyword(keyword))			
       
   810 			return KErrGeneral;
       
   811 		}
       
   812 
       
   813 	if (!GotKeyDriveVariables())
       
   814 		return KErrGeneral;
       
   815 
       
   816 	// Second pass to process the file specifications in the obey file.
       
   817 	// Build the TRomNode directory structure and the TRomBuilderEntry list
       
   818 	iReader.Rewind();
       
   819 	iRootDirectory = new TRomNode((TText*)"//");					
       
   820 	iLastExecutable = iRootDirectory;
       
   821 
       
   822 	while(iReader.NextLine(2,keyword)!=KErrEof)
       
   823 		{
       
   824 		switch (keyword)
       
   825 			{
       
   826 			case EKeywordPatchDllData:
       
   827 			{	// Collect patchdata statements to process at the end
       
   828 				StringVector patchDataTokens;
       
   829 				SplitPatchDataStatement(patchDataTokens); 				
       
   830 				iPatchData->AddPatchDataStatement(patchDataTokens);									
       
   831 				break;
       
   832 			}
       
   833 	
       
   834 			case EKeywordHide:						
       
   835 			case EKeywordFile:
       
   836 			case EKeywordData:
       
   837 			case EKeywordFileCompress:
       
   838 			case EKeywordFileUncompress:
       
   839 		        if (!ProcessDriveFile(keyword))
       
   840 				  return KErrGeneral;
       
   841 		        break;
       
   842 	
       
   843 			default:							
       
   844 		        break;
       
   845 			}
       
   846 		}
       
   847 
       
   848 	if(!ParsePatchDllData())
       
   849 		return KErrGeneral;
       
   850     if (iMissingFiles)   
       
   851 		{
       
   852 		Print(EError, "Source Files Missing.\n");
       
   853 		return KErrGeneral;
       
   854 		}
       
   855 	if (!iNumberOfFiles)
       
   856 		Print(EWarning,"No files specified.\n");
       
   857 	
       
   858 	return KErrNone;
       
   859 	}
       
   860 
       
   861 
       
   862 /**
       
   863 Process and stores the keyword information.
       
   864 
       
   865 @param aKeyword - keyword to update its value to variables.
       
   866 @return - Return the status i.e Success,
       
   867 */
       
   868 TBool CObeyFile::ProcessDriveKeyword(enum EKeyword aKeyword)
       
   869 	{
       
   870 
       
   871 	TBool success = ETrue;
       
   872 	switch (aKeyword)
       
   873 		{
       
   874 		case EKeywordDataImageName:
       
   875 			iReader.CopyWord(1, iDriveFileName);
       
   876 			break;
       
   877 		case EKeywordDataImageFileSystem:
       
   878 			iReader.CopyWord(1, iDriveFileFormat);
       
   879 			break;
       
   880 		case EKeywordDataImageSize:
       
   881 			{
       
   882 			char* bigString = iReader.Word(1);
       
   883 			if(*bigString == '\0')
       
   884 				{
       
   885 				Print(EWarning,"Not a valid Image Size. Default size is considered\n");		
       
   886 				break;
       
   887 				}
       
   888 #ifdef __LINUX__
       
   889 			errno = 0;
       
   890 			iDataSize = strtoll(bigString,NULL,10);
       
   891 			if((iDataSize == LONG_MAX) || (iDataSize == LONG_MIN) ||(errno == ERANGE))
       
   892 				{
       
   893 				Print(EWarning,"Invalid Range. Default size is considered\n");		
       
   894 				}
       
   895 #else
       
   896 			iDataSize = _atoi64(bigString);
       
   897 #endif
       
   898 			}
       
   899 			break;
       
   900 		case EKeywordDataImageVolume:
       
   901 			{				
       
   902 				// Get the volume label provided by using "volume" keyword.
       
   903 				// e.g. vlolume = NO NAME
       
   904 				String volumeLabel = (char*)iReader.GetCurrentObeyStatement();
       
   905 				String volumeLabelKeyword = "volume";
       
   906 
       
   907 				TUint position = volumeLabel.find(volumeLabelKeyword.c_str(),0,volumeLabelKeyword.size());
       
   908 				position += volumeLabelKeyword.size();
       
   909 				if (volumeLabel.find('=',position) != std::string::npos)
       
   910 				{
       
   911 					position=volumeLabel.find('=',position);
       
   912 					++position;
       
   913 				}								
       
   914 
       
   915 				position = volumeLabel.find_first_not_of(' ',position);
       
   916 				if (position != std::string::npos)
       
   917 				{
       
   918 					volumeLabel = volumeLabel.substr(position);
       
   919 
       
   920 					// Remove the new line character from the end
       
   921 					position = volumeLabel.find_first_of("\r\n");
       
   922 					if (position != std::string::npos)
       
   923 						volumeLabel = volumeLabel.substr(0,position);
       
   924 
       
   925 					iConfigurableFatAttributes->iDriveVolumeLabel = volumeLabel.data(); 								
       
   926 				}
       
   927 				else
       
   928 				{
       
   929 					Print(EWarning,"Value for Volume Label is not provided. Default value is considered.\n");
       
   930 				}
       
   931 				break;
       
   932 			}
       
   933 		case EKeywordDataImageSectorSize:
       
   934 			{
       
   935 				char* bigString = iReader.Word(1);
       
   936 				TInt sectorSize = atoi(bigString);
       
   937 				if(sectorSize <= 0)
       
   938 				{
       
   939 					Print(EWarning,"Invalid Sector Size value. Default value is considered.\n");
       
   940 				}
       
   941 				else
       
   942 				{
       
   943 					iConfigurableFatAttributes->iDriveSectorSize = atoi(bigString);
       
   944 				}
       
   945 			}			
       
   946 			break;
       
   947 		case EKeywordDataImageNoOfFats:
       
   948 			{
       
   949 				char* bigString = iReader.Word(1);
       
   950 				TInt noOfFats = atoi(bigString);
       
   951 				if (noOfFats <=0)
       
   952 				{
       
   953 					Print(EWarning,"Invalid No of FATs specified. Default value is considered.\n");
       
   954 				}
       
   955 				else
       
   956 				{
       
   957 					iConfigurableFatAttributes->iDriveNoOfFATs = atoi(bigString);			
       
   958 				}
       
   959 			}			
       
   960 			break;			
       
   961 		default:
       
   962 			// unexpected keyword iReader.Word(0), keep going.
       
   963 			break;
       
   964 		}
       
   965 	return success;
       
   966 	}
       
   967 
       
   968 
       
   969 /**
       
   970 Checks whether obeyfile has supplied enough variables to continue.
       
   971 
       
   972 @return - Return the status 
       
   973 		  ETrue - Supplied valid values,
       
   974 		  EFalse- Not valied values.
       
   975 */
       
   976 TBool CObeyFile::GotKeyDriveVariables()
       
   977    	{
       
   978 
       
   979 	TBool retVal=ETrue;
       
   980 
       
   981 	// Mandatory keywords
       
   982 	if (iDriveFileName==0)                             
       
   983 		{                                                  
       
   984 		Print(EError,"The name of the image file has not been supplied.\n");
       
   985 		Print(EError,"Use the keyword \"dataimagename\".\n");
       
   986 		retVal = EFalse;
       
   987 		}
       
   988 		
       
   989 	// Check for '-'ve entered value.
       
   990 	if(iDataSize <= 0)
       
   991 		{
       
   992 		Print(EWarning,"Image Size should be positive. Default size is Considered.\n");
       
   993 		}
       
   994 
       
   995 	// File system format.
       
   996 	if(iDriveFileFormat==0)
       
   997 		{
       
   998 		Print(EError,"The name of the file system not been supplied.\n");
       
   999 		Print(EError,"Use the keyword \"dataimagefilesystem\".\n");
       
  1000 		retVal = EFalse;
       
  1001 		}
       
  1002 
       
  1003 	// Checking the validity of file system format.
       
  1004 	if(iDriveFileFormat)
       
  1005 		{
       
  1006 		strupr((char *)iDriveFileFormat);
       
  1007 		enum TFileSystem check = (TFileSystem)0;
       
  1008 		if(!(CDriveImage::FormatTranslation(iDriveFileFormat,check)))
       
  1009 			{
       
  1010 			Print(EError,"The name of the file system not supported : %s\n",iDriveFileFormat);
       
  1011 			retVal = EFalse;
       
  1012 			}
       
  1013 		}
       
  1014 	
       
  1015 	if(retVal)
       
  1016 		Print(ELog,"\nCreating Data Drive image : %s\n", iDriveFileName);
       
  1017 
       
  1018   	return retVal;
       
  1019 	}
       
  1020 
       
  1021 /**
       
  1022 Process a parsed line to set up one or more new TRomBuilder entry objects.
       
  1023 
       
  1024 @param  - obey file keyword.
       
  1025 // iWord[0] = the keyword (file,)      
       
  1026 // iWord[1] = the PC pathname
       
  1027 // iWord[2] = the EPOC pathname
       
  1028 // iWord[3] = start of the file attributes
       
  1029 
       
  1030 @return - Return the status 
       
  1031 		  ETrue - Successful generation of tree.
       
  1032 		  EFalse- Fail to generate the tree.
       
  1033 */
       
  1034 TBool CObeyFile::ProcessDriveFile(enum EKeyword aKeyword)               
       
  1035 	{
       
  1036 
       
  1037 	TBool isPeFile = ETrue;
       
  1038 	TBool aFileCompressOption, aFileUncompressOption;
       
  1039 
       
  1040 	TInt epocPathStart=2;
       
  1041 	aFileCompressOption = aFileUncompressOption = EFalse;
       
  1042 	// do some validation of the keyword
       
  1043 	TInt currentLine = iReader.CurrentLine();
       
  1044 
       
  1045 	switch (aKeyword)
       
  1046 		{
       
  1047 		case EKeywordData:
       
  1048 		case EKeywordHide:
       
  1049 			isPeFile = EFalse;
       
  1050 			break;
       
  1051 
       
  1052 		case EKeywordFile:
       
  1053 			break;
       
  1054 
       
  1055 		case EKeywordFileCompress:
       
  1056 			aFileCompressOption = ETrue;
       
  1057 			break;
       
  1058 
       
  1059 		case EKeywordFileUncompress:
       
  1060 			aFileUncompressOption = ETrue;
       
  1061 			break;
       
  1062 
       
  1063 		default:
       
  1064 			return EFalse;
       
  1065 		}
       
  1066 
       
  1067 	if (aKeyword!=EKeywordHide)
       
  1068 		{
       
  1069 		// check the PC file exists
       
  1070 		char* nname = NormaliseFileName(iReader.Word(1));                 
       
  1071 
       
  1072 #if defined(__MSVCDOTNET__) || defined(__TOOLS2__)																		  
       
  1073 		ifstream test(nname);
       
  1074 #else //!__MSVCDOTNET__
       
  1075 		ifstream test(nname, ios::nocreate);
       
  1076 #endif //__MSVCDOTNET__
       
  1077 
       
  1078 		if (!test)
       
  1079 			{
       
  1080 			Print(EError,"Cannot open file %s for input.\n",iReader.Word(1));
       
  1081 			iMissingFiles++;
       
  1082 			}
       
  1083 
       
  1084 		test.close();
       
  1085 		if(nname)
       
  1086 			free(nname);												
       
  1087 		nname = 0;
       
  1088 		}
       
  1089 	else
       
  1090 		epocPathStart=1;   
       
  1091 
       
  1092 	iNumberOfFiles++;
       
  1093 
       
  1094 	TBool endOfName=EFalse;
       
  1095 	TText *epocStartPtr=IsValidFilePath(iReader.Text(epocPathStart));
       
  1096 	TText *epocEndPtr=epocStartPtr;
       
  1097 
       
  1098 	if (epocStartPtr==NULL)
       
  1099 		{
       
  1100 		Print(EError, "Invalid destination path on line %d\n",currentLine);
       
  1101 		return EFalse;
       
  1102 		}
       
  1103 
       
  1104 	TRomNode* dir=iRootDirectory;
       
  1105 	TRomNode* subDir=0;
       
  1106 	TRomBuilderEntry *file=0;      
       
  1107 
       
  1108 	while (!endOfName)
       
  1109 		{
       
  1110 		endOfName = GetNextBitOfFileName(&epocEndPtr);      
       
  1111 		if (endOfName) // file
       
  1112 			{
       
  1113 			TRomNode* alreadyExists=dir->FindInDirectory(epocStartPtr);
       
  1114 
       
  1115 			if ((aKeyword != EKeywordHide) && alreadyExists) // duplicate file
       
  1116 				{
       
  1117 				Print(EError, "Duplicate file for %s on line %d\n",iReader.Word(1),iReader.CurrentLine());
       
  1118 				return EFalse;
       
  1119 				}
       
  1120 			else if((aKeyword == EKeywordHide) && (alreadyExists))
       
  1121 				{ 
       
  1122 				alreadyExists->iEntry->iHidden = ETrue;
       
  1123 				alreadyExists->iHidden = ETrue;
       
  1124 				return ETrue;
       
  1125 				}
       
  1126 			else if((aKeyword == EKeywordHide) && (!alreadyExists))
       
  1127 				{
       
  1128 				Print(EWarning, "Hiding non-existent file %s on line %d\n",iReader.Word(1),iReader.CurrentLine());
       
  1129 				return ETrue;
       
  1130 				}
       
  1131 				
       
  1132 			file = new TRomBuilderEntry(iReader.Word(1), epocStartPtr);                   
       
  1133 			file->iExecutable=isPeFile;
       
  1134 			if( aFileCompressOption )
       
  1135 			{
       
  1136 			file->iCompressEnabled = ECompressionCompress;
       
  1137 			}
       
  1138 			else if(aFileUncompressOption )
       
  1139 			{
       
  1140 			file->iCompressEnabled = ECompressionUncompress;
       
  1141 			}
       
  1142 			
       
  1143 			TRomNode* node=new TRomNode(epocStartPtr, file);
       
  1144 			if (node==0)
       
  1145 				return EFalse;
       
  1146 
       
  1147 			TInt r=ParseFileAttributes(node, file, aKeyword);         
       
  1148 			if (r!=KErrNone)
       
  1149 				return EFalse;
       
  1150 
       
  1151 			if(gCompress != ECompressionUnknown)
       
  1152 			{
       
  1153 			node->iFileUpdate = ETrue;
       
  1154 			}
       
  1155 
       
  1156 			if((node->iOverride) || (aFileCompressOption) || (aFileUncompressOption))
       
  1157 			{
       
  1158 			node->iFileUpdate = ETrue;
       
  1159 			}
       
  1160 
       
  1161 			dir->AddFile(node);	// to drive directory structure.
       
  1162 			}		 
       
  1163 		else	
       
  1164 		{
       
  1165 		// directory
       
  1166 		subDir = dir->FindInDirectory(epocStartPtr);      
       
  1167 		if (!subDir) // sub directory does not exist
       
  1168 			{
       
  1169 			if(aKeyword==EKeywordHide)
       
  1170 			{
       
  1171 			Print(EWarning, "Hiding non-existent file %s on line %d\n",iReader.Word(1),iReader.CurrentLine());
       
  1172 			return ETrue;
       
  1173 			}
       
  1174 			subDir = dir->NewSubDir(epocStartPtr);
       
  1175 			if (!subDir)
       
  1176 				return EFalse;
       
  1177 			}
       
  1178 			dir=subDir;
       
  1179 
       
  1180 			epocStartPtr = epocEndPtr;
       
  1181 			}  // end of else.
       
  1182 		}
       
  1183 	return ETrue;
       
  1184 	}
       
  1185 
       
  1186 
       
  1187 TInt CObeyFile::SetStackSize(TRomNode *aNode, TText *aStr)
       
  1188 	{
       
  1189 	if (isNumber(aStr)==0)
       
  1190 		return Print(EError, "Number required as argument for keyword 'stack'.\n");
       
  1191 	aNode->SetStackSize( getNumber(aStr) );
       
  1192 	return KErrNone;
       
  1193 	}
       
  1194 
       
  1195 TInt CObeyFile::SetHeapSizeMin(TRomNode *aNode, TText *aStr)
       
  1196 	{
       
  1197 	if (isNumber(aStr)==0)
       
  1198 		return Print(EError, "Number required as argument for keyword 'heapmin'.\n");
       
  1199 	aNode->SetHeapSizeMin( getNumber(aStr) );
       
  1200 	return KErrNone;
       
  1201 	}
       
  1202 
       
  1203 TInt CObeyFile::SetHeapSizeMax(TRomNode *aNode, TText *aStr)
       
  1204 	{
       
  1205 	if (isNumber(aStr)==0)
       
  1206 		return Print(EError, "Number required as argument for keyword 'heapmax'.\n");
       
  1207 	aNode->SetHeapSizeMax( getNumber(aStr) );
       
  1208 	return KErrNone;
       
  1209 	}
       
  1210 
       
  1211 TInt CObeyFile::SetCapability(TRomNode *aNode, TText *aStr)
       
  1212 	{
       
  1213 	if (isNumber(aStr))
       
  1214 		{
       
  1215 		Print(EDiagnostic,"Old style numeric CAPABILTY specification ignored.\n");
       
  1216 		return KErrNone;
       
  1217 		}
       
  1218 	SCapabilitySet cap;
       
  1219 	TInt r = ParseCapabilitiesArg(cap, (char*)aStr);
       
  1220 	if( KErrNone == r )
       
  1221 		{
       
  1222 		aNode->SetCapability( cap );
       
  1223 		}
       
  1224 	return r;
       
  1225 	}
       
  1226 
       
  1227 TInt CObeyFile::SetPriority(TRomNode *aNode, TText *aStr)
       
  1228 	{
       
  1229 	TProcessPriority priority;
       
  1230 	if (isNumber(aStr))
       
  1231 		{
       
  1232 		priority = (TProcessPriority)getNumber(aStr);
       
  1233 		}
       
  1234 	else
       
  1235 		{
       
  1236 		char *str=(char *)aStr;
       
  1237 		if (stricmp(str, "low")==0)
       
  1238 			priority=EPriorityLow;
       
  1239 		else if (strnicmp(str, "background", 4)==0)
       
  1240 			priority=EPriorityBackground;
       
  1241 		else if (strnicmp(str, "foreground", 4)==0)
       
  1242 			priority=EPriorityForeground;
       
  1243 		else if (stricmp(str, "high")==0)
       
  1244 			priority=EPriorityHigh;
       
  1245 		else if (strnicmp(str, "windowserver",3)==0)
       
  1246 			priority=EPriorityWindowServer;
       
  1247 		else if (strnicmp(str, "fileserver",4)==0)
       
  1248 			priority=EPriorityFileServer;
       
  1249 		else if (strnicmp(str, "realtimeserver",4)==0)
       
  1250 			priority=EPriorityRealTimeServer;
       
  1251 		else if (strnicmp(str, "supervisor",3)==0)
       
  1252 			priority=EPrioritySupervisor;
       
  1253 		else
       
  1254 			return Print(EError, "Unrecognised priority keyword.\n");
       
  1255 		}
       
  1256 	if (priority<EPriorityLow || priority>EPrioritySupervisor)
       
  1257 		return Print(EError, "Priority out of range.\n");
       
  1258 
       
  1259 	aNode->SetPriority( priority );
       
  1260 	return KErrNone;
       
  1261 	}
       
  1262 
       
  1263 TInt CObeyFile::SetUid1(TRomNode *aNode, TText *aStr)
       
  1264 	{
       
  1265 	if (isNumber(aStr)==0)
       
  1266 		return Print(EError, "Number required as argument for keyword 'uid1'.\n");
       
  1267 	aNode->SetUid1( getNumber(aStr) );
       
  1268 	return KErrNone;
       
  1269 	}
       
  1270 TInt CObeyFile::SetUid2(TRomNode *aNode, TText *aStr)
       
  1271 	{
       
  1272 	if (isNumber(aStr)==0)
       
  1273 		return Print(EError, "Number required as argument for keyword 'uid2'.\n");
       
  1274 	aNode->SetUid2( getNumber(aStr) );
       
  1275 	return KErrNone;
       
  1276 	}
       
  1277 TInt CObeyFile::SetUid3(TRomNode *aNode, TText *aStr)
       
  1278 	{
       
  1279 	if (isNumber(aStr)==0)
       
  1280 		return Print(EError, "Number required as argument for keyword 'uid3'.\n");
       
  1281 	aNode->SetUid3( getNumber(aStr) );
       
  1282 	return KErrNone;
       
  1283 	}
       
  1284 
       
  1285 
       
  1286 TInt CObeyFile::ParseFileAttributes(TRomNode *aNode, TRomBuilderEntry* aFile, enum EKeyword aKeyword)
       
  1287 //
       
  1288 // Process any inline keywords
       
  1289 //
       
  1290 	{
       
  1291 	TInt currentLine = iReader.CurrentLine();
       
  1292 	enum EFileAttribute attribute;
       
  1293 	TInt r=KErrNone;
       
  1294 	TInt index=3;
       
  1295 	TText* arg=0;
       
  1296 
       
  1297 	while(r==KErrNone)
       
  1298 		{
       
  1299 		r=iReader.NextAttribute(index,(aFile!=0),attribute,arg);
       
  1300 		if (r!=KErrNone)
       
  1301 			break;
       
  1302 		switch(attribute)
       
  1303 			{
       
  1304 		case EAttributeAtt:
       
  1305 			r=aNode->SetAtt(arg);
       
  1306 			break;
       
  1307 		case EAttributeAttExtra:
       
  1308 			r=aNode->SetAttExtra(arg, aFile, aKeyword);
       
  1309 			break;
       
  1310 		case EAttributeStack:
       
  1311 			r=SetStackSize(aNode, arg);
       
  1312 			break;
       
  1313 		case EAttributeFixed:
       
  1314 			aNode->SetFixed();
       
  1315 			r = KErrNone;
       
  1316 			break;
       
  1317 		case EAttributeUid1:
       
  1318 			r=SetUid1(aNode, arg);
       
  1319 			break;
       
  1320 		case EAttributeUid2:
       
  1321 			r=SetUid2(aNode, arg);
       
  1322 			break;
       
  1323 		case EAttributeUid3:
       
  1324 			r=SetUid3(aNode, arg);
       
  1325 			break;
       
  1326 		case EAttributeHeapMin:
       
  1327 			r=SetHeapSizeMin(aNode, arg);
       
  1328 			break;
       
  1329 		case EAttributeHeapMax:
       
  1330 			r=SetHeapSizeMax(aNode, arg);
       
  1331 			break;
       
  1332 		case EAttributePriority:
       
  1333 			r=SetPriority(aNode, arg);
       
  1334 			break;
       
  1335 		case EAttributeCapability:
       
  1336 			r=SetCapability(aNode, arg);
       
  1337 			break;
       
  1338 		case EAttributeUnpaged:
       
  1339 			aNode->iOverride |= KOverrideCodeUnpaged|KOverrideDataUnpaged;
       
  1340 			aNode->iOverride &= ~(KOverrideCodePaged|KOverrideDataPaged);
       
  1341 			break;
       
  1342 		case EAttributePaged:
       
  1343 			aNode->iOverride |= KOverrideCodePaged|KOverrideDataPaged;
       
  1344 			aNode->iOverride &= ~(KOverrideCodeUnpaged|KOverrideDataUnpaged);
       
  1345 			break;
       
  1346 		case EAttributeUnpagedCode:
       
  1347 			aNode->iOverride |= KOverrideCodeUnpaged;
       
  1348 			aNode->iOverride &= ~KOverrideCodePaged;
       
  1349 			break;
       
  1350 		case EAttributePagedCode:
       
  1351 			aNode->iOverride |= KOverrideCodePaged;
       
  1352 			aNode->iOverride &= ~KOverrideCodeUnpaged;
       
  1353 			break;
       
  1354 		case EAttributeUnpagedData:
       
  1355 			aNode->iOverride |= KOverrideDataUnpaged;
       
  1356 			aNode->iOverride &= ~KOverrideDataPaged;
       
  1357 			break;
       
  1358 		case EAttributePagedData:
       
  1359 			aNode->iOverride |= KOverrideDataPaged;
       
  1360 			aNode->iOverride &= ~KOverrideDataUnpaged;
       
  1361 			break;
       
  1362 
       
  1363 		default:
       
  1364 			return Print(EError, "Unrecognised keyword in file attributes on line %d.\n",currentLine);
       
  1365 			}
       
  1366 		}
       
  1367 
       
  1368 	if (r==KErrEof)
       
  1369 		return KErrNone;
       
  1370 	return r;
       
  1371 	}
       
  1372 
       
  1373 
       
  1374 TBool CObeyFile::ProcessFile(TInt /*aAlign*/, enum EKeyword aKeyword)
       
  1375 //
       
  1376 // Process a parsed line to set up one or more new TRomBuilder entry objects.
       
  1377 // iWord[0] = the keyword (file, primary or secondary)
       
  1378 // iWord[1] = the PC pathname
       
  1379 // iWord[2] = the EPOC pathname
       
  1380 // iWord[3] = start of the file attributes
       
  1381 //
       
  1382 	{
       
  1383 	TBool isPeFile = ETrue;
       
  1384 	TBool aFileCompressOption, aFileUncompressOption;
       
  1385 	TInt epocPathStart=2;
       
  1386 	aFileCompressOption = aFileUncompressOption = EFalse;
       
  1387  	TBool warnFlag = EFalse;
       
  1388  	static const char aStdPath[] = "SYS\\BIN\\";
       
  1389  	static const int sysBinLength = sizeof(aStdPath)-1;
       
  1390 
       
  1391 	// do some validation of the keyword
       
  1392 	TInt currentLine = iReader.CurrentLine();
       
  1393 
       
  1394 	switch (aKeyword)
       
  1395 		{
       
  1396 	case EKeywordData:
       
  1397 	case EKeywordHideV2:
       
  1398 		iNumberOfDataFiles++;
       
  1399 		isPeFile = EFalse;
       
  1400 		break;
       
  1401 
       
  1402 	case EKeywordFile:
       
  1403 		warnFlag = gEnableStdPathWarning;
       
  1404 		break;
       
  1405 	case EKeywordFileCompress:
       
  1406 		aFileCompressOption = ETrue;
       
  1407 		warnFlag = gEnableStdPathWarning;
       
  1408 		break;
       
  1409 	case EKeywordFileUncompress:
       
  1410 		aFileUncompressOption = ETrue;
       
  1411 		warnFlag = gEnableStdPathWarning;
       
  1412 		break;
       
  1413 
       
  1414 	default:
       
  1415 		Print(EError,"Unexpected keyword '%s' on line %d.\n",iReader.Word(0),currentLine);
       
  1416 		return EFalse;
       
  1417 		}
       
  1418 
       
  1419 	if (aKeyword!=EKeywordHideV2)
       
  1420 		{
       
  1421 
       
  1422 		// check the PC file exists
       
  1423 		char* nname = NormaliseFileName(iReader.Word(1));
       
  1424 
       
  1425 #if defined(__MSVCDOTNET__) || defined(__TOOLS2__)
       
  1426 		ifstream test(nname);
       
  1427 #else //!__MSVCDOTNET__
       
  1428 		ifstream test(nname, ios::nocreate);
       
  1429 #endif //__MSVCDOTNET__
       
  1430 
       
  1431 		if (!test)
       
  1432 			{
       
  1433 			Print(EError,"Cannot open file %s for input.\n",iReader.Word(1));
       
  1434 			iMissingFiles++;
       
  1435 			}
       
  1436 		test.close();
       
  1437 		free(nname);
       
  1438 		}
       
  1439 	else
       
  1440 		epocPathStart=1;
       
  1441 
       
  1442 	iNumberOfFiles++;
       
  1443 
       
  1444 
       
  1445  	TBool endOfName=EFalse;
       
  1446 	TText *epocStartPtr=IsValidFilePath(iReader.Text(epocPathStart));
       
  1447 	TText *epocEndPtr=epocStartPtr;
       
  1448 	if (epocStartPtr==NULL)
       
  1449 		{
       
  1450 		Print(EError, "Invalid destination path on line %d\n",currentLine);
       
  1451 		return EFalse;
       
  1452 		}
       
  1453  	if(warnFlag)	// Check for the std destination path(for executables) as per platsec.
       
  1454  		{
       
  1455  		if(strnicmp(aStdPath,(const char*)epocStartPtr,sysBinLength) != 0)
       
  1456  			{
       
  1457  			Print(EWarning,"Invalid destination path on line %d. \"%s\" \n",currentLine,epocStartPtr);
       
  1458  			}
       
  1459 		}
       
  1460 	
       
  1461 	TRomNode* dir=iRootDirectory;
       
  1462 	TRomNode* subDir=0;
       
  1463 	TRomBuilderEntry *file=0;
       
  1464 	while (!endOfName)
       
  1465 		{
       
  1466 		endOfName = GetNextBitOfFileName(&epocEndPtr);
       
  1467 		if (endOfName) // file
       
  1468 			{
       
  1469 			TRomNode* alreadyExists=dir->FindInDirectory(epocStartPtr);
       
  1470 			/*
       
  1471 			 * The EKeywordHideV2 keyword is used to indicate that:
       
  1472 			 *	1. if the file exists in the same image and then hidden, mark it hidden
       
  1473 			 *	2. if the file exists in another image, but in this (ROFS) image, it is
       
  1474 			 *		required to hide that file, create a 0 length file entry setting the 'hide'
       
  1475 			 *		flag so that at runtime, file gets hidden in the composite filesystem.
       
  1476 			 */
       
  1477 			if ((aKeyword != EKeywordHideV2) && alreadyExists) // duplicate file
       
  1478 				{
       
  1479 				Print(EError, "Duplicate file for %s on line %d\n",iReader.Word(1),iReader.CurrentLine());
       
  1480 				return EFalse;
       
  1481 				}
       
  1482 
       
  1483 			TBool aHidden = aKeyword==EKeywordHideV2;
       
  1484 			/* The file is only marked hidden and hence the source file name isn't known 
       
  1485 			 * here as hide statement says :
       
  1486 			 *	hide <filename as in ROM>
       
  1487 			 * Therefore, create TRomBuilderEntry with iFileName as 0 for hidden file when
       
  1488 			 * the file doesn't exist in the same ROM image. Otherwise, the src file name
       
  1489 			 * is known because of alreadyExists (which comes from the 'file'/'data' statement).
       
  1490 			 */
       
  1491 			if(aHidden)
       
  1492 				file = new TRomBuilderEntry(0, epocStartPtr);
       
  1493 			else
       
  1494 				file = new TRomBuilderEntry(iReader.Word(1), epocStartPtr);
       
  1495 			file->iExecutable=isPeFile;
       
  1496 			file->iHidden= aHidden;
       
  1497 			if( aFileCompressOption )
       
  1498 			{
       
  1499 				file->iCompressEnabled = ECompressionCompress;
       
  1500 			}
       
  1501 			else if(aFileUncompressOption )
       
  1502 			{
       
  1503 				file->iCompressEnabled = ECompressionUncompress;
       
  1504 			}
       
  1505 			TRomNode* node=new TRomNode(epocStartPtr, file);
       
  1506 			if (node==0)
       
  1507 				return EFalse;
       
  1508 			TInt r=ParseFileAttributes(node, file, aKeyword);
       
  1509 			if (r!=KErrNone)
       
  1510 				return EFalse;
       
  1511 
       
  1512 			dir->AddFile(node);	// to ROFS directory structure
       
  1513 			AddFile(file);		// to our list of files
       
  1514 			}		 
       
  1515 		else // directory
       
  1516 			{
       
  1517 			subDir = dir->FindInDirectory(epocStartPtr);
       
  1518 			if (!subDir) // sub directory does not exist
       
  1519 				{
       
  1520 				subDir = dir->NewSubDir(epocStartPtr);
       
  1521 				if (!subDir)
       
  1522 					return EFalse;
       
  1523 				}
       
  1524 			dir=subDir;
       
  1525 			epocStartPtr = epocEndPtr;
       
  1526 			}
       
  1527 		}
       
  1528 	return ETrue;
       
  1529 	}
       
  1530 
       
  1531 
       
  1532 TBool CObeyFile::ProcessRenaming(enum EKeyword aKeyword)
       
  1533 	{
       
  1534 
       
  1535 	// find existing file
       
  1536 	TBool endOfName=EFalse;
       
  1537 	TText *epocStartPtr=IsValidFilePath(iReader.Text(1));
       
  1538 	
       
  1539 	// Store the current name and new name to maintain renamed file map
       
  1540 	String currentName=iReader.Word(1);
       
  1541 	String newName=iReader.Word(2);
       
  1542 
       
  1543 	TText *epocEndPtr=epocStartPtr;
       
  1544 	if (epocStartPtr==NULL)
       
  1545 		{
       
  1546 		Print(EError, "Invalid source path on line %d\n",iReader.CurrentLine());
       
  1547 		return EFalse;
       
  1548 		}
       
  1549 
       
  1550 	char saved_srcname[257];
       
  1551 	strcpy(saved_srcname, iReader.Word(1));
       
  1552 
       
  1553 	TRomNode* dir=iRootDirectory;
       
  1554 	TRomNode* existingFile=0;
       
  1555 	while (!endOfName)
       
  1556 		{
       
  1557 		endOfName = GetNextBitOfFileName(&epocEndPtr);
       
  1558 		if (endOfName) // file
       
  1559 			{
       
  1560 			existingFile=dir->FindInDirectory(epocStartPtr);
       
  1561 			if (existingFile)
       
  1562 				{
       
  1563 				TInt fileCount=0;
       
  1564 				TInt dirCount=0;
       
  1565 				existingFile->CountDirectory(fileCount, dirCount);
       
  1566 				if (dirCount != 0 || fileCount != 0)
       
  1567 					{
       
  1568 					Print(EError, "Keyword %s not applicable to directories - line %d\n",iReader.Word(0),iReader.CurrentLine());
       
  1569 					return EFalse;
       
  1570 					}
       
  1571 				}
       
  1572 			}
       
  1573 		else // directory
       
  1574 			{
       
  1575 			TRomNode* subDir = dir->FindInDirectory(epocStartPtr);
       
  1576 			if (!subDir) // sub directory does not exist
       
  1577 				break;
       
  1578 			dir=subDir;
       
  1579 			epocStartPtr = epocEndPtr;
       
  1580 			}
       
  1581 		}
       
  1582 	if (aKeyword == EKeywordHide)
       
  1583 		{
       
  1584 			/*
       
  1585 			 * The EKeywordHide keyword is used to indicate that if the file exists in 
       
  1586 			 * the primary ROFS image and then hidden in extension ROFS, mark it hidden.
       
  1587 			 */
       
  1588 		if (!existingFile)
       
  1589 			{
       
  1590 			Print(EWarning, "Hiding non-existent file %s on line %d\n", 
       
  1591 				saved_srcname, iReader.CurrentLine());
       
  1592 			// Just a warning, as we've achieved the right overall effect.
       
  1593 			}
       
  1594 		else if (existingFile->iFileStartOffset==(TUint)KFileHidden)
       
  1595 			{
       
  1596 			Print(EWarning, "Hiding already hidden file %s on line %d\n", 
       
  1597 				saved_srcname, iReader.CurrentLine());
       
  1598 			// We will igrore this request, otherwise it will "undelete" it.
       
  1599 			}
       
  1600 		else
       
  1601 			{
       
  1602 			  //hidden files will not be placed to the image
       
  1603 			  existingFile->iHidden = ETrue;
       
  1604 			}
       
  1605 		return ETrue;
       
  1606 		}
       
  1607 
       
  1608 	if (!existingFile)
       
  1609 		{
       
  1610 		Print(EError, "Can't %s non-existent source file %s on line %d\n",
       
  1611 			iReader.Word(0), saved_srcname, iReader.CurrentLine());
       
  1612 		return EFalse;
       
  1613 		}
       
  1614 
       
  1615 	epocStartPtr=IsValidFilePath(iReader.Text(2));
       
  1616 	epocEndPtr=epocStartPtr;
       
  1617 	endOfName=EFalse;
       
  1618 	if (epocStartPtr==NULL)
       
  1619 		{
       
  1620 		Print(EError, "Invalid destination path on line %d\n",iReader.CurrentLine());
       
  1621 		return EFalse;
       
  1622 		}
       
  1623 
       
  1624 	TRomNode* newdir=iRootDirectory;
       
  1625 	while (!endOfName)
       
  1626 		{
       
  1627 		endOfName = GetNextBitOfFileName(&epocEndPtr);
       
  1628 		if (endOfName) // file
       
  1629 			{
       
  1630 			TRomNode* alreadyExists=newdir->FindInDirectory(epocStartPtr);
       
  1631 			if (alreadyExists && !(alreadyExists->iHidden)) // duplicate file
       
  1632 				{
       
  1633 				Print(EError, "Duplicate file for %s on line %d\n",saved_srcname,iReader.CurrentLine());
       
  1634 				return EFalse;
       
  1635 				}
       
  1636 			}
       
  1637 		else // directory
       
  1638 			{
       
  1639 			TRomNode* subDir = newdir->FindInDirectory(epocStartPtr);
       
  1640 			if (!subDir) // sub directory does not exist
       
  1641 				{
       
  1642 				subDir = newdir->NewSubDir(epocStartPtr);
       
  1643 				if (!subDir)
       
  1644 					return EFalse;
       
  1645 				}
       
  1646 			newdir=subDir;
       
  1647 			epocStartPtr = epocEndPtr;
       
  1648 			}
       
  1649 		}
       
  1650 
       
  1651 	if (aKeyword == EKeywordRename)
       
  1652 		{
       
  1653 		// rename => remove existingFile and insert into tree at new place
       
  1654 		// has no effect on the iNextExecutable or iNextNodeForSameFile links
       
  1655 
       
  1656 		TInt r=ParseFileAttributes(existingFile, existingFile->iEntry, aKeyword);
       
  1657 		if (r!=KErrNone)
       
  1658 			return EFalse;
       
  1659 		existingFile->Rename(dir, newdir, epocStartPtr);
       
  1660 		// Store the current and new name of file in the renamed file map.
       
  1661 		iPatchData->AddToRenamedFileMap(currentName, newName);
       
  1662 		return ETrue;
       
  1663 		}
       
  1664 	
       
  1665 	// alias => create new TRomNode entry and insert into tree
       
  1666 
       
  1667 	TRomNode* node = new TRomNode(epocStartPtr, 0);
       
  1668 	if (node == 0)
       
  1669 		{
       
  1670 		Print(EError, "Out of memory\n");
       
  1671 		return EFalse;
       
  1672 		}
       
  1673 	node->Alias(existingFile);
       
  1674 	TInt r=ParseFileAttributes(node, 0, aKeyword);
       
  1675 	if (r!=KErrNone)
       
  1676 		return EFalse;
       
  1677 
       
  1678 	newdir->AddFile(node);	// to ROFS directory structure, though possibly hidden
       
  1679 
       
  1680 	return ETrue;
       
  1681 	}
       
  1682 
       
  1683 TInt ParsePagingPolicy(const char* policy)
       
  1684 	{
       
  1685 	if(stricmp(policy,"NOPAGING")==0)
       
  1686 		return EKernelConfigPagingPolicyNoPaging;
       
  1687 	else if (stricmp(policy,"ALWAYSPAGE")==0)
       
  1688 		return EKernelConfigPagingPolicyAlwaysPage;
       
  1689 	else if(stricmp(policy,"DEFAULTUNPAGED")==0)
       
  1690 		return EKernelConfigPagingPolicyDefaultUnpaged;
       
  1691 	else if(stricmp(policy,"DEFAULTPAGED")==0)
       
  1692 		return EKernelConfigPagingPolicyDefaultPaged;
       
  1693 	return KErrArgument;
       
  1694 	}
       
  1695 
       
  1696 TBool CObeyFile::ProcessKeyword(enum EKeyword aKeyword)
       
  1697 	{
       
  1698 	#ifdef __TOOLS2__
       
  1699 	istringstream val(iReader.Word(1));
       
  1700 	#else
       
  1701 	istrstream val(iReader.Word(1),strlen(iReader.Word(1)));
       
  1702 	#endif
       
  1703 
       
  1704 #if defined(__MSVCDOTNET__) || defined(__TOOLS2__)
       
  1705 	val >> setbase(0);
       
  1706 #endif //__MSVCDOTNET__
       
  1707 
       
  1708 	TBool success = ETrue;
       
  1709 
       
  1710 	switch (aKeyword)
       
  1711 		{
       
  1712 	case EKeywordRofsName:
       
  1713 		iReader.CopyWord(1, iRomFileName);
       
  1714 		break;
       
  1715 	case EKeywordRofsSize:
       
  1716 		val >> iRomSize;
       
  1717 		break;
       
  1718 	case EKeywordVersion:
       
  1719 		val >> iVersion;
       
  1720 		break;
       
  1721 	case EKeywordRofsChecksum:
       
  1722 		val >> iCheckSum;
       
  1723 		break;
       
  1724 	case EKeywordTime:
       
  1725 		iReader.ProcessTime(iTime);
       
  1726 		break;
       
  1727 	case EKeywordPagingOverride:
       
  1728 		{
       
  1729 		if(iPagingOverrideParsed)
       
  1730 			Print(EWarning, "PagingOverride redefined - previous PagingOverride values lost\n");
       
  1731 		if(iCodePagingOverrideParsed)
       
  1732 			Print(EWarning, "PagingOverride defined - previous CodePagingOverride values lost\n");
       
  1733 		if(iDataPagingOverrideParsed)
       
  1734 			Print(EWarning, "PagingOverride defined - previous DataPagingOverride values lost\n");
       
  1735 		iPagingOverrideParsed = true;
       
  1736 		TInt policy = ParsePagingPolicy(iReader.Word(1));
       
  1737 		if(policy<0)
       
  1738 			{
       
  1739 			Print(EError,"Unrecognised option for PAGINGOVERRIDE keyword\n");
       
  1740 			success = false;
       
  1741 			}
       
  1742 		else
       
  1743 			{
       
  1744 			gCodePagingOverride = policy;
       
  1745 			gDataPagingOverride = policy;
       
  1746 			}
       
  1747 		}
       
  1748 		break;
       
  1749 	case EKeywordCodePagingOverride:
       
  1750 		{
       
  1751 		if(iCodePagingOverrideParsed)
       
  1752 			Print(EWarning, "CodePagingOverride redefined - previous CodePagingOverride values lost\n");
       
  1753 		if(iPagingOverrideParsed)
       
  1754 			Print(EWarning, "CodePagingOverride defined - previous PagingOverride values lost\n");
       
  1755 		iCodePagingOverrideParsed = true;
       
  1756 		TInt policy = ParsePagingPolicy(iReader.Word(1));
       
  1757 		if(policy<0)
       
  1758 			{
       
  1759 			Print(EError,"Unrecognised option for CODEPAGINGOVERRIDE keyword\n");
       
  1760 			success = false;
       
  1761 			}
       
  1762 		else
       
  1763 			gCodePagingOverride = policy;
       
  1764 		}
       
  1765 		break;
       
  1766 	case EKeywordDataPagingOverride:
       
  1767 		{
       
  1768 		if(iDataPagingOverrideParsed)
       
  1769 			Print(EWarning, "DataPagingOverride redefined - previous DataPagingOverride values lost\n");
       
  1770 		if(iPagingOverrideParsed)
       
  1771 			{
       
  1772 			Print(EError, "DataPagingOverride defined - previous PagingOverride values lost\n");
       
  1773 			success = false;
       
  1774 			break;
       
  1775 			}
       
  1776 		iDataPagingOverrideParsed = true;
       
  1777 		TInt policy = ParsePagingPolicy(iReader.Word(1));
       
  1778 		if(policy<0)
       
  1779 			{
       
  1780 			Print(EError,"Unrecognised option for DATAPAGINGOVERRIDE keyword\n");
       
  1781 			success = false;
       
  1782 			}
       
  1783 		else
       
  1784 			gDataPagingOverride = policy;
       
  1785 		}
       
  1786 		break;
       
  1787 	case EKeywordRofsAutoSize:
       
  1788 		iAutoSize = ETrue;
       
  1789 		val >> iAutoPageSize;
       
  1790 		break;
       
  1791 	default:
       
  1792 		// unexpected keyword iReader.Word(0)
       
  1793 		break;
       
  1794 		}
       
  1795 
       
  1796 	return success;
       
  1797 	}
       
  1798 
       
  1799 TBool CObeyFile::GotKeyVariables()
       
  1800 //
       
  1801 // Checks that the obeyfile has supplied enough variables to continue
       
  1802 //
       
  1803    	{
       
  1804 
       
  1805 	TBool retVal=ETrue;
       
  1806 
       
  1807 	// Mandatory keywords
       
  1808 
       
  1809 	if (iRomFileName==0)
       
  1810 		{
       
  1811 		Print(EAlways,"The name of the image file has not been supplied.\n");
       
  1812 		Print(EAlways,"Use the keyword \"rofsname\".\n");
       
  1813 		retVal = EFalse;
       
  1814 		}
       
  1815 	if (iRomSize==0)
       
  1816 		{
       
  1817 		Print(EAlways,"The size of the image has not been supplied.\n");
       
  1818 		Print(EAlways,"Use the keyword \"rofssize\".\n");
       
  1819 		retVal = EFalse;
       
  1820 		}
       
  1821 
       
  1822 	// Apply defaults as necessary
       
  1823 	if (iTime==0)
       
  1824 		{
       
  1825 		Print(ELog, "No timestamp specified. Using current time...\n");
       
  1826 		ObeyFileReader::TimeNow(iTime);
       
  1827 		}
       
  1828 
       
  1829 	Print(ELog, "\nCreating Rofs image %s\n", iRomFileName);
       
  1830 	return retVal;
       
  1831 	}
       
  1832 
       
  1833 
       
  1834 TText *CObeyFile::IsValidFilePath(TText *aPath)
       
  1835 //
       
  1836 // Check the path is valid
       
  1837 //
       
  1838 	{
       
  1839 	// skip leading "\"
       
  1840 	if (*aPath=='\\')
       
  1841 		aPath++;
       
  1842 	if (*aPath==0)
       
  1843 		return NULL; // file ends in a backslash
       
  1844 
       
  1845 	TText *p=aPath;
       
  1846 	TInt len=0;
       
  1847 	FOREVER
       
  1848 		{
       
  1849 		if (*p==0)
       
  1850 			return (len ? aPath : NULL);
       
  1851 		if (*p=='\\')
       
  1852 			{
       
  1853 			if (len==0)
       
  1854 				return NULL;
       
  1855 			len=0;
       
  1856 			}
       
  1857 		len++;
       
  1858 		p++;
       
  1859 		}
       
  1860 	}
       
  1861 
       
  1862 TBool CObeyFile::GetNextBitOfFileName(TText **epocEndPtr)
       
  1863 //
       
  1864 // Move the end pointer past the next directory separator, replacing it with 0
       
  1865 //
       
  1866 	{
       
  1867 	while (**epocEndPtr != '\\') // until reach the directory separator
       
  1868 		{
       
  1869 		if (**epocEndPtr==0) // if reach end of string, return TRUE, it's the filename
       
  1870 			return ETrue;
       
  1871 		(*epocEndPtr)++;
       
  1872 		}
       
  1873 	**epocEndPtr=0; // overwrite the directory separator with a 0
       
  1874 	(*epocEndPtr)++; // point past the 0 ready for the next one
       
  1875 	return EFalse;
       
  1876 	}
       
  1877 
       
  1878 
       
  1879 void CObeyFile::AddFile(TRomBuilderEntry* aFile)
       
  1880 	{
       
  1881 	*iNextFilePtrPtr = aFile;
       
  1882 	iNextFilePtrPtr = &(aFile->iNext);
       
  1883 	}
       
  1884 
       
  1885 
       
  1886 
       
  1887 TInt CObeyFile::ProcessExtensionRofs(MRofsImage* aKernelRom)
       
  1888 	{
       
  1889 	//
       
  1890 	// First pass through the obey file to set up key variables
       
  1891 	//
       
  1892 
       
  1893 
       
  1894         iReader.Rewind();
       
  1895 
       
  1896 	enum EKeyword keyword;
       
  1897 
       
  1898 	// Deal with the "extensionrofs" keyword, which should be first
       
  1899 		
       
  1900 	if (iReader.NextLine(1,keyword) != KErrNone)
       
  1901 		return KErrEof;
       
  1902 	if (keyword != EKeywordExtensionRofs)
       
  1903 		return Print(EError, "Unexpected keyword '%s' at start of extension rom - line %d\n",
       
  1904 			iReader.Word(0), iReader.CurrentLine());
       
  1905 	
       
  1906 	iReader.CopyWord(1, iRomFileName);
       
  1907 	Print(ELog, "\n========================================================\n");
       
  1908 	Print(ELog, "Extension ROFS %s starting at line %d\n\n", iRomFileName, iReader.CurrentLine());
       
  1909 
       
  1910 
       
  1911 	iReader.MarkNext();		// so that we rewind to the line after the extensionrom keyword
       
  1912 
       
  1913 	while (iReader.NextLine(1,keyword) != KErrEof)
       
  1914 		{
       
  1915 		if (keyword == EKeywordExtensionRofs)
       
  1916 			break;
       
  1917 			ProcessExtensionKeyword(keyword);
       
  1918 		}
       
  1919 
       
  1920 	if (!GotExtensionVariables(aKernelRom))
       
  1921 		return KErrGeneral;
       
  1922 
       
  1923 	// second pass to process the file specifications in the obey file building
       
  1924 	// up the TRomNode directory structure and the TRomBuilderEntry list
       
  1925 	//
       
  1926 	iReader.Rewind();
       
  1927 
       
  1928 	//
       
  1929 	if (aKernelRom==0)
       
  1930 		return Print(EError, "Option to extend a kernel ROFS image not yet implemented\n");
       
  1931 
       
  1932 
       
  1933 	
       
  1934 	iRootDirectory = new TRomNode((TText*)"");
       
  1935 	
       
  1936 	iLastExecutable = 0;
       
  1937 
       
  1938 	(aKernelRom->RootDirectory())->deleteTheFirstNode();
       
  1939 
       
  1940 
       
  1941 	iRootDirectory = aKernelRom->CopyDirectory(iLastExecutable);
       
  1942 	aKernelRom->SetRootDirectory(iRootDirectory);
       
  1943 
       
  1944 
       
  1945 	TInt align=0;
       
  1946 	while (iReader.NextLine(2,keyword)!=KErrEof)
       
  1947 		{
       
  1948 		if (keyword == EKeywordExtensionRofs)
       
  1949 			break;
       
  1950 
       
  1951 		switch (keyword)
       
  1952 			{
       
  1953 		case EKeywordHide:
       
  1954 		case EKeywordAlias:
       
  1955 		case EKeywordRename:
       
  1956 			if (!ProcessRenaming(keyword))
       
  1957 				return KErrGeneral;
       
  1958 			break;
       
  1959 
       
  1960 		case EKeywordPatchDllData:
       
  1961 		{	
       
  1962 			// Collect patchdata statements to process at the end
       
  1963 			StringVector patchDataTokens;
       
  1964 			SplitPatchDataStatement(patchDataTokens); 
       
  1965 			iPatchData->AddPatchDataStatement(patchDataTokens);									
       
  1966 			break;
       
  1967 		}
       
  1968 		default:
       
  1969 			if (!ProcessFile(align, keyword))
       
  1970 				return KErrGeneral;
       
  1971 			align=0;
       
  1972 			break;
       
  1973 			}
       
  1974 		}
       
  1975 
       
  1976 	if(!ParsePatchDllData() )
       
  1977 		return KErrGeneral;
       
  1978 	
       
  1979 	iReader.Mark();			// ready for processing the next extension rom(s)
       
  1980 
       
  1981 	if (iMissingFiles!=0)
       
  1982 		return KErrGeneral;
       
  1983 	if (iNumberOfFiles==0)
       
  1984 		{
       
  1985 		Print(EError, "No files specified.\n");
       
  1986 		return KErrGeneral;
       
  1987 		}
       
  1988 	return KErrNone;
       
  1989 	}
       
  1990 
       
  1991 
       
  1992 
       
  1993 
       
  1994 void CObeyFile::ProcessExtensionKeyword(enum EKeyword aKeyword)
       
  1995 	{
       
  1996 	#ifdef __TOOLS2__
       
  1997 	istringstream val(iReader.Word(1));
       
  1998 	#else
       
  1999 	istrstream val(iReader.Word(1),strlen(iReader.Word(1)));
       
  2000 	#endif
       
  2001 
       
  2002 #if defined(__MSVCDOTNET__) || defined(__TOOLS2__)
       
  2003 	val >> setbase(0);
       
  2004 #endif //__MSVCDOTNET__
       
  2005 
       
  2006 	switch (aKeyword)
       
  2007 		{
       
  2008 	case EKeywordCoreRofsName:
       
  2009  		iReader.CopyWord(1, iKernelRofsName);
       
  2010 		return;
       
  2011 	case EKeywordRofsSize:
       
  2012 		val >> iRomSize;
       
  2013 		return;
       
  2014 	case EKeywordVersion:
       
  2015 		val >> iVersion;
       
  2016 		return;
       
  2017 	case EKeywordRomChecksum:
       
  2018 		val >> iCheckSum;
       
  2019 		return;
       
  2020 	case EKeywordTime:
       
  2021 		iReader.ProcessTime(iTime);
       
  2022 		return;
       
  2023 	case EKeywordRofsAutoSize:
       
  2024 		iAutoSize = ETrue;
       
  2025 		val >> iAutoPageSize;
       
  2026 		return;
       
  2027 	default:
       
  2028 		Print(EError,"Keyword '%s' not valid in extension ROFS - line %d\n", iReader.Word(0), iReader.CurrentLine());
       
  2029 		break;
       
  2030 		}
       
  2031 	return;
       
  2032 	}
       
  2033 
       
  2034 TBool CObeyFile::GotExtensionVariables(MRofsImage* aRom)
       
  2035 //
       
  2036 // Checks that the obeyfile has supplied enough variables to continue
       
  2037 //
       
  2038    	{
       
  2039 
       
  2040 	TBool retVal=ETrue;
       
  2041   	TText* kernelRofsName = iKernelRofsName;
       
  2042 
       
  2043 	// Mandatory keywords
       
  2044 
       
  2045 	if (iRomSize==0)
       
  2046 		{
       
  2047 		Print(EAlways,"The size of the extension ROFS has not been supplied.\n");
       
  2048 		Print(EAlways,"Use the keyword \"rofssize\".\n");
       
  2049 		retVal = EFalse;
       
  2050 		}
       
  2051 
       
  2052 	// keywords we need if we don't already have a ROFS image to work from
       
  2053 
       
  2054 	if (aRom==0)
       
  2055 		{
       
  2056   		if (iKernelRofsName==0)
       
  2057 			{
       
  2058 			Print(EAlways,"The name of the core ROFS has not been supplied.\n");
       
  2059 			Print(EAlways,"Use the keyword \"rofsname\".\n");
       
  2060 			retVal = EFalse;
       
  2061 			}
       
  2062 		}
       
  2063 	else
       
  2064 		{
       
  2065 		if (iKernelRofsName != 0)
       
  2066 			{
       
  2067 			Print(EWarning,"Keyword \"rofsname\" ignored.\n");
       
  2068 			}
       
  2069 		kernelRofsName = aRom->RomFileName();
       
  2070 		}
       
  2071 
       
  2072 	// validation
       
  2073 
       
  2074 	// Apply defaults as necessary
       
  2075 	if (iTime==0)
       
  2076 		{
       
  2077 		Print(ELog, "No timestamp specified. Using current time...\n");
       
  2078 		ObeyFileReader::TimeNow(iTime);
       
  2079 		}
       
  2080 
       
  2081 	// fix up "*" in rofsname
       
  2082 	TText newname[256];
       
  2083 	TText* p=newname;
       
  2084 	TText* q=iRomFileName;
       
  2085 	TText c;
       
  2086 
       
  2087 	while ((c=*q++)!='\0')
       
  2088 		{
       
  2089 		if (c!='*')
       
  2090 			{
       
  2091 			*p++=c;
       
  2092 			continue;
       
  2093 			}
       
  2094 		TText *r=kernelRofsName;
       
  2095 		while ((c=*r++)!='\0')
       
  2096 			*p++=c;
       
  2097 		}
       
  2098 	*p = '\0';
       
  2099 	free(iRomFileName);
       
  2100   	iRomFileName = (TText*)strdup((char*)newname);
       
  2101 
       
  2102 	Print(ELog, "\nCreating ROFS image %s\n", iRomFileName);
       
  2103 
       
  2104 	return retVal;
       
  2105 	}
       
  2106 
       
  2107 // Fuction to split patchdata statement 
       
  2108 void CObeyFile::SplitPatchDataStatement(StringVector& aPatchDataTokens)
       
  2109 {
       
  2110 	// Get the value of symbol size, address/ordinal and new value 
       
  2111 	// to be patched from the patchdata statement.
       
  2112 	// Syntax of patchdata statements is as follows:
       
  2113 	// 1)	patchdata dll_name  ordinal OrdinalNumber size_in_bytes   new_value 
       
  2114 	// 2)   patchdata dll_name  addr    Address       size_in_bytes   new_value
       
  2115 	for(TInt count=1; count<=5; count++)
       
  2116 	{
       
  2117 		aPatchDataTokens.push_back(iReader.Word(count));
       
  2118 	}
       
  2119 
       
  2120 	// Store the the value of current line which will be used
       
  2121 	// when displaying error messages.
       
  2122 	OutputStringStream outStrStream;
       
  2123 	outStrStream<<iReader.CurrentLine();
       
  2124     aPatchDataTokens.push_back(outStrStream.str());
       
  2125 }
       
  2126 
       
  2127 TBool CObeyFile::ParsePatchDllData()
       
  2128 {
       
  2129 	// Get the list of patchdata statements
       
  2130 	VectorOfStringVector patchDataStatements=iPatchData->GetPatchDataStatements();
       
  2131 	// Get the list of renamed file map
       
  2132 	MapOfString RenamedFileMap=iPatchData->GetRenamedFileMap();
       
  2133 
       
  2134 	for(TUint count=0; count<patchDataStatements.size(); count++)
       
  2135 	{
       
  2136 		StringVector strVector = patchDataStatements.at(count);
       
  2137 		String filename=strVector.at(0);
       
  2138 		String lineNoStr = strVector.at(5);
       
  2139 		TUint lineNo=getNumber(((TText*)lineNoStr.c_str()));
       
  2140 		TRomNode* existingFile = NULL;
       
  2141 		
       
  2142 		do
       
  2143 		{
       
  2144 			TRomNode* dir=iRootDirectory;			
       
  2145 			TBool endOfName=EFalse;
       
  2146 
       
  2147 			TText *epocStartPtr=IsValidFilePath((TText*)filename.c_str());
       
  2148 			if (epocStartPtr==NULL)
       
  2149 			{
       
  2150 				Print(EError, "Invalid source path on line %d\n",lineNo);
       
  2151 				return EFalse;
       
  2152 			}
       
  2153 			epocStartPtr = (TText*)NormaliseFileName((const char*)epocStartPtr);
       
  2154 			TText *epocEndPtr=epocStartPtr;
       
  2155 
       
  2156 			while (!endOfName)
       
  2157 			{
       
  2158 				endOfName = GetNextBitOfFileName(&epocEndPtr);
       
  2159 				if (endOfName) // file
       
  2160 				{
       
  2161 					existingFile=dir->FindInDirectory(epocStartPtr);
       
  2162 					if (existingFile)
       
  2163 					{
       
  2164 						TInt fileCount=0;
       
  2165 						TInt dirCount=0;
       
  2166 						existingFile->CountDirectory(fileCount, dirCount);
       
  2167 						if (dirCount != 0 || fileCount != 0)
       
  2168 						{
       
  2169 							Print(EError, "Keyword %s not applicable to directories - line %d\n","patchdata",lineNo);
       
  2170 							return EFalse;
       
  2171 						}
       
  2172 					}
       
  2173 				}
       
  2174 				else // directory
       
  2175 				{
       
  2176 					TRomNode* subDir = dir->FindInDirectory(epocStartPtr);
       
  2177 					if (!subDir) // sub directory does not exist
       
  2178 						break;
       
  2179 					dir=subDir;
       
  2180 					epocStartPtr = epocEndPtr;
       
  2181 				}
       
  2182 			}
       
  2183 
       
  2184 			if(!existingFile)
       
  2185 			{
       
  2186 				// If the E32Image file to be patched is not included then check if the
       
  2187 				// file was renamed.
       
  2188 				MapOfStringIterator RenamedFileMapIterator;
       
  2189 				if ((RenamedFileMapIterator=RenamedFileMap.find(filename)) != RenamedFileMap.end())
       
  2190 					filename = (*RenamedFileMapIterator).second; 				
       
  2191 				else
       
  2192 				{
       
  2193 					Print(EError, "File %s not found - line %d\n", filename.c_str(), lineNo);
       
  2194 					return EFalse;
       
  2195 				}
       
  2196 			}
       
  2197 		}while(!existingFile);
       
  2198 
       
  2199 		TUint32 aSize, aOrdinal, aNewValue, aOffset;
       
  2200 		TLinAddr aDataAddr;
       
  2201 
       
  2202 		aOrdinal = (TUint32)-1;
       
  2203 		aDataAddr = (TUint32)-1;
       
  2204 		aOffset = 0;
       
  2205 
       
  2206 		String symbolSize=strVector.at(3);
       
  2207 		aSize = getNumber((TText*)symbolSize.c_str());
       
  2208 		String aValue=strVector.at(4);
       
  2209 		aNewValue = getNumber((TText*)aValue.c_str());		
       
  2210 
       
  2211 		DllDataEntry *dataEntry = new DllDataEntry(aSize, aNewValue);
       
  2212 
       
  2213 		// Set the address of the data or the ordinal number specified in OBY statement.
       
  2214 		String keyword=strVector.at(1);
       
  2215 		String keywordValue=strVector.at(2);
       
  2216 		
       
  2217 		/* Check for +OFFSET at the end of the ordinal number or address */
       
  2218 		TUint plus = keywordValue.find("+",0);
       
  2219 		if (plus != std::string::npos)
       
  2220 		{
       
  2221 			/* Get the offset that we found after the + sign */
       
  2222 			String offset = keywordValue.substr(plus+1);
       
  2223 			aOffset = getNumber((TText*)offset.c_str());
       
  2224 
       
  2225 			keywordValue.resize(plus);		
       
  2226 		}
       
  2227 		if(stricmp (keyword.c_str(), "addr") == 0)
       
  2228 			aDataAddr = getNumber((TText*)keywordValue.c_str());
       
  2229 		
       
  2230 		else 
       
  2231 			 aOrdinal = getNumber((TText*)keywordValue.c_str());
       
  2232 		
       
  2233 		dataEntry->iDataAddress = aDataAddr;
       
  2234 		dataEntry->iOrdinal = aOrdinal;
       
  2235 		dataEntry->iOffset = aOffset;
       
  2236 
       
  2237 		existingFile->SetDllData();
       
  2238 
       
  2239 		DllDataEntry *aDllDataEntry= existingFile->iEntry->GetFirstDllDataEntry();
       
  2240 		if (aDllDataEntry==NULL)
       
  2241 		{
       
  2242 			// Set the first node of the patchdata linked list
       
  2243 			aDllDataEntry=dataEntry;
       
  2244 			existingFile->iEntry->SetFirstDllDataEntry(aDllDataEntry);
       
  2245 		}
       
  2246 		else
       
  2247 		{
       
  2248 			// Goto the last node
       
  2249 			while((aDllDataEntry->NextDllDataEntry()) != NULL)
       
  2250 			{
       
  2251 				aDllDataEntry = aDllDataEntry->NextDllDataEntry();
       
  2252 			}
       
  2253 			
       
  2254 			// Add the new node at the end of linked list
       
  2255 			aDllDataEntry->AddDllDataEntry(dataEntry);			
       
  2256 		}
       
  2257 	}
       
  2258 	return ETrue;
       
  2259 }
       
  2260 
       
  2261 
       
  2262 
       
  2263 
       
  2264 
       
  2265 
       
  2266 
       
  2267 
       
  2268