debugsrv/runmodedebug/rmdriver/src/d_list_manager.cpp
author hgs
Fri, 08 Oct 2010 14:56:39 +0300
changeset 56 aa2539c91954
parent 42 0ff24a8f6ca2
permissions -rw-r--r--
201041
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
42
hgs
parents:
diff changeset
     1
// Copyright (c) 2007-2009 Nokia Corporation and/or its subsidiary(-ies).
hgs
parents:
diff changeset
     2
// All rights reserved.
hgs
parents:
diff changeset
     3
// This component and the accompanying materials are made available
56
hgs
parents: 42
diff changeset
     4
// under the terms of "Eclipse Public License v1.0"
42
hgs
parents:
diff changeset
     5
// which accompanies this distribution, and is available
hgs
parents:
diff changeset
     6
// at the URL "http://www.eclipse.org/legal/epl-v10.html".
hgs
parents:
diff changeset
     7
//
hgs
parents:
diff changeset
     8
// Initial Contributors:
hgs
parents:
diff changeset
     9
// Nokia Corporation - initial contribution.
hgs
parents:
diff changeset
    10
//
hgs
parents:
diff changeset
    11
// Contributors:
hgs
parents:
diff changeset
    12
//
hgs
parents:
diff changeset
    13
// Description:
hgs
parents:
diff changeset
    14
// Provides a class to manage the generation of lists
hgs
parents:
diff changeset
    15
// 
hgs
parents:
diff changeset
    16
//
hgs
parents:
diff changeset
    17
hgs
parents:
diff changeset
    18
#include "d_list_manager.h"
hgs
parents:
diff changeset
    19
#include "d_process_tracker.h"
hgs
parents:
diff changeset
    20
#include "debug_utils.h"
hgs
parents:
diff changeset
    21
#include "plat_priv.h"
hgs
parents:
diff changeset
    22
#include "debug_logging.h"
hgs
parents:
diff changeset
    23
#include <arm.h>
hgs
parents:
diff changeset
    24
hgs
parents:
diff changeset
    25
// make accessing DThread's MState more intuitive
hgs
parents:
diff changeset
    26
#define iMState iWaitLink.iSpare1
hgs
parents:
diff changeset
    27
// make accessing NThread's NState more intuitive
hgs
parents:
diff changeset
    28
#define iNState iSpare3
hgs
parents:
diff changeset
    29
hgs
parents:
diff changeset
    30
//constants to match against a rom entry's attributes,
hgs
parents:
diff changeset
    31
//these are defined in the file server (can't be included kernel side)
hgs
parents:
diff changeset
    32
//and in the ROM tools (also inaccessible) so redefined here
hgs
parents:
diff changeset
    33
const TUint KEntryAttXIP=0x0080;
hgs
parents:
diff changeset
    34
const TUint KEntryAttDir=0x0010;
hgs
parents:
diff changeset
    35
hgs
parents:
diff changeset
    36
using namespace Debug;
hgs
parents:
diff changeset
    37
hgs
parents:
diff changeset
    38
/**
hgs
parents:
diff changeset
    39
  Get thread listing for the specified thread, if the thread data will not fit
hgs
parents:
diff changeset
    40
  in the buffer then an error is returned.
hgs
parents:
diff changeset
    41
hgs
parents:
diff changeset
    42
  @param aBuffer buffer to put data in
hgs
parents:
diff changeset
    43
  @param aDataSize on return will contain size of data
hgs
parents:
diff changeset
    44
  @param aTargetThreadId thread ID to return listing for
hgs
parents:
diff changeset
    45
hgs
parents:
diff changeset
    46
  @return KErrNone on success,
hgs
parents:
diff changeset
    47
  KErrTooBig if data won't fit in aBuffer
hgs
parents:
diff changeset
    48
  or one of the other system wide error codes on failure
hgs
parents:
diff changeset
    49
  */
hgs
parents:
diff changeset
    50
TInt TListManager::GetThreadListForThread(TDes8& aBuffer, TUint32& aDataSize, const TUint64 aTargetThreadId) const
hgs
parents:
diff changeset
    51
	{
hgs
parents:
diff changeset
    52
	LOG_MSG("TListManager::GetThreadListForThread()");
hgs
parents:
diff changeset
    53
hgs
parents:
diff changeset
    54
	// open a handle to check whether the thread actually exists
hgs
parents:
diff changeset
    55
	NKern::ThreadEnterCS();
hgs
parents:
diff changeset
    56
	DThread* thread = DebugUtils::OpenThreadHandle(aTargetThreadId);
hgs
parents:
diff changeset
    57
	TUint64 processId = 0;
hgs
parents:
diff changeset
    58
	if (thread)
hgs
parents:
diff changeset
    59
		{
hgs
parents:
diff changeset
    60
		processId = thread->iOwningProcess->iId;
hgs
parents:
diff changeset
    61
		thread->Close(NULL);
hgs
parents:
diff changeset
    62
		}
hgs
parents:
diff changeset
    63
	NKern::ThreadLeaveCS();
hgs
parents:
diff changeset
    64
	if (!thread)
hgs
parents:
diff changeset
    65
		{
hgs
parents:
diff changeset
    66
		return KErrArgument;
hgs
parents:
diff changeset
    67
		}
hgs
parents:
diff changeset
    68
hgs
parents:
diff changeset
    69
	//request a process specific list
hgs
parents:
diff changeset
    70
	return GetThreadListForProcess(aBuffer, aDataSize, processId);
hgs
parents:
diff changeset
    71
	}
hgs
parents:
diff changeset
    72
hgs
parents:
diff changeset
    73
TInt TListManager::GetThreadListForProcess(TDes8& aBuffer, TUint32& aDataSize, const TUint64 aTargetProcessId) const
hgs
parents:
diff changeset
    74
	{
hgs
parents:
diff changeset
    75
	LOG_MSG("TListManager::GetThreadListForProcess()");
hgs
parents:
diff changeset
    76
hgs
parents:
diff changeset
    77
	// open a handle to check whether the process actually exists
hgs
parents:
diff changeset
    78
	DProcess* process = DebugUtils::OpenProcessHandle(aTargetProcessId);
hgs
parents:
diff changeset
    79
	if(!process)
hgs
parents:
diff changeset
    80
		{
hgs
parents:
diff changeset
    81
		return KErrArgument;
hgs
parents:
diff changeset
    82
		}
hgs
parents:
diff changeset
    83
	process->Close(NULL);
hgs
parents:
diff changeset
    84
hgs
parents:
diff changeset
    85
	//request a process specific list
hgs
parents:
diff changeset
    86
	return GetThreadList(aBuffer, aDataSize, EFalse, aTargetProcessId);
hgs
parents:
diff changeset
    87
	}
hgs
parents:
diff changeset
    88
hgs
parents:
diff changeset
    89
/**
hgs
parents:
diff changeset
    90
  Get global thread listing
hgs
parents:
diff changeset
    91
hgs
parents:
diff changeset
    92
  @param aBuffer buffer to put data in
hgs
parents:
diff changeset
    93
  @param aDataSize on return will contain size of data
hgs
parents:
diff changeset
    94
hgs
parents:
diff changeset
    95
  @return KErrNone on success,
hgs
parents:
diff changeset
    96
  KErrTooBig if data won't fit in aBuffer
hgs
parents:
diff changeset
    97
  or one of the other system wide error codes on failure
hgs
parents:
diff changeset
    98
  */
hgs
parents:
diff changeset
    99
TInt TListManager::GetGlobalThreadList(TDes8& aBuffer, TUint32& aDataSize) const
hgs
parents:
diff changeset
   100
	{
hgs
parents:
diff changeset
   101
	LOG_MSG("TListManager::GetGlobalThreadList()");
hgs
parents:
diff changeset
   102
hgs
parents:
diff changeset
   103
	//request a global list
hgs
parents:
diff changeset
   104
	return GetThreadList(aBuffer, aDataSize, ETrue, 0);
hgs
parents:
diff changeset
   105
	}
hgs
parents:
diff changeset
   106
hgs
parents:
diff changeset
   107
/**
hgs
parents:
diff changeset
   108
  Get thread listing, if the thread data will not fit
hgs
parents:
diff changeset
   109
  in the buffer then an error is returned.
hgs
parents:
diff changeset
   110
hgs
parents:
diff changeset
   111
  @param aBuffer buffer to put data in
hgs
parents:
diff changeset
   112
  @param aDataSize on return will contain size of data
hgs
parents:
diff changeset
   113
  @param aGlobal whether or not the listing should be global or thread specific
hgs
parents:
diff changeset
   114
  @param aTargetProcessId process ID to return listing for, relevant only if aGlobal == ETrue
hgs
parents:
diff changeset
   115
hgs
parents:
diff changeset
   116
  @return KErrNone on success,
hgs
parents:
diff changeset
   117
  KErrTooBig if data won't fit in aBuffer
hgs
parents:
diff changeset
   118
  or one of the other system wide error codes on failure
hgs
parents:
diff changeset
   119
  */
hgs
parents:
diff changeset
   120
TInt TListManager::GetThreadList(TDes8& aBuffer, TUint32& aDataSize, TBool aGlobal, const TUint64 aTargetProcessId) const
hgs
parents:
diff changeset
   121
	{
hgs
parents:
diff changeset
   122
	LOG_MSG("TListManager::GetThreadList\n");
hgs
parents:
diff changeset
   123
hgs
parents:
diff changeset
   124
	NKern::ThreadEnterCS();
hgs
parents:
diff changeset
   125
	DObjectCon *threads = Kern::Containers()[EThread];
hgs
parents:
diff changeset
   126
	threads->Wait();
hgs
parents:
diff changeset
   127
hgs
parents:
diff changeset
   128
	aDataSize = 0;
hgs
parents:
diff changeset
   129
	aBuffer.SetLength(0);
hgs
parents:
diff changeset
   130
	//iterate through the threads adding them to the buffer
hgs
parents:
diff changeset
   131
	for(TInt i=0; i<threads->Count(); i++)
hgs
parents:
diff changeset
   132
		{
hgs
parents:
diff changeset
   133
		DThread* thread = (DThread*)(*threads)[i];
hgs
parents:
diff changeset
   134
hgs
parents:
diff changeset
   135
		//skip this thread pointer is the thread is NULL
hgs
parents:
diff changeset
   136
		if(thread)
hgs
parents:
diff changeset
   137
			{
hgs
parents:
diff changeset
   138
			NThread& nThread = thread->iNThread;
hgs
parents:
diff changeset
   139
hgs
parents:
diff changeset
   140
			// if the thread is marked as being dead then don't return information about it in the listing
hgs
parents:
diff changeset
   141
#ifndef __SMP__
hgs
parents:
diff changeset
   142
			if((NThread::EDead != nThread.iNState) && (DThread::EDead != thread->iMState))
hgs
parents:
diff changeset
   143
#else
hgs
parents:
diff changeset
   144
 			if((!nThread.IsDead()) && (DThread::EDead != thread->iMState))
hgs
parents:
diff changeset
   145
#endif
hgs
parents:
diff changeset
   146
				{
hgs
parents:
diff changeset
   147
				if( aGlobal || (aTargetProcessId == (TUint64)thread->iOwningProcess->iId))
hgs
parents:
diff changeset
   148
					{
hgs
parents:
diff changeset
   149
					//store the data in the buffer
hgs
parents:
diff changeset
   150
					AppendThreadData(aBuffer, aDataSize, thread);
hgs
parents:
diff changeset
   151
					}
hgs
parents:
diff changeset
   152
				}
hgs
parents:
diff changeset
   153
			}
hgs
parents:
diff changeset
   154
		}
hgs
parents:
diff changeset
   155
hgs
parents:
diff changeset
   156
	//leave critical section
hgs
parents:
diff changeset
   157
	threads->Signal();
hgs
parents:
diff changeset
   158
	NKern::ThreadLeaveCS();
hgs
parents:
diff changeset
   159
hgs
parents:
diff changeset
   160
	//return indication of whether the kernel's data was too big
hgs
parents:
diff changeset
   161
	return (aDataSize > aBuffer.Length()) ? KErrTooBig : KErrNone;
hgs
parents:
diff changeset
   162
	}
hgs
parents:
diff changeset
   163
hgs
parents:
diff changeset
   164
/**
hgs
parents:
diff changeset
   165
  Helper function for writing thread data into a buffer
hgs
parents:
diff changeset
   166
hgs
parents:
diff changeset
   167
  @pre call in a critical section
hgs
parents:
diff changeset
   168
  @pre call only on threads which have NThread state not equal to NThread::EDead
hgs
parents:
diff changeset
   169
hgs
parents:
diff changeset
   170
  @param aBuffer buffer to put data in
hgs
parents:
diff changeset
   171
  @param aDataSize on return will contain size of data
hgs
parents:
diff changeset
   172
  @param aThread thread object to include information about
hgs
parents:
diff changeset
   173
hgs
parents:
diff changeset
   174
  @return KErrNone on success, or one of the other system wide error codes
hgs
parents:
diff changeset
   175
*/
hgs
parents:
diff changeset
   176
void TListManager::AppendThreadData(TDes8& aBuffer, TUint32& aDataSize, DThread* aThread) const
hgs
parents:
diff changeset
   177
	{
hgs
parents:
diff changeset
   178
	LOG_MSG3("TListManager::AppendThreadData for thrd 0x%08x, currThrd=0x%08x", 
hgs
parents:
diff changeset
   179
			aThread->iId, Kern::CurrentThread().iId );
hgs
parents:
diff changeset
   180
	
hgs
parents:
diff changeset
   181
	//get aThread's name
hgs
parents:
diff changeset
   182
	TFileName fileName;
hgs
parents:
diff changeset
   183
	aThread->FullName(fileName);
hgs
parents:
diff changeset
   184
	TUint16 nameLength = fileName.Length();
hgs
parents:
diff changeset
   185
hgs
parents:
diff changeset
   186
	//increase aDataSize by the size of this entry
hgs
parents:
diff changeset
   187
	aDataSize = Align4(aDataSize + (2*nameLength) + sizeof(TThreadListEntry) - sizeof(TUint16));
hgs
parents:
diff changeset
   188
	//if the data would not cause overflow then add it to the buffer
hgs
parents:
diff changeset
   189
	if(aDataSize <= aBuffer.MaxLength())
hgs
parents:
diff changeset
   190
		{
hgs
parents:
diff changeset
   191
		//Create a TThreadListEntry which references the buffer.
hgs
parents:
diff changeset
   192
		TThreadListEntry& entry = *(TThreadListEntry*)(aBuffer.Ptr()+aBuffer.Length());
hgs
parents:
diff changeset
   193
		//add data to entry
hgs
parents:
diff changeset
   194
		entry.iProcessId = (TUint64)aThread->iOwningProcess->iId;
hgs
parents:
diff changeset
   195
		entry.iThreadId = (TUint64)aThread->iId;
hgs
parents:
diff changeset
   196
		entry.iSupervisorStackBase = (TUint32)aThread->iSupervisorStack;
hgs
parents:
diff changeset
   197
		entry.iSupervisorStackBaseValid = ETrue;
hgs
parents:
diff changeset
   198
		entry.iSupervisorStackSize = aThread->iSupervisorStackSize;
hgs
parents:
diff changeset
   199
		entry.iSupervisorStackSizeValid = ETrue;
hgs
parents:
diff changeset
   200
		entry.iNameLength = nameLength;
hgs
parents:
diff changeset
   201
hgs
parents:
diff changeset
   202
		entry.iSupervisorStackPtrValid = EInValid;
hgs
parents:
diff changeset
   203
		entry.iSupervisorStackPtr = 0;
hgs
parents:
diff changeset
   204
		
hgs
parents:
diff changeset
   205
		if(aThread->iId != Kern::CurrentThread().iId)
hgs
parents:
diff changeset
   206
			{
hgs
parents:
diff changeset
   207
			NThread& nThread = aThread->iNThread;
hgs
parents:
diff changeset
   208
hgs
parents:
diff changeset
   209
			TArmRegSet regSet;
hgs
parents:
diff changeset
   210
			TUint32 flags;
hgs
parents:
diff changeset
   211
			NKern::ThreadGetSystemContext(&nThread, &regSet, flags);
hgs
parents:
diff changeset
   212
			entry.iSupervisorStackPtr = (TUint32)regSet.iR13;
hgs
parents:
diff changeset
   213
			//need to check that the stack pointer flag is valid
hgs
parents:
diff changeset
   214
			if(flags & (1<<EArmSp))
hgs
parents:
diff changeset
   215
				{
hgs
parents:
diff changeset
   216
				entry.iSupervisorStackPtrValid = EValid;
hgs
parents:
diff changeset
   217
				}
hgs
parents:
diff changeset
   218
			}
hgs
parents:
diff changeset
   219
hgs
parents:
diff changeset
   220
		//copy name data into the buffer
hgs
parents:
diff changeset
   221
		TUint16* ptr = &(entry.iName[0]);
hgs
parents:
diff changeset
   222
		const TUint8* ptr8 = fileName.Ptr();
hgs
parents:
diff changeset
   223
		const TUint8* ptr8End = ptr8 + nameLength;
hgs
parents:
diff changeset
   224
		while(ptr8 < ptr8End)
hgs
parents:
diff changeset
   225
			{
hgs
parents:
diff changeset
   226
			*ptr++ = (TUint16)*ptr8++;
hgs
parents:
diff changeset
   227
			}
hgs
parents:
diff changeset
   228
 
hgs
parents:
diff changeset
   229
		aBuffer.SetLength(aDataSize);
hgs
parents:
diff changeset
   230
		}
hgs
parents:
diff changeset
   231
	}
hgs
parents:
diff changeset
   232
hgs
parents:
diff changeset
   233
/**
hgs
parents:
diff changeset
   234
  Get global process listing
hgs
parents:
diff changeset
   235
hgs
parents:
diff changeset
   236
  @param aBuffer buffer to put data in
hgs
parents:
diff changeset
   237
  @param aDataSize on return will contain size of data
hgs
parents:
diff changeset
   238
hgs
parents:
diff changeset
   239
  @return KErrNone on success,
hgs
parents:
diff changeset
   240
  KErrTooBig if data won't fit in aBuffer
hgs
parents:
diff changeset
   241
  or one of the other system wide error codes on failure
hgs
parents:
diff changeset
   242
  */
hgs
parents:
diff changeset
   243
TInt TListManager::GetProcessList(TDes8& aBuffer, TUint32& aDataSize) const
hgs
parents:
diff changeset
   244
	{
hgs
parents:
diff changeset
   245
	LOG_MSG("TListManager::GetProcessList()");
hgs
parents:
diff changeset
   246
hgs
parents:
diff changeset
   247
	//get a pointer to the kernel's process list
hgs
parents:
diff changeset
   248
	DObjectCon* processes = Kern::Containers()[EProcess];
hgs
parents:
diff changeset
   249
hgs
parents:
diff changeset
   250
	if(processes == NULL)
hgs
parents:
diff changeset
   251
		{
hgs
parents:
diff changeset
   252
		//if can't get container then something is seriously wrong
hgs
parents:
diff changeset
   253
		return KErrNotFound;
hgs
parents:
diff changeset
   254
		}
hgs
parents:
diff changeset
   255
hgs
parents:
diff changeset
   256
	//have to read the processes in a critical section
hgs
parents:
diff changeset
   257
	NKern::ThreadEnterCS();
hgs
parents:
diff changeset
   258
	processes->Wait();
hgs
parents:
diff changeset
   259
hgs
parents:
diff changeset
   260
	aDataSize = 0;
hgs
parents:
diff changeset
   261
	//iterate through the processes adding them to the buffer
hgs
parents:
diff changeset
   262
	for(TInt i=0; i<processes->Count(); i++)
hgs
parents:
diff changeset
   263
		{
hgs
parents:
diff changeset
   264
		DProcess* process = (DProcess*)(*processes)[i];
hgs
parents:
diff changeset
   265
		if(process)
hgs
parents:
diff changeset
   266
			{
hgs
parents:
diff changeset
   267
			//get process's file name length
hgs
parents:
diff changeset
   268
			DCodeSeg* codeSeg = process->iCodeSeg;
hgs
parents:
diff changeset
   269
			TUint16 fileNameLength = (codeSeg) ? (*codeSeg->iFileName).Length() : 0;
hgs
parents:
diff changeset
   270
hgs
parents:
diff changeset
   271
			//get process's dynamic name length and name
hgs
parents:
diff changeset
   272
			TFullName fullName;
hgs
parents:
diff changeset
   273
			process->FullName(fullName);
hgs
parents:
diff changeset
   274
			TUint16 dynamicNameLength = fullName.Length();
hgs
parents:
diff changeset
   275
hgs
parents:
diff changeset
   276
			//increase aDataSize to reflect size of entry
hgs
parents:
diff changeset
   277
			aDataSize = Align4(aDataSize + (2*fileNameLength) + (2*dynamicNameLength) + sizeof(TProcessListEntry) - sizeof(TUint16));
hgs
parents:
diff changeset
   278
			//if the data would not cause overflow then add it to the buffer
hgs
parents:
diff changeset
   279
			if(aDataSize <= aBuffer.MaxLength())
hgs
parents:
diff changeset
   280
				{
hgs
parents:
diff changeset
   281
				//Create a TProcessListEntry which references the buffer.
hgs
parents:
diff changeset
   282
				TProcessListEntry& entry = *(TProcessListEntry*)(aBuffer.Ptr() + aBuffer.Length());
hgs
parents:
diff changeset
   283
hgs
parents:
diff changeset
   284
				//set values
hgs
parents:
diff changeset
   285
				entry.iProcessId = (TUint64)process->iId;
hgs
parents:
diff changeset
   286
				entry.iFileNameLength = fileNameLength;
hgs
parents:
diff changeset
   287
				entry.iDynamicNameLength = dynamicNameLength;
hgs
parents:
diff changeset
   288
				entry.iUid3 = process->iUids.iUid[2].iUid;
hgs
parents:
diff changeset
   289
hgs
parents:
diff changeset
   290
				if(codeSeg)
hgs
parents:
diff changeset
   291
					{
hgs
parents:
diff changeset
   292
					//create TPtr to where the file name should be written
hgs
parents:
diff changeset
   293
					TPtr name = TPtr((TUint8*)&(entry.iNames[0]), fileNameLength*2, fileNameLength*2);
hgs
parents:
diff changeset
   294
					//copy the file name
hgs
parents:
diff changeset
   295
					TInt err = CopyAndExpandDes(*codeSeg->iFileName, name);
hgs
parents:
diff changeset
   296
					if(err != KErrNone)
hgs
parents:
diff changeset
   297
						{
hgs
parents:
diff changeset
   298
						processes->Signal();
hgs
parents:
diff changeset
   299
						NKern::ThreadLeaveCS();
hgs
parents:
diff changeset
   300
						return KErrGeneral;
hgs
parents:
diff changeset
   301
						}
hgs
parents:
diff changeset
   302
					}
hgs
parents:
diff changeset
   303
hgs
parents:
diff changeset
   304
				//create TPtr to where the dynamic name should be written
hgs
parents:
diff changeset
   305
				TPtr name = TPtr((TUint8*)(&(entry.iNames[0]) + fileNameLength), dynamicNameLength*2, dynamicNameLength*2);
hgs
parents:
diff changeset
   306
				//copy the dynamic name
hgs
parents:
diff changeset
   307
				TInt err = CopyAndExpandDes(fullName, name);
hgs
parents:
diff changeset
   308
				if(err != KErrNone)
hgs
parents:
diff changeset
   309
					{
hgs
parents:
diff changeset
   310
					processes->Signal();
hgs
parents:
diff changeset
   311
					NKern::ThreadLeaveCS();
hgs
parents:
diff changeset
   312
					return KErrGeneral;
hgs
parents:
diff changeset
   313
					}
hgs
parents:
diff changeset
   314
hgs
parents:
diff changeset
   315
				//set length same as aDataSize
hgs
parents:
diff changeset
   316
				aBuffer.SetLength(aDataSize);
hgs
parents:
diff changeset
   317
				}
hgs
parents:
diff changeset
   318
			}
hgs
parents:
diff changeset
   319
		}
hgs
parents:
diff changeset
   320
hgs
parents:
diff changeset
   321
	//leave critical section
hgs
parents:
diff changeset
   322
	processes->Signal();
hgs
parents:
diff changeset
   323
	NKern::ThreadLeaveCS();
hgs
parents:
diff changeset
   324
hgs
parents:
diff changeset
   325
	//return indication of whether the kernel's data was too big
hgs
parents:
diff changeset
   326
	return (aDataSize > aBuffer.Length()) ? KErrTooBig : KErrNone;
hgs
parents:
diff changeset
   327
	}
hgs
parents:
diff changeset
   328
hgs
parents:
diff changeset
   329
/**
hgs
parents:
diff changeset
   330
  Copy the descriptor aSrc to aDest and converting each byte from aSrc
hgs
parents:
diff changeset
   331
  into the two-byte equivalent. For example if aSrc contains 'XYZ' then
hgs
parents:
diff changeset
   332
  aDest will be filled with 'X\0Y\0Z\0' where \0 is the null character.
hgs
parents:
diff changeset
   333
  The length of aDest is set to twice the length of aSrc.
hgs
parents:
diff changeset
   334
hgs
parents:
diff changeset
   335
  @param aSrc source descriptor
hgs
parents:
diff changeset
   336
  @param aDest destination descriptor to copy and expand aSrc into
hgs
parents:
diff changeset
   337
hgs
parents:
diff changeset
   338
  @return KErrNone on success,
hgs
parents:
diff changeset
   339
  KErrArgument if the max length of aDest is less than twice the length of aSrc
hgs
parents:
diff changeset
   340
  */
hgs
parents:
diff changeset
   341
TInt TListManager::CopyAndExpandDes(const TDesC& aSrc, TDes& aDest) const
hgs
parents:
diff changeset
   342
	{
hgs
parents:
diff changeset
   343
	//check bounds
hgs
parents:
diff changeset
   344
	if(aSrc.Length() * 2 > aDest.MaxLength())
hgs
parents:
diff changeset
   345
		{
hgs
parents:
diff changeset
   346
		return KErrArgument;
hgs
parents:
diff changeset
   347
		}
hgs
parents:
diff changeset
   348
hgs
parents:
diff changeset
   349
	//get a pointer to the start of the destination descriptor
hgs
parents:
diff changeset
   350
	TUint16* destPtr = (TUint16*)aDest.Ptr();
hgs
parents:
diff changeset
   351
hgs
parents:
diff changeset
   352
	//get pointers to the start and end of the aSrc descriptor
hgs
parents:
diff changeset
   353
	const TUint8* srcPtr = aSrc.Ptr();
hgs
parents:
diff changeset
   354
	const TUint8* srcEnd = srcPtr + aSrc.Length();
hgs
parents:
diff changeset
   355
hgs
parents:
diff changeset
   356
	//copy the characters from aSrc into aDest, expanding to make them 16-bit characters
hgs
parents:
diff changeset
   357
	while(srcPtr < srcEnd)
hgs
parents:
diff changeset
   358
		{
hgs
parents:
diff changeset
   359
		*destPtr = (TUint16)*srcPtr;
hgs
parents:
diff changeset
   360
		destPtr++;
hgs
parents:
diff changeset
   361
		srcPtr++;
hgs
parents:
diff changeset
   362
		}
hgs
parents:
diff changeset
   363
hgs
parents:
diff changeset
   364
	//set aDest's length to reflect the new contents
hgs
parents:
diff changeset
   365
	aDest.SetLength(2*aSrc.Length());
hgs
parents:
diff changeset
   366
	return KErrNone;
hgs
parents:
diff changeset
   367
	}
hgs
parents:
diff changeset
   368
hgs
parents:
diff changeset
   369
/**
hgs
parents:
diff changeset
   370
  Get global code segment listing
hgs
parents:
diff changeset
   371
hgs
parents:
diff changeset
   372
  @param aBuffer buffer to put data in
hgs
parents:
diff changeset
   373
  @param aDataSize on return will contain size of data
hgs
parents:
diff changeset
   374
hgs
parents:
diff changeset
   375
  @return KErrNone on success,
hgs
parents:
diff changeset
   376
  KErrTooBig if data won't fit in aBuffer,
hgs
parents:
diff changeset
   377
  or one of the other system wide error codes
hgs
parents:
diff changeset
   378
  */
hgs
parents:
diff changeset
   379
TInt TListManager::GetGlobalCodeSegList(TDes8& aBuffer, TUint32& aDataSize) const
hgs
parents:
diff changeset
   380
	{
hgs
parents:
diff changeset
   381
	LOG_MSG("TListManager::GetGlobalCodeSegList()");
hgs
parents:
diff changeset
   382
hgs
parents:
diff changeset
   383
	// Acquire code seg lock mutex
hgs
parents:
diff changeset
   384
	NKern::ThreadEnterCS();
hgs
parents:
diff changeset
   385
	DMutex* codeMutex = Kern::CodeSegLock();
hgs
parents:
diff changeset
   386
	Kern::MutexWait(*codeMutex);
hgs
parents:
diff changeset
   387
hgs
parents:
diff changeset
   388
	//get global code seg list
hgs
parents:
diff changeset
   389
	SDblQue* codeSegList = Kern::CodeSegList();
hgs
parents:
diff changeset
   390
hgs
parents:
diff changeset
   391
	//create a memory info object for use in the loop
hgs
parents:
diff changeset
   392
	TModuleMemoryInfo memoryInfo;
hgs
parents:
diff changeset
   393
hgs
parents:
diff changeset
   394
	//iterate through the list
hgs
parents:
diff changeset
   395
	aDataSize = 0;
hgs
parents:
diff changeset
   396
	for (SDblQueLink* codeSegPtr= codeSegList->First(); codeSegPtr!=(SDblQueLink*) (codeSegList); codeSegPtr=codeSegPtr->iNext)
hgs
parents:
diff changeset
   397
		{
hgs
parents:
diff changeset
   398
		DEpocCodeSeg* codeSeg = (DEpocCodeSeg*)_LOFF(codeSegPtr,DCodeSeg, iLink);
hgs
parents:
diff changeset
   399
		//the code seg shouldn't be null as we're in critical section, ignore if it is null
hgs
parents:
diff changeset
   400
		if(codeSeg)
hgs
parents:
diff changeset
   401
			{
hgs
parents:
diff changeset
   402
			//get the memory info
hgs
parents:
diff changeset
   403
			TInt err = codeSeg->GetMemoryInfo(memoryInfo, NULL);
hgs
parents:
diff changeset
   404
			if(err != KErrNone)
hgs
parents:
diff changeset
   405
				{
hgs
parents:
diff changeset
   406
				// Release the codeseglock mutex again
hgs
parents:
diff changeset
   407
				Kern::MutexSignal(*codeMutex);
hgs
parents:
diff changeset
   408
				NKern::ThreadLeaveCS();
hgs
parents:
diff changeset
   409
hgs
parents:
diff changeset
   410
				//there's been an error so return it
hgs
parents:
diff changeset
   411
				return err;
hgs
parents:
diff changeset
   412
				}
hgs
parents:
diff changeset
   413
			//calculate data values
hgs
parents:
diff changeset
   414
			TBool isXip = (TBool)(codeSeg->iXIP);
hgs
parents:
diff changeset
   415
hgs
parents:
diff changeset
   416
			//get the code seg type, can ignore error as have already checked codeSeg is not NULL
hgs
parents:
diff changeset
   417
			TCodeSegType type = EUnknownCodeSegType;
hgs
parents:
diff changeset
   418
			err = GetCodeSegType(codeSeg, type);
hgs
parents:
diff changeset
   419
			if(err != KErrNone)
hgs
parents:
diff changeset
   420
				{
hgs
parents:
diff changeset
   421
				LOG_MSG("TListManager::GetGlobalCodeSegList() : code seg is NULL");
hgs
parents:
diff changeset
   422
				}
hgs
parents:
diff changeset
   423
hgs
parents:
diff changeset
   424
			TUint32 uid3 = codeSeg->iUids.iUid[2].iUid;
hgs
parents:
diff changeset
   425
			//append data to buffer
56
hgs
parents: 42
diff changeset
   426
			err = AppendCodeSegData(aBuffer, aDataSize, memoryInfo, isXip, type, *codeSeg->iFileName, uid3);
42
hgs
parents:
diff changeset
   427
			if(err != KErrNone)
hgs
parents:
diff changeset
   428
				{
hgs
parents:
diff changeset
   429
				// Release the codeseglock mutex again
hgs
parents:
diff changeset
   430
				Kern::MutexSignal(*codeMutex);
hgs
parents:
diff changeset
   431
				NKern::ThreadLeaveCS();
hgs
parents:
diff changeset
   432
hgs
parents:
diff changeset
   433
				return KErrGeneral;
hgs
parents:
diff changeset
   434
				}
hgs
parents:
diff changeset
   435
			}
hgs
parents:
diff changeset
   436
		}
hgs
parents:
diff changeset
   437
hgs
parents:
diff changeset
   438
	// Release the codeseglock mutex again
hgs
parents:
diff changeset
   439
	Kern::MutexSignal(*codeMutex);
hgs
parents:
diff changeset
   440
	NKern::ThreadLeaveCS();
hgs
parents:
diff changeset
   441
hgs
parents:
diff changeset
   442
	return (aDataSize > aBuffer.MaxLength()) ? KErrTooBig : KErrNone;
hgs
parents:
diff changeset
   443
	}
hgs
parents:
diff changeset
   444
hgs
parents:
diff changeset
   445
/**
hgs
parents:
diff changeset
   446
  Get code segment list for a thread
hgs
parents:
diff changeset
   447
hgs
parents:
diff changeset
   448
  @param aBuffer buffer to store data in
hgs
parents:
diff changeset
   449
  @param aDataSize size of kernel's data
hgs
parents:
diff changeset
   450
  @param thread ID to get listing for
hgs
parents:
diff changeset
   451
hgs
parents:
diff changeset
   452
  @return KErrNone on success,
hgs
parents:
diff changeset
   453
  KErrTooBig if data won't fit in aBuffer,
hgs
parents:
diff changeset
   454
  or one of the other system wide error codes
hgs
parents:
diff changeset
   455
  */
hgs
parents:
diff changeset
   456
TInt TListManager::GetCodeSegListForThread(TDes8& aBuffer, TUint32& aDataSize, const TUint64 aTargetThreadId) const
hgs
parents:
diff changeset
   457
	{
hgs
parents:
diff changeset
   458
	LOG_MSG("TListManager::GetCodeSegListForThread()");
hgs
parents:
diff changeset
   459
hgs
parents:
diff changeset
   460
	TUint64 processId = 0;
hgs
parents:
diff changeset
   461
	NKern::ThreadEnterCS();
hgs
parents:
diff changeset
   462
	DThread* thread = DebugUtils::OpenThreadHandle(aTargetThreadId);
hgs
parents:
diff changeset
   463
	if (thread)
hgs
parents:
diff changeset
   464
		{
hgs
parents:
diff changeset
   465
		processId = thread->iOwningProcess->iId;
hgs
parents:
diff changeset
   466
		thread->Close(NULL);
hgs
parents:
diff changeset
   467
		}
hgs
parents:
diff changeset
   468
	NKern::ThreadLeaveCS();
hgs
parents:
diff changeset
   469
hgs
parents:
diff changeset
   470
	if (processId == 0)
hgs
parents:
diff changeset
   471
		{
hgs
parents:
diff changeset
   472
		return KErrArgument;
hgs
parents:
diff changeset
   473
		}
hgs
parents:
diff changeset
   474
hgs
parents:
diff changeset
   475
	return GetCodeSegListForProcess(aBuffer, aDataSize, processId);
hgs
parents:
diff changeset
   476
	}
hgs
parents:
diff changeset
   477
hgs
parents:
diff changeset
   478
/**
hgs
parents:
diff changeset
   479
  Get code segment list for a process
hgs
parents:
diff changeset
   480
hgs
parents:
diff changeset
   481
  @param aBuffer buffer to store data in
hgs
parents:
diff changeset
   482
  @param aDataSize size of kernel's data
hgs
parents:
diff changeset
   483
  @param process ID to get listing for
hgs
parents:
diff changeset
   484
hgs
parents:
diff changeset
   485
  @return KErrNone on success,
hgs
parents:
diff changeset
   486
  KErrTooBig if data won't fit in aBuffer,
hgs
parents:
diff changeset
   487
  or one of the other system wide error codes
hgs
parents:
diff changeset
   488
  */
hgs
parents:
diff changeset
   489
TInt TListManager::GetCodeSegListForProcess(TDes8& aBuffer, TUint32& aDataSize, const TUint64 aTargetProcessId) const
hgs
parents:
diff changeset
   490
	{
hgs
parents:
diff changeset
   491
	LOG_MSG("TListManager::GetCodeSegListForProcess()");
hgs
parents:
diff changeset
   492
hgs
parents:
diff changeset
   493
	NKern::ThreadEnterCS();
hgs
parents:
diff changeset
   494
hgs
parents:
diff changeset
   495
	//get the process
hgs
parents:
diff changeset
   496
	DProcess* process = DebugUtils::OpenProcessHandle(aTargetProcessId);
hgs
parents:
diff changeset
   497
hgs
parents:
diff changeset
   498
	if(!process)
hgs
parents:
diff changeset
   499
		{
hgs
parents:
diff changeset
   500
		NKern::ThreadLeaveCS();
hgs
parents:
diff changeset
   501
		return KErrArgument;
hgs
parents:
diff changeset
   502
		}
hgs
parents:
diff changeset
   503
hgs
parents:
diff changeset
   504
	// acquire code segment mutex
hgs
parents:
diff changeset
   505
	Kern::AccessCode();
hgs
parents:
diff changeset
   506
hgs
parents:
diff changeset
   507
	//memory info object to use in loop
hgs
parents:
diff changeset
   508
	TModuleMemoryInfo memoryInfo;
hgs
parents:
diff changeset
   509
hgs
parents:
diff changeset
   510
	//get code seg list
hgs
parents:
diff changeset
   511
	SDblQue queue;
hgs
parents:
diff changeset
   512
	process->TraverseCodeSegs(&queue, NULL, DCodeSeg::EMarkDebug, DProcess::ETraverseFlagAdd);
hgs
parents:
diff changeset
   513
hgs
parents:
diff changeset
   514
	//iterate through the list
hgs
parents:
diff changeset
   515
	aDataSize = 0;
hgs
parents:
diff changeset
   516
	TInt err = KErrNone;
hgs
parents:
diff changeset
   517
	for(SDblQueLink* codeSegPtr= queue.First(); codeSegPtr!=(SDblQueLink*) (&queue); codeSegPtr=codeSegPtr->iNext)
hgs
parents:
diff changeset
   518
		{
hgs
parents:
diff changeset
   519
		//get the code seg
hgs
parents:
diff changeset
   520
		DEpocCodeSeg* codeSeg = (DEpocCodeSeg*)_LOFF(codeSegPtr,DCodeSeg, iTempLink);
hgs
parents:
diff changeset
   521
hgs
parents:
diff changeset
   522
		//the code seg shouldn't be null as we're in critical section, ignore if it is null
hgs
parents:
diff changeset
   523
		if(codeSeg)
hgs
parents:
diff changeset
   524
			{
hgs
parents:
diff changeset
   525
			err = codeSeg->GetMemoryInfo(memoryInfo, NULL);
hgs
parents:
diff changeset
   526
			if (err) break;
hgs
parents:
diff changeset
   527
hgs
parents:
diff changeset
   528
			TBool isXip = (TBool)(codeSeg->iXIP);
hgs
parents:
diff changeset
   529
hgs
parents:
diff changeset
   530
			//get the code seg type, can ignore error as have already checked codeSeg is not NULL
hgs
parents:
diff changeset
   531
			TCodeSegType type = EUnknownCodeSegType;
hgs
parents:
diff changeset
   532
			err = GetCodeSegType(codeSeg, type);
hgs
parents:
diff changeset
   533
			if(err != KErrNone)
hgs
parents:
diff changeset
   534
				{
hgs
parents:
diff changeset
   535
				LOG_MSG("TListManager::GetCodeSegListForProcess() : code seg is NULL");
hgs
parents:
diff changeset
   536
				}
hgs
parents:
diff changeset
   537
hgs
parents:
diff changeset
   538
			TUint32 uid3 = codeSeg->iUids.iUid[2].iUid;
hgs
parents:
diff changeset
   539
			//append data to buffer
56
hgs
parents: 42
diff changeset
   540
			err = AppendCodeSegData(aBuffer, aDataSize, memoryInfo, isXip, type, *codeSeg->iFileName, uid3);
42
hgs
parents:
diff changeset
   541
			if (err) break;
hgs
parents:
diff changeset
   542
			}
hgs
parents:
diff changeset
   543
		}
hgs
parents:
diff changeset
   544
hgs
parents:
diff changeset
   545
	//un mark the code segs that we've iterated over
hgs
parents:
diff changeset
   546
	DCodeSeg::EmptyQueue(queue, DCodeSeg::EMarkDebug);
hgs
parents:
diff changeset
   547
hgs
parents:
diff changeset
   548
	//release mutex
hgs
parents:
diff changeset
   549
	Kern::EndAccessCode();
hgs
parents:
diff changeset
   550
hgs
parents:
diff changeset
   551
	process->Close(NULL);
hgs
parents:
diff changeset
   552
	NKern::ThreadLeaveCS();
hgs
parents:
diff changeset
   553
	return (aDataSize > aBuffer.MaxLength()) ? KErrTooBig : err;
hgs
parents:
diff changeset
   554
	}
hgs
parents:
diff changeset
   555
hgs
parents:
diff changeset
   556
/**
hgs
parents:
diff changeset
   557
  Appends data to a specified buffer and puts the resulting size in aDataSize.
hgs
parents:
diff changeset
   558
  If the data won't fit then aDataSize is updated to reflect what the new length
hgs
parents:
diff changeset
   559
  would be.
hgs
parents:
diff changeset
   560
hgs
parents:
diff changeset
   561
  @param aBuffer buffer to append data to
hgs
parents:
diff changeset
   562
  @param aDataSize will contain buffer size (or the size the buffer would be) on return
hgs
parents:
diff changeset
   563
  @param aMemoryInfo info to append to buffer
hgs
parents:
diff changeset
   564
  @param aIsXip boolean indicating whether the code segment is XIP
hgs
parents:
diff changeset
   565
  @param aFileName file name to append to buffer
hgs
parents:
diff changeset
   566
hgs
parents:
diff changeset
   567
  @return KErrNone on success, or one of the other system wide error codes
hgs
parents:
diff changeset
   568
  */
hgs
parents:
diff changeset
   569
TInt TListManager::AppendCodeSegData(TDes8& aBuffer, TUint32& aDataSize, const TModuleMemoryInfo& aMemoryInfo, const TBool aIsXip, const TCodeSegType aCodeSegType, const TDesC8& aFileName, const TUint32 aUid3) const
hgs
parents:
diff changeset
   570
	{
hgs
parents:
diff changeset
   571
	//get some data elements to put in buffer
hgs
parents:
diff changeset
   572
	TUint16 fileNameLength = aFileName.Length();
hgs
parents:
diff changeset
   573
hgs
parents:
diff changeset
   574
	//calculate the resultant size
hgs
parents:
diff changeset
   575
	aDataSize = Align4(aDataSize + sizeof(TCodeSegListEntry) + (2*fileNameLength) - sizeof(TUint16));
hgs
parents:
diff changeset
   576
	if(aDataSize <= aBuffer.MaxLength())
hgs
parents:
diff changeset
   577
		{
hgs
parents:
diff changeset
   578
		//Create a TCodeSegListEntry which references the buffer.
hgs
parents:
diff changeset
   579
		TCodeSegListEntry& entry = *(TCodeSegListEntry*)(aBuffer.Ptr() + aBuffer.Length());
hgs
parents:
diff changeset
   580
		entry.iCodeBase = aMemoryInfo.iCodeBase;
hgs
parents:
diff changeset
   581
		entry.iCodeSize = aMemoryInfo.iCodeSize;
hgs
parents:
diff changeset
   582
		entry.iConstDataSize = aMemoryInfo.iConstDataSize;
hgs
parents:
diff changeset
   583
		entry.iInitialisedDataBase = aMemoryInfo.iInitialisedDataBase;
hgs
parents:
diff changeset
   584
		entry.iInitialisedDataSize = aMemoryInfo.iInitialisedDataSize;
hgs
parents:
diff changeset
   585
		entry.iUninitialisedDataSize = aMemoryInfo.iUninitialisedDataSize;
hgs
parents:
diff changeset
   586
		entry.iIsXip = aIsXip;
hgs
parents:
diff changeset
   587
		entry.iCodeSegType = aCodeSegType;
hgs
parents:
diff changeset
   588
		entry.iNameLength = fileNameLength;
hgs
parents:
diff changeset
   589
		entry.iUid3 = aUid3;
hgs
parents:
diff changeset
   590
hgs
parents:
diff changeset
   591
		//have to convert the stored name to 16 bit unicode
hgs
parents:
diff changeset
   592
		TPtr name = TPtr((TUint8*)&(entry.iName[0]), fileNameLength*2, fileNameLength*2);
hgs
parents:
diff changeset
   593
		TInt err = CopyAndExpandDes(aFileName, name);
hgs
parents:
diff changeset
   594
		if(err != KErrNone)
hgs
parents:
diff changeset
   595
			{
hgs
parents:
diff changeset
   596
			return KErrGeneral;
hgs
parents:
diff changeset
   597
			}
hgs
parents:
diff changeset
   598
hgs
parents:
diff changeset
   599
		//increase length
hgs
parents:
diff changeset
   600
		aBuffer.SetLength(aDataSize);
hgs
parents:
diff changeset
   601
		}
hgs
parents:
diff changeset
   602
hgs
parents:
diff changeset
   603
	return KErrNone;
hgs
parents:
diff changeset
   604
	}
hgs
parents:
diff changeset
   605
hgs
parents:
diff changeset
   606
/**
hgs
parents:
diff changeset
   607
  Get global XIP libraries list. The ROM file system is searched for files in
hgs
parents:
diff changeset
   608
  z:\sys\bin. The files are filtered to only include library files which
hgs
parents:
diff changeset
   609
  correspond to the correct hardware variant.
hgs
parents:
diff changeset
   610
hgs
parents:
diff changeset
   611
  In the rom, a directory is represented as a list of TRomEntrys, corresponding to
hgs
parents:
diff changeset
   612
  the files and directories in that directory. A TRomEntry corresponding to a file
hgs
parents:
diff changeset
   613
  contains a pointer to that file's location in the rom. If the TRomEntry
hgs
parents:
diff changeset
   614
  corresponds to a directory then it contains a pointer to that directory in the
hgs
parents:
diff changeset
   615
  ROM header. As such, from a pointer to the root directory of the z: drive, it is
hgs
parents:
diff changeset
   616
  possible to extract the directory contents for a particular directory (i.e. z:\sys\bin)
hgs
parents:
diff changeset
   617
  by recursively finding the subdirectories (i.e. find 'sys' in 'z:', then 'bin' in 'sys')
hgs
parents:
diff changeset
   618
  and then listing the contents of that directory.
hgs
parents:
diff changeset
   619
hgs
parents:
diff changeset
   620
  @param aBuffer buffer to store data in
hgs
parents:
diff changeset
   621
  @param aDataSize size of kernel's data
hgs
parents:
diff changeset
   622
hgs
parents:
diff changeset
   623
  @return KErrNone on success,
hgs
parents:
diff changeset
   624
  KErrTooBig if data won't fit in aBuffer,
hgs
parents:
diff changeset
   625
  or one of the other system wide error codes
hgs
parents:
diff changeset
   626
  */
hgs
parents:
diff changeset
   627
TInt TListManager::GetXipLibrariesList(TDes8& aBuffer, TUint32& aDataSize) const
hgs
parents:
diff changeset
   628
	{
hgs
parents:
diff changeset
   629
	LOG_MSG("TListManager::GetXipLibrariesList()");
hgs
parents:
diff changeset
   630
hgs
parents:
diff changeset
   631
	// z:\sys\bin expressed as 16 bit unicode..
hgs
parents:
diff changeset
   632
	_LIT(KZSysBin, "z\0:\0\\\0s\0y\0s\0\\\0b\0i\0n\0\\\0");
hgs
parents:
diff changeset
   633
hgs
parents:
diff changeset
   634
	//array to store pointers to directory entries in
hgs
parents:
diff changeset
   635
	RPointerArray<TRomEntry> entries;
hgs
parents:
diff changeset
   636
	//get the entries in KZSysBin
hgs
parents:
diff changeset
   637
	TInt err = GetDirectoryEntries(entries, KZSysBin());
hgs
parents:
diff changeset
   638
	if(KErrNone != err)
hgs
parents:
diff changeset
   639
		{
hgs
parents:
diff changeset
   640
		entries.Close();
hgs
parents:
diff changeset
   641
		return err;
hgs
parents:
diff changeset
   642
		}
hgs
parents:
diff changeset
   643
hgs
parents:
diff changeset
   644
	aDataSize = 0;
hgs
parents:
diff changeset
   645
	for(TInt i=0; i<entries.Count(); i++)
hgs
parents:
diff changeset
   646
		{
hgs
parents:
diff changeset
   647
		//if the entry is XIP and it's not a directory then it's a candidate to add
hgs
parents:
diff changeset
   648
		if( (entries[i]->iAtt & KEntryAttXIP) && ! (entries[i]->iAtt & KEntryAttDir) )
hgs
parents:
diff changeset
   649
			{
hgs
parents:
diff changeset
   650
			//get a reference to the dll's header
hgs
parents:
diff changeset
   651
			const TRomImageHeader& header = *(const TRomImageHeader*)(entries[i]->iAddressLin);
hgs
parents:
diff changeset
   652
hgs
parents:
diff changeset
   653
			//check that it's uid1 value corresponds to that for a library
hgs
parents:
diff changeset
   654
			if(header.iUid1 == KDynamicLibraryUidValue)
hgs
parents:
diff changeset
   655
				{
hgs
parents:
diff changeset
   656
				//get the current hardware variant
hgs
parents:
diff changeset
   657
				TSuperPage& superPage = Kern::SuperPage();
hgs
parents:
diff changeset
   658
				TUint variant = superPage.iActiveVariant;
hgs
parents:
diff changeset
   659
				TUint cpu = (variant >> 16) & 0xff;
hgs
parents:
diff changeset
   660
				TUint asic = (variant >> 24);
hgs
parents:
diff changeset
   661
hgs
parents:
diff changeset
   662
				//check this dll is compatible with the current variant
hgs
parents:
diff changeset
   663
				if(THardwareVariant(header.iHardwareVariant).IsCompatibleWith(cpu,asic,variant))
hgs
parents:
diff changeset
   664
					{
hgs
parents:
diff changeset
   665
					const TInt fileNameLength16 = entries[i]->iNameLength;
hgs
parents:
diff changeset
   666
					const TInt fullNameLength16 = (KZSysBin().Length() / 2) + fileNameLength16;
hgs
parents:
diff changeset
   667
					aDataSize += Align4((2 * fullNameLength16) + sizeof(TXipLibraryListEntry) - sizeof(TUint16));
hgs
parents:
diff changeset
   668
hgs
parents:
diff changeset
   669
					if(aDataSize <= aBuffer.MaxLength())
hgs
parents:
diff changeset
   670
						{
hgs
parents:
diff changeset
   671
						//Create a TXipLibraryListEntry which references the buffer.
hgs
parents:
diff changeset
   672
						TXipLibraryListEntry& libraryInfo = *(TXipLibraryListEntry*)(aBuffer.Ptr() + aBuffer.Length());
hgs
parents:
diff changeset
   673
hgs
parents:
diff changeset
   674
						//add the data
hgs
parents:
diff changeset
   675
						libraryInfo.iCodeBase = header.iCodeAddress;
hgs
parents:
diff changeset
   676
						libraryInfo.iCodeSize = header.iTextSize;
hgs
parents:
diff changeset
   677
						libraryInfo.iConstDataSize = header.iCodeSize - header.iTextSize;
hgs
parents:
diff changeset
   678
						libraryInfo.iInitialisedDataBase = header.iDataBssLinearBase;
hgs
parents:
diff changeset
   679
						libraryInfo.iInitialisedDataSize = header.iDataSize;
hgs
parents:
diff changeset
   680
						libraryInfo.iUninitialisedDataSize = header.iBssSize;
hgs
parents:
diff changeset
   681
						libraryInfo.iNameLength = fullNameLength16;
hgs
parents:
diff changeset
   682
hgs
parents:
diff changeset
   683
						//create a TPtr8 to contain the fully qualified name (i.e. z:\sys\bin\ prefixed)
hgs
parents:
diff changeset
   684
						TPtr8 name((TUint8*)&(libraryInfo.iName[0]), 0, 2 * fullNameLength16);
hgs
parents:
diff changeset
   685
						name.Append(KZSysBin());
hgs
parents:
diff changeset
   686
						name.Append(TPtr8((TUint8*)&(entries[i]->iName), 2 * fileNameLength16, 2 * fileNameLength16));
hgs
parents:
diff changeset
   687
hgs
parents:
diff changeset
   688
						//increase the buffer's length to reflect the new data size
hgs
parents:
diff changeset
   689
						aBuffer.SetLength(aDataSize);
hgs
parents:
diff changeset
   690
						}
hgs
parents:
diff changeset
   691
					}
hgs
parents:
diff changeset
   692
				}
hgs
parents:
diff changeset
   693
			}
hgs
parents:
diff changeset
   694
		}
hgs
parents:
diff changeset
   695
	entries.Close();
hgs
parents:
diff changeset
   696
	return (aDataSize == aBuffer.Length()) ? KErrNone : KErrTooBig;
hgs
parents:
diff changeset
   697
	}
hgs
parents:
diff changeset
   698
hgs
parents:
diff changeset
   699
/**
hgs
parents:
diff changeset
   700
Get the list of TRomEntry objects in the specified directory aDirectory
hgs
parents:
diff changeset
   701
hgs
parents:
diff changeset
   702
@param aRomEntryArray array to store pointers to the TRomEntry objects in
hgs
parents:
diff changeset
   703
@param aDirectoryName directory to get contents of. The passed in string should be
hgs
parents:
diff changeset
   704
16 bit unicode and should begin with z:. Single backslashes should be used as delimiters
hgs
parents:
diff changeset
   705
rather than forward slashes and a terminating backslash is optional.
hgs
parents:
diff changeset
   706
For example: z:\sys\bin
hgs
parents:
diff changeset
   707
hgs
parents:
diff changeset
   708
@return KErrNone on success, or one of the other system wide error codes
hgs
parents:
diff changeset
   709
*/
hgs
parents:
diff changeset
   710
TInt TListManager::GetDirectoryEntries(RPointerArray<TRomEntry>& aRomEntryArray, const TDesC& aDirectoryName) const
hgs
parents:
diff changeset
   711
	{
hgs
parents:
diff changeset
   712
	LOG_MSG("TListManager::GetDirectoryEntries()");
hgs
parents:
diff changeset
   713
hgs
parents:
diff changeset
   714
	//definition in 16 bit unicode
hgs
parents:
diff changeset
   715
	_LIT(KForwardSlash, "/\0");
hgs
parents:
diff changeset
   716
hgs
parents:
diff changeset
   717
	//if directory has forward slashes then exit
hgs
parents:
diff changeset
   718
	if(aDirectoryName.Find(KForwardSlash()) != KErrNotFound)
hgs
parents:
diff changeset
   719
		{
hgs
parents:
diff changeset
   720
		return KErrArgument;
hgs
parents:
diff changeset
   721
		}
hgs
parents:
diff changeset
   722
hgs
parents:
diff changeset
   723
	//create an array to hold the folders in aDirectoryName
hgs
parents:
diff changeset
   724
	RArray<TPtr8> folders;
hgs
parents:
diff changeset
   725
hgs
parents:
diff changeset
   726
	//split the directory up into its folders, i.e. z:\sys\bin is split into { 'z:', 'sys', 'bin' }
hgs
parents:
diff changeset
   727
	TInt err = SplitDirectoryName(aDirectoryName, folders);
hgs
parents:
diff changeset
   728
	if(KErrNone != err)
hgs
parents:
diff changeset
   729
		{
hgs
parents:
diff changeset
   730
		folders.Close();
hgs
parents:
diff changeset
   731
		return err;
hgs
parents:
diff changeset
   732
		}
hgs
parents:
diff changeset
   733
hgs
parents:
diff changeset
   734
	if(folders.Count() == 0)
hgs
parents:
diff changeset
   735
		{
hgs
parents:
diff changeset
   736
		folders.Close();
hgs
parents:
diff changeset
   737
		//empty string passed in
hgs
parents:
diff changeset
   738
		return KErrArgument;
hgs
parents:
diff changeset
   739
		}
hgs
parents:
diff changeset
   740
hgs
parents:
diff changeset
   741
	// z: as 16 bit unicode
hgs
parents:
diff changeset
   742
	_LIT(KZColon, "z\0:\0");
hgs
parents:
diff changeset
   743
	if(folders[0].CompareF(KZColon()) != 0)
hgs
parents:
diff changeset
   744
		{
hgs
parents:
diff changeset
   745
		//first argument must be z: otherwise not in rom
hgs
parents:
diff changeset
   746
		folders.Close();
hgs
parents:
diff changeset
   747
		return KErrArgument;
hgs
parents:
diff changeset
   748
		}
hgs
parents:
diff changeset
   749
	//remove z: from array
hgs
parents:
diff changeset
   750
	folders.Remove(0);
hgs
parents:
diff changeset
   751
	for(TInt i=0; i<folders.Count(); i++)
hgs
parents:
diff changeset
   752
		{
hgs
parents:
diff changeset
   753
		if(folders[i].Length() == 0)
hgs
parents:
diff changeset
   754
			{
hgs
parents:
diff changeset
   755
			// there were two backslashes in a row
hgs
parents:
diff changeset
   756
			folders.Close();
hgs
parents:
diff changeset
   757
			return KErrArgument;
hgs
parents:
diff changeset
   758
			}
hgs
parents:
diff changeset
   759
		}
hgs
parents:
diff changeset
   760
hgs
parents:
diff changeset
   761
	//get a pointer to the start of the rom root directory list
hgs
parents:
diff changeset
   762
	TLinAddr romRootDirectoryList = Epoc::RomHeader().iRomRootDirectoryList;
hgs
parents:
diff changeset
   763
hgs
parents:
diff changeset
   764
	//the first 4 bytes of the rom root directory list is a count of how many sections (rom roots) there are
hgs
parents:
diff changeset
   765
	TUint32 rootDirectoryCount = (TUint32)*(TLinAddr*)romRootDirectoryList;
hgs
parents:
diff changeset
   766
hgs
parents:
diff changeset
   767
	//rootDirectoryPointer will be shifted through the rom root directory list and will contain pointers to the sections in the rom
hgs
parents:
diff changeset
   768
	TLinAddr rootDirectoryPointer = romRootDirectoryList;
hgs
parents:
diff changeset
   769
	for(TInt i=0; i<rootDirectoryCount; i++)
hgs
parents:
diff changeset
   770
		{
hgs
parents:
diff changeset
   771
		//the address of the section is stored in the second four bytes of the 8 byte pair reserved for each section
hgs
parents:
diff changeset
   772
		rootDirectoryPointer += 8;
hgs
parents:
diff changeset
   773
hgs
parents:
diff changeset
   774
		//romRoot contains the address of the root of the section
hgs
parents:
diff changeset
   775
		TLinAddr romRoot = *(TLinAddr*)rootDirectoryPointer;
hgs
parents:
diff changeset
   776
hgs
parents:
diff changeset
   777
		//append the directory entries from romRoot's z:\sys\bin subdirectory
hgs
parents:
diff changeset
   778
		TInt err = GetDirectoryEntries(aRomEntryArray, folders, romRoot);
hgs
parents:
diff changeset
   779
		if(KErrNone != err)
hgs
parents:
diff changeset
   780
			{
hgs
parents:
diff changeset
   781
			folders.Close();
hgs
parents:
diff changeset
   782
			return err;
hgs
parents:
diff changeset
   783
			}
hgs
parents:
diff changeset
   784
		}
hgs
parents:
diff changeset
   785
	folders.Close();
hgs
parents:
diff changeset
   786
	return KErrNone;
hgs
parents:
diff changeset
   787
	}
hgs
parents:
diff changeset
   788
hgs
parents:
diff changeset
   789
/**
hgs
parents:
diff changeset
   790
  Recursively finds the subdirectories in aArray and stores references to the
hgs
parents:
diff changeset
   791
  entries in the most derived subdirectory in aRomEntryArray
hgs
parents:
diff changeset
   792
hgs
parents:
diff changeset
   793
  @param aRomEntryArray on return will contain the entries in the directory corresponding to aArray
hgs
parents:
diff changeset
   794
  @param aArray an array containing the directory to get the entries for, i.e. { 'sys', 'bin' }
hgs
parents:
diff changeset
   795
  @param aAddress address in rom to being searching from
hgs
parents:
diff changeset
   796
hgs
parents:
diff changeset
   797
  @param KErrNone on success, or one of the other system wide error codes
hgs
parents:
diff changeset
   798
*/
hgs
parents:
diff changeset
   799
TInt TListManager::GetDirectoryEntries(RPointerArray<TRomEntry>& aRomEntryArray, RArray<TPtr8>& aArray, TLinAddr& aAddress) const
hgs
parents:
diff changeset
   800
	{
hgs
parents:
diff changeset
   801
	LOG_MSG2("TListManager::GetDirectoryEntries() aAddress: 0x%08x", aAddress);
hgs
parents:
diff changeset
   802
hgs
parents:
diff changeset
   803
	//find the next subdirectory and store its address in aAddress, return error if we can't find it
hgs
parents:
diff changeset
   804
	TInt err = FindDirectory(aArray[0], aAddress);
hgs
parents:
diff changeset
   805
	if(err != KErrNone)
hgs
parents:
diff changeset
   806
		{
hgs
parents:
diff changeset
   807
		return err;
hgs
parents:
diff changeset
   808
		}
hgs
parents:
diff changeset
   809
hgs
parents:
diff changeset
   810
	//if this is the most derived sub-directory (i.e. the bin of z:\sys\bin) then get the dir contents
hgs
parents:
diff changeset
   811
	if(aArray.Count() == 1)
hgs
parents:
diff changeset
   812
		{
hgs
parents:
diff changeset
   813
		return GetDirectoryContents(aRomEntryArray, aAddress);
hgs
parents:
diff changeset
   814
		}
hgs
parents:
diff changeset
   815
	else
hgs
parents:
diff changeset
   816
		{
hgs
parents:
diff changeset
   817
		//get the next subdirectory's contents
hgs
parents:
diff changeset
   818
		aArray.Remove(0);
hgs
parents:
diff changeset
   819
		return GetDirectoryEntries(aRomEntryArray, aArray, aAddress);
hgs
parents:
diff changeset
   820
		}
hgs
parents:
diff changeset
   821
	}
hgs
parents:
diff changeset
   822
hgs
parents:
diff changeset
   823
/**
hgs
parents:
diff changeset
   824
Return the entries of a directory in the rom
hgs
parents:
diff changeset
   825
hgs
parents:
diff changeset
   826
@param aRomEntryArray array to store the entries in
hgs
parents:
diff changeset
   827
@param aAddress address of a directory block in the rom
hgs
parents:
diff changeset
   828
*/
hgs
parents:
diff changeset
   829
TInt TListManager::GetDirectoryContents(RPointerArray<TRomEntry>& aRomEntryArray, const TLinAddr aAddress) const
hgs
parents:
diff changeset
   830
	{
hgs
parents:
diff changeset
   831
	LOG_MSG("TListManager::GetDirectoryContents()");
hgs
parents:
diff changeset
   832
hgs
parents:
diff changeset
   833
	TLinAddr address = aAddress;
hgs
parents:
diff changeset
   834
hgs
parents:
diff changeset
   835
	//get the size in bytes of the block of rom to iterate over
hgs
parents:
diff changeset
   836
	const TUint32 sizeInBytes = *(TUint32*)aAddress;
hgs
parents:
diff changeset
   837
hgs
parents:
diff changeset
   838
	//get address of first TRomEntry
hgs
parents:
diff changeset
   839
	const TLinAddr initialAddress = aAddress + sizeof(TUint32);
hgs
parents:
diff changeset
   840
hgs
parents:
diff changeset
   841
	//get pointer to subdir count
hgs
parents:
diff changeset
   842
	address = initialAddress + sizeInBytes;
hgs
parents:
diff changeset
   843
hgs
parents:
diff changeset
   844
	//the upper two bytes of this entry contain the number of files in this directory, and the lower two bytes
hgs
parents:
diff changeset
   845
	//contains the number of subdirectories in this directory
hgs
parents:
diff changeset
   846
	TUint32 filesAndDirectories = *(TUint32*)address;
hgs
parents:
diff changeset
   847
hgs
parents:
diff changeset
   848
	//get number of subdirectories in this directory
hgs
parents:
diff changeset
   849
	const TUint16 subDirCount = filesAndDirectories & 0xFFFF;
hgs
parents:
diff changeset
   850
hgs
parents:
diff changeset
   851
	//get the number of files in this dir
hgs
parents:
diff changeset
   852
	const TUint16 filesCount = filesAndDirectories >> 16;
hgs
parents:
diff changeset
   853
hgs
parents:
diff changeset
   854
	//get total number of entries in dir
hgs
parents:
diff changeset
   855
	const TUint numDirectoryEntries = subDirCount + filesCount;
hgs
parents:
diff changeset
   856
hgs
parents:
diff changeset
   857
	//set address to start of first entry
hgs
parents:
diff changeset
   858
	address = initialAddress;
hgs
parents:
diff changeset
   859
hgs
parents:
diff changeset
   860
	for(TInt i=0; i<numDirectoryEntries; i++)
hgs
parents:
diff changeset
   861
		{
hgs
parents:
diff changeset
   862
		TRomEntry* romEntry = (TRomEntry*)address;
hgs
parents:
diff changeset
   863
hgs
parents:
diff changeset
   864
		//store the entry
hgs
parents:
diff changeset
   865
		TInt err = aRomEntryArray.Append(romEntry);
hgs
parents:
diff changeset
   866
		if(KErrNone != err)
hgs
parents:
diff changeset
   867
			{
hgs
parents:
diff changeset
   868
			return err;
hgs
parents:
diff changeset
   869
			}
hgs
parents:
diff changeset
   870
hgs
parents:
diff changeset
   871
		//length of the name of the rom entry
hgs
parents:
diff changeset
   872
		TInt nameLength = romEntry->iNameLength;
hgs
parents:
diff changeset
   873
hgs
parents:
diff changeset
   874
		//get the size of the entry including the name
hgs
parents:
diff changeset
   875
		TUint32 romEntrySize = sizeof(TRomEntry) - sizeof(romEntry->iName) + (2 * nameLength);
hgs
parents:
diff changeset
   876
		//adjust the address to the next entry
hgs
parents:
diff changeset
   877
		address += Align4(romEntrySize);
hgs
parents:
diff changeset
   878
		}
hgs
parents:
diff changeset
   879
	return KErrNone;
hgs
parents:
diff changeset
   880
	}
hgs
parents:
diff changeset
   881
hgs
parents:
diff changeset
   882
/**
hgs
parents:
diff changeset
   883
  Finds the subdirectory with name aDirectory in the directory at aAddress
hgs
parents:
diff changeset
   884
hgs
parents:
diff changeset
   885
  @param aDirectory name of subdirectory to search for (i.e. 'bin')
hgs
parents:
diff changeset
   886
  @param aAddress address in rom of containing directory (i.e. address of 'sys' directory)
hgs
parents:
diff changeset
   887
hgs
parents:
diff changeset
   888
  @param KErrNone if aDirectory could be found in aAddress, KErrNotFound if it could not be found
hgs
parents:
diff changeset
   889
  */
hgs
parents:
diff changeset
   890
TInt TListManager::FindDirectory(const TDesC& aDirectory, TLinAddr& aAddress) const
hgs
parents:
diff changeset
   891
	{
hgs
parents:
diff changeset
   892
	LOG_MSG3("TListManager::FindDirectory() aDirectory: %S, aAddress: 0x%08x", &aDirectory, aAddress);
hgs
parents:
diff changeset
   893
hgs
parents:
diff changeset
   894
	//get the directory's contents
hgs
parents:
diff changeset
   895
	RPointerArray<TRomEntry> dirContents;
hgs
parents:
diff changeset
   896
	TInt err = GetDirectoryContents(dirContents, aAddress);
hgs
parents:
diff changeset
   897
	if(KErrNone != err)
hgs
parents:
diff changeset
   898
		{
hgs
parents:
diff changeset
   899
		dirContents.Close();
hgs
parents:
diff changeset
   900
		return err;
hgs
parents:
diff changeset
   901
		}
hgs
parents:
diff changeset
   902
	for(TInt i=0; i<dirContents.Count(); i++)
hgs
parents:
diff changeset
   903
		{
hgs
parents:
diff changeset
   904
		//create a reference to the TRomEntry in the rom to access its attributes
hgs
parents:
diff changeset
   905
		TRomEntry& romEntry = *(dirContents[i]);
hgs
parents:
diff changeset
   906
		if(romEntry.iAtt & KEntryAttDir)
hgs
parents:
diff changeset
   907
			{
hgs
parents:
diff changeset
   908
			// this entry's a directory so check if it matches aDirectory
hgs
parents:
diff changeset
   909
			const TInt nameLength = romEntry.iNameLength;
hgs
parents:
diff changeset
   910
			TPtr8 name((TUint8*)&(romEntry.iName), nameLength * 2, nameLength * 2);
hgs
parents:
diff changeset
   911
			if(0 == aDirectory.CompareF(name))
hgs
parents:
diff changeset
   912
				{
hgs
parents:
diff changeset
   913
				// names matched so get the address of this directory's contents
hgs
parents:
diff changeset
   914
				aAddress = romEntry.iAddressLin;
hgs
parents:
diff changeset
   915
				dirContents.Close();
hgs
parents:
diff changeset
   916
				return KErrNone;
hgs
parents:
diff changeset
   917
				}
hgs
parents:
diff changeset
   918
			}
hgs
parents:
diff changeset
   919
		}
hgs
parents:
diff changeset
   920
	dirContents.Close();
hgs
parents:
diff changeset
   921
	//couldn't find it so return error
hgs
parents:
diff changeset
   922
	return KErrNotFound;
hgs
parents:
diff changeset
   923
	}
hgs
parents:
diff changeset
   924
hgs
parents:
diff changeset
   925
/**
hgs
parents:
diff changeset
   926
  Helper function to get code seg type.
hgs
parents:
diff changeset
   927
hgs
parents:
diff changeset
   928
  @param aCodeSeg code seg to get type of
hgs
parents:
diff changeset
   929
  @param aType will contain type on return
hgs
parents:
diff changeset
   930
hgs
parents:
diff changeset
   931
  @return KErrNone on success, KErrNotFound if aCodeSeg is NULL
hgs
parents:
diff changeset
   932
  */
hgs
parents:
diff changeset
   933
TInt TListManager::GetCodeSegType(const DCodeSeg* aCodeSeg, TCodeSegType& aType) const
hgs
parents:
diff changeset
   934
	{
hgs
parents:
diff changeset
   935
	if(!aCodeSeg)
hgs
parents:
diff changeset
   936
		{
hgs
parents:
diff changeset
   937
		return KErrNotFound;
hgs
parents:
diff changeset
   938
		}
hgs
parents:
diff changeset
   939
hgs
parents:
diff changeset
   940
	if(aCodeSeg->IsExe())
hgs
parents:
diff changeset
   941
		{
hgs
parents:
diff changeset
   942
		aType = EExeCodeSegType;
hgs
parents:
diff changeset
   943
		return KErrNone;
hgs
parents:
diff changeset
   944
		}
hgs
parents:
diff changeset
   945
hgs
parents:
diff changeset
   946
	if(aCodeSeg->IsDll())
hgs
parents:
diff changeset
   947
		{
hgs
parents:
diff changeset
   948
		aType = EDllCodeSegType;
hgs
parents:
diff changeset
   949
		return KErrNone;
hgs
parents:
diff changeset
   950
		}
hgs
parents:
diff changeset
   951
hgs
parents:
diff changeset
   952
	aType = EUnknownCodeSegType;
hgs
parents:
diff changeset
   953
	return KErrNone;
hgs
parents:
diff changeset
   954
	}
hgs
parents:
diff changeset
   955
hgs
parents:
diff changeset
   956
hgs
parents:
diff changeset
   957
/**
hgs
parents:
diff changeset
   958
  Split a directory name into its subdirectories, using a 16-bit backslash ('\\\0') as a delimiter.
hgs
parents:
diff changeset
   959
  For example z:\sys\bin would be split into { 'z:', 'sys', 'bin' }
hgs
parents:
diff changeset
   960
hgs
parents:
diff changeset
   961
  @param aDirectoryName directory name to split into subdirectories
hgs
parents:
diff changeset
   962
  @param aSubDirectories array to store the subdirectories in
hgs
parents:
diff changeset
   963
  */
hgs
parents:
diff changeset
   964
TInt TListManager::SplitDirectoryName(const TDesC& aDirectoryName, RArray<TPtr8>& aSubDirectories) const
hgs
parents:
diff changeset
   965
	{
hgs
parents:
diff changeset
   966
	//definition in 16 bit unicode
hgs
parents:
diff changeset
   967
	_LIT(KBackSlash, "\\\0");
hgs
parents:
diff changeset
   968
hgs
parents:
diff changeset
   969
	//split the directory up into its folders, i.e. z:\sys\bin is split into 
hgs
parents:
diff changeset
   970
	TPtr8 string((TUint8*)aDirectoryName.Ptr(), aDirectoryName.Length(), aDirectoryName.Length());
hgs
parents:
diff changeset
   971
	while(string.Ptr() < aDirectoryName.Ptr() + aDirectoryName.Length())
hgs
parents:
diff changeset
   972
		{
hgs
parents:
diff changeset
   973
		TInt offset = string.Find(KBackSlash());
hgs
parents:
diff changeset
   974
		if(offset == KErrNotFound)
hgs
parents:
diff changeset
   975
			{
hgs
parents:
diff changeset
   976
			//reached the end of the string
hgs
parents:
diff changeset
   977
			offset = string.Length();
hgs
parents:
diff changeset
   978
			}
hgs
parents:
diff changeset
   979
		//adjustedOffset takes account of the end of the string case
hgs
parents:
diff changeset
   980
		TInt adjustedOffset = (offset == string.Length()) ? offset : offset + KBackSlash().Length();
hgs
parents:
diff changeset
   981
		//add sub-folder name
hgs
parents:
diff changeset
   982
		TInt err = aSubDirectories.Append(TPtr8((TUint8*)string.Ptr(), offset, offset));
hgs
parents:
diff changeset
   983
		if(KErrNone != err)
hgs
parents:
diff changeset
   984
			{
hgs
parents:
diff changeset
   985
			return err;
hgs
parents:
diff changeset
   986
			}
hgs
parents:
diff changeset
   987
		//remove the sub-folder name and continue
hgs
parents:
diff changeset
   988
		string.Set((TUint8*)string.Ptr() + adjustedOffset, string.Length() - adjustedOffset, string.Length() - adjustedOffset);
hgs
parents:
diff changeset
   989
		}
hgs
parents:
diff changeset
   990
	return KErrNone;
hgs
parents:
diff changeset
   991
	}
hgs
parents:
diff changeset
   992
hgs
parents:
diff changeset
   993
hgs
parents:
diff changeset
   994