libraries/iosrv/client/iocons.cpp
changeset 0 7f656887cf89
equal deleted inserted replaced
-1:000000000000 0:7f656887cf89
       
     1 // iocons.cpp
       
     2 // 
       
     3 // Copyright (c) 2006 - 2010 Accenture. All rights reserved.
       
     4 // This component and the accompanying materials are made available
       
     5 // under the terms of the "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 // Accenture - Initial contribution
       
    11 //
       
    12 
       
    13 #include <fshell/iocli.h>
       
    14 #include <fshell/consoleextensions.h>
       
    15 #include "iocons.h"
       
    16 #include <fshell/ioutils.h>
       
    17 #include <fshell/common.mmh>
       
    18 #ifdef FSHELL_MEMORY_ACCESS_SUPPORT
       
    19 #include <fshell/memoryaccess.h>
       
    20 #endif
       
    21 
       
    22 // This constant is used to find the PIPS Stdio Server CServer2 object in the situation
       
    23 // where iocons in running in the stdioserver.exe process. Normally, when iocons calls
       
    24 // RIo(Read|Write)Handle::Open(RIoSession&), iosrv looks to see if it hand any read or
       
    25 // write objects that belong to the calling thread. Note, when fshell creates a new process
       
    26 // it creates a set of read and write objects inside iosrv, and assigns them as being owned
       
    27 // by the main thread of the new process. However, in the case of PIPS, the main thread
       
    28 // of the process that fshell creates isn't the one that opens the console. This is done
       
    29 // from the context of the sdioserver.exe process. To cater for this, iocons has a special
       
    30 // behaviour when its running in the context of sdioserver.exe. This involves finding the
       
    31 // server's CServer2 sub-class object, and using this to retrieve the current RMessage2
       
    32 // object. From this, the client's thread id can be found. This is passed into a different
       
    33 // RIo(Read|Write)Handle::Open overload that attempt to open a handle using the specified
       
    34 // thread id (not that which iocons is currently running in). If fshell created the process
       
    35 // this should return without error, in which case the PIPS process will be able to share
       
    36 // fshell's console (or take part in a pipe-line that it created). If not, then the old
       
    37 // behaviour of creating a new console will proceed.
       
    38 const TInt KPipsStdioServerAllocPos = 5;
       
    39 
       
    40 
       
    41 CIoConsole::CIoConsole()
       
    42 	{
       
    43 	}
       
    44 
       
    45 CIoConsole::CIoConsole(RIoConsoleReadHandle& aReadHandle, RIoConsoleWriteHandle& aWriteHandle)
       
    46 	{
       
    47 	iReadHandle = aReadHandle;
       
    48 	iWriteHandle = aWriteHandle;
       
    49 	}
       
    50 
       
    51 CIoConsole::~CIoConsole()
       
    52 	{
       
    53 	if (iIoSession.Handle())
       
    54 		{
       
    55 		// If the handle isn't set it means we don't own iReadHandle/iWriteHandle (or they haven't been constructed and we needn't close them anyway)
       
    56 		iReadHandle.Close();
       
    57 		iWriteHandle.Close();
       
    58 		iConsole.Close();
       
    59 		iIoSession.Close();
       
    60 		}
       
    61 	}
       
    62 
       
    63 TInt CIoConsole::Create(const TDesC& aTitle, TSize aSize)
       
    64 	{
       
    65 	// This should only be called via iocons, ie when the zero arguments constructor was used.
       
    66 	// When the 2-arg constructor is used, the console is fully constructed and Create should not be called
       
    67 	TInt err = iIoSession.Connect();
       
    68 	if (err == KErrNone)
       
    69 		{
       
    70 		// See if iosrv has any handles ready for us
       
    71 		err = iReadHandle.Open(iIoSession);
       
    72 		if (err)
       
    73 			{
       
    74 			// If not, check if we're being opened from the stdioserver on behalf of the client PIPS exe
       
    75 			TThreadId clientThreadId;
       
    76 			if (FindClientThreadId(clientThreadId) == KErrNone)
       
    77 				{
       
    78 				err = iReadHandle.Open(iIoSession, clientThreadId);
       
    79 				if (err == KErrNone)
       
    80 					{
       
    81 					err = iWriteHandle.Open(iIoSession, clientThreadId);
       
    82 					if (err != KErrNone)
       
    83 						{
       
    84 						iReadHandle.Close();
       
    85 						}
       
    86 					}
       
    87 				}
       
    88 
       
    89 #ifdef FSHELL_MEMORY_ACCESS_SUPPORT
       
    90 			if (err)
       
    91 				{
       
    92 				// Try and see if the thread that created us has some handles we can use, and if not, the thread that created it etc until we find one or lose track
       
    93 				RMemoryAccess::LoadDriver();
       
    94 				RMemoryAccess memAccess;
       
    95 				err = memAccess.Open();
       
    96 				if (!err) err = iReadHandle.Create(iIoSession);
       
    97 				if (!err) iWriteHandle.Create(iIoSession);
       
    98 				if (!err)
       
    99 					{
       
   100 					TUint creator = RThread().Id();
       
   101 					while (creator != 0)
       
   102 						{
       
   103 						creator = memAccess.GetThreadCreatorId(creator);
       
   104 						err = iReadHandle.DuplicateHandleFromThread(TThreadId(creator));
       
   105 						if (err == KErrNone)
       
   106 							{
       
   107 							// Found one - open the writer too...
       
   108 							err = iWriteHandle.DuplicateHandleFromThread(TThreadId(creator));
       
   109 							break; // Stop looking if we found one
       
   110 							}
       
   111 						}
       
   112 					memAccess.Close();
       
   113 					}
       
   114 				if (err)
       
   115 					{
       
   116 					iReadHandle.Close();
       
   117 					iWriteHandle.Close();
       
   118 					}
       
   119 				}
       
   120 #endif
       
   121 
       
   122 			if (err)
       
   123 				{
       
   124 				// If all else fails, create a new console
       
   125 				err = CreateNewConsole(aTitle, aSize);
       
   126 				}
       
   127 			}
       
   128 		else
       
   129 			{
       
   130 			err = iWriteHandle.Open(iIoSession);
       
   131 			}
       
   132 		}
       
   133 	if (err)
       
   134 		{
       
   135 		iReadHandle.Close();
       
   136 		iWriteHandle.Close();
       
   137 		iConsole.Close();
       
   138 		iIoSession.Close();
       
   139 		}
       
   140 	return err;
       
   141 	}
       
   142 
       
   143 TInt CIoConsole::CreateNewConsole(const TDesC& aTitle, TSize aSize)
       
   144 	{
       
   145 	TInt err = iConsole.Create(iIoSession, aTitle, aSize);
       
   146 	if (err) return err;
       
   147 	err = iReadHandle.Create(iIoSession);
       
   148 	if (err) return err;
       
   149 	err = iWriteHandle.Create(iIoSession);
       
   150 	if (err) return err;
       
   151 	err = iConsole.Attach(iReadHandle, RIoEndPoint::EForeground);
       
   152 	if (err) return err;
       
   153 	err = iConsole.Attach(iWriteHandle);
       
   154 	if (err) return err;
       
   155 
       
   156 	err = iReadHandle.SetOwner(RThread().Id());
       
   157 	if (err) return err;
       
   158 	err = iWriteHandle.SetOwner(RThread().Id());
       
   159 	
       
   160 	return err;
       
   161 	}
       
   162 
       
   163 TBool CIoConsole::HeapWalk(TAny* aSelf, RAllocatorHelper::TCellType aCellType, TLinAddr aCellPtr, TInt)
       
   164 	{
       
   165 	CIoConsole* self = (CIoConsole*)aSelf;
       
   166 	if (aCellType == RAllocatorHelper::EAllocation)
       
   167 		{
       
   168 		if (++(self->iHeapCellCount) == KPipsStdioServerAllocPos)
       
   169 			{
       
   170 			self->iServerAddress = (TAny*)aCellPtr;
       
   171 			return EFalse; // To indicate we're finished
       
   172 			}
       
   173 		}
       
   174 	return ETrue; // keep going
       
   175 	}
       
   176 
       
   177 class CHackedServer : public CServer2
       
   178 	{
       
   179 public:
       
   180 	inline CHackedServer() : CServer2(CActive::EPriorityStandard) {} // needed to shut up gcce
       
   181 	inline const RMessage2& Msg() const { return Message(); }
       
   182 	};
       
   183 
       
   184 TInt CIoConsole::FindClientThreadId(TThreadId& aThreadId)
       
   185 	{
       
   186 	TInt err = KErrNotFound;
       
   187 	_LIT(KPipsStdioServer, "stdioserver.exe*");
       
   188 	TName processName(RProcess().Name());
       
   189 	if (processName.MatchF(KPipsStdioServer) == 0)
       
   190 		{
       
   191 		LtkUtils::RAllocatorHelper allocHelper;
       
   192 		TInt err = allocHelper.Open(&User::Allocator());
       
   193 		if (!err) err = allocHelper.Walk(&HeapWalk, this);
       
   194 		allocHelper.Close();
       
   195 		if (err == KErrNone && iServerAddress)
       
   196 			{
       
   197 			// This means that we found the server's address (possibly).
       
   198 			CHackedServer* server = (CHackedServer*)iServerAddress;
       
   199 			RThread client;
       
   200 			if (server->Msg().Client(client) == KErrNone)
       
   201 				{
       
   202 				err = KErrNone;
       
   203 				aThreadId = client.Id();
       
   204 				client.Close();
       
   205 				}
       
   206 			}
       
   207 		}
       
   208 	return err;
       
   209 	}
       
   210 
       
   211 void CIoConsole::Read(TRequestStatus& aStatus)
       
   212 	{
       
   213 	iReadHandle.WaitForKey(aStatus);
       
   214 	}
       
   215 
       
   216 void CIoConsole::ReadCancel()
       
   217 	{
       
   218 	iReadHandle.WaitForKeyCancel();
       
   219 	}
       
   220 
       
   221 void CIoConsole::Write(const TDesC& aDes)
       
   222 	{
       
   223 	iWriteHandle.Write(aDes);
       
   224 	}
       
   225 
       
   226 TPoint CIoConsole::CursorPos() const
       
   227 	{
       
   228 	TPoint pos;
       
   229 	iWriteHandle.GetCursorPos(pos);
       
   230 	return pos;
       
   231 	}
       
   232 
       
   233 void CIoConsole::SetCursorPosAbs(const TPoint& aPoint)
       
   234 	{
       
   235 	iWriteHandle.SetCursorPosAbs(aPoint);
       
   236 	}
       
   237 
       
   238 void CIoConsole::SetCursorPosRel(const TPoint& aPoint)
       
   239 	{
       
   240 	iWriteHandle.SetCursorPosRel(aPoint);
       
   241 	}
       
   242 
       
   243 void CIoConsole::SetCursorHeight(TInt aPercentage)
       
   244 	{
       
   245 	iWriteHandle.SetCursorHeight(aPercentage);
       
   246 	}
       
   247 
       
   248 void CIoConsole::SetTitle(const TDesC& aTitle)
       
   249 	{
       
   250 	iWriteHandle.SetTitle(aTitle);
       
   251 	}
       
   252 
       
   253 void CIoConsole::ClearScreen()
       
   254 	{
       
   255 	iWriteHandle.ClearScreen();
       
   256 	}
       
   257 
       
   258 void CIoConsole::ClearToEndOfLine()
       
   259 	{
       
   260 	iWriteHandle.ClearToEndOfLine();
       
   261 	}
       
   262 
       
   263 TSize CIoConsole::ScreenSize() const
       
   264 	{
       
   265 	TSize size;
       
   266 	iWriteHandle.GetScreenSize(size);
       
   267 	return size;
       
   268 	}
       
   269 
       
   270 TKeyCode CIoConsole::KeyCode() const
       
   271 	{
       
   272 	return (TKeyCode)iReadHandle.KeyCode();
       
   273 	}
       
   274 
       
   275 TUint CIoConsole::KeyModifiers() const
       
   276 	{
       
   277 	return iReadHandle.KeyModifiers();
       
   278 	}
       
   279 
       
   280 TInt CIoConsole::Extension_(TUint aExtensionId, TAny*& a0, TAny* a1)
       
   281 	{
       
   282 	return CConsoleBase::Extension_(aExtensionId, a0, a1);
       
   283 	}
       
   284 
       
   285 EXPORT_C CConsoleBase* IoUtils::NewConsole()
       
   286 	{
       
   287 	return new CIoConsole;
       
   288 	}
       
   289 
       
   290 // This is horrible, but only way to satisfy WINSCW compiler. If we define it always, we end up re-exporting typeinfo for CColorConsoleBase in armv5 which we don't want to be doing
       
   291 #ifdef __WINS__
       
   292 void CColorConsoleBase::SetTextAttribute(TTextAttribute)
       
   293 	{
       
   294 	}
       
   295 #endif
       
   296 
       
   297 void CIoConsole::SetTextAttribute(TTextAttribute aAttribute)
       
   298 	{
       
   299 	TUint attrib = 0;
       
   300 	switch (aAttribute)
       
   301 		{
       
   302 	case ETextAttributeNormal:
       
   303 		attrib = ConsoleAttributes::ENone;
       
   304 		break;
       
   305 	case ETextAttributeBold:
       
   306 		attrib = ConsoleAttributes::EBold;
       
   307 		break;
       
   308 	case ETextAttributeInverse:
       
   309 		attrib = ConsoleAttributes::EInverse;
       
   310 		break;
       
   311 	case ETextAttributeHighlight:
       
   312 		// Should highlight map to inverse? Seems slightly better than bold
       
   313 		attrib = ConsoleAttributes::EInverse;
       
   314 		break;
       
   315 	default:
       
   316 		break;
       
   317 		}
       
   318 	iWriteHandle.SetAttributes(attrib); // Can't do anything with the error
       
   319 	}