os/ossrv/genericopenlibs/cstdlib/USTW32/UW32SVR.CPP
author sl
Tue, 10 Jun 2014 14:32:02 +0200
changeset 1 260cb5ec6c19
permissions -rw-r--r--
Update contrib.
     1 // Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies).
     2 // All rights reserved.
     3 // This component and the accompanying materials are made available
     4 // under the terms of "Eclipse Public License v1.0"
     5 // which accompanies this distribution, and is available
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
     7 //
     8 // Initial Contributors:
     9 // Nokia Corporation - initial contribution.
    10 //
    11 // Contributors:
    12 //
    13 // Description:
    14 //
    15 
    16 
    17 #include <e32std.h>
    18 #if defined(_UNICODE)
    19 #if !defined(UNICODE)
    20 #define UNICODE
    21 #endif
    22 #endif
    23 #define WIN32_LEAN_AND_MEAN
    24 #pragma warning( disable : 4201 ) // nonstandard extension used : nameless struct/union
    25 #include <windows.h>
    26 #include <winbase.h>
    27 #include <TCHAR.H>
    28 #pragma warning( default : 4201 ) // nonstandard extension used : nameless struct/union
    29 
    30 #include "ESTW32SV.H"
    31 
    32 #ifndef EKA2
    33 GLDEF_C TInt E32Dll(TDllReason)
    34 	{
    35 	return KErrNone;
    36 	}
    37 #endif
    38 
    39 // -------------- CLIENT IMPLEMENTATION -----------------------------
    40 
    41 EXPORT_C void RWin32Stream::StartServer()
    42 //
    43 // Static function which spawns the three servers
    44 //
    45 	{
    46 	CWin32Stream::StartServer(Kstdin);
    47 	CWin32Stream::StartServer(Kstdout);
    48 	CWin32Stream::StartServer(Kstderr);
    49 	}
    50 
    51 EXPORT_C TInt RWin32Stream::Open(TInt aStream)
    52 	{
    53 	TBuf<8> stream;
    54 	if (CWin32Stream::StreamName(aStream,stream)!=KErrNone)
    55 		return KErrArgument;
    56 	TVersion version(1,0,0);
    57 	return CreateSession(stream,version,1);	// only one message allowed - no concurrency
    58 	}
    59 
    60 TInt RWin32Stream::CheckEOF(TRequestStatus& aStatus)
    61 	{
    62 	if (Handle()!=0)
    63 		return KErrNone;
    64 	TRequestStatus* aStatusPtr=&aStatus;
    65 	User::RequestComplete(aStatusPtr,KErrEof);
    66 	return KErrEof;
    67 	}
    68 	
    69 EXPORT_C void RWin32Stream::Read(TRequestStatus& aStatus, TDes8& aDes)
    70 	{
    71 	Read(aStatus, aDes, aDes.MaxLength());
    72 	}
    73 
    74 EXPORT_C void RWin32Stream::Read(TRequestStatus& aStatus, TDes8& aDes, TInt aLength)
    75 	{
    76 	if (CheckEOF(aStatus))
    77 		return;
    78 	SendReceive(EWin32Read,TIpcArgs(&aDes,aLength),aStatus);
    79 	}
    80 
    81 EXPORT_C void RWin32Stream::Write(TRequestStatus& aStatus, const TDesC8& aDes)
    82 	{
    83 	Write(aStatus, aDes, aDes.Length());
    84 	}
    85 
    86 EXPORT_C void RWin32Stream::Write(TRequestStatus& aStatus, const TDesC8& aDes, TInt aLength)
    87 //
    88 // Write aLength bytes
    89 //
    90 	{
    91 	if (CheckEOF(aStatus))
    92 		return;
    93 	SendReceive(EWin32Write,TIpcArgs(&aDes,aLength),aStatus);
    94 	}
    95 
    96 EXPORT_C void RWin32Stream::Flush(TRequestStatus& aStatus)
    97 //
    98 // Flush output
    99 //
   100 	{
   101 	if (CheckEOF(aStatus))
   102 		return;
   103 	SendReceive(EWin32Flush,aStatus);
   104 	}
   105 
   106 // -------------- SERVER IMPLEMENTATION -----------------------------
   107 //
   108 // This is only relevant to WINS, so we know that in truth it's all a single address space
   109 // and we can just operate on the descriptors directly.
   110 
   111 //#define ESTW32_LOGGING	// log the stream output into a file
   112 
   113 TInt CWin32Stream::StreamName(TInt aStream, TDes& aBuf)
   114 	{
   115 	switch (aStream)
   116 		{
   117 	case Kstdin:
   118 		aBuf=_L("stdin"); break;
   119 	case Kstdout:
   120 		aBuf=_L("stdout"); break;
   121 	case Kstderr:
   122 		aBuf=_L("stderr"); break;
   123 	default:
   124 		return KErrArgument;
   125 		}
   126 	return KErrNone;
   127 	}
   128 
   129 struct rendezvous 
   130 	{
   131 	TRequestStatus*	iStatus;
   132 	TInt	iStream;
   133 	RThread iCaller;
   134 	TBuf<8> iStreamName;
   135 	};
   136 
   137 void CWin32Stream::StartServer(TInt aStream)
   138 //
   139 // Static function which spawns a server thread
   140 //
   141 	{
   142 	TRequestStatus status(KRequestPending);
   143 	struct rendezvous rv;
   144 	rv.iStatus=&status;
   145 	rv.iStream=aStream;
   146 	TInt err=StreamName(aStream,rv.iStreamName);
   147 	if (err!=KErrNone)
   148 		return;
   149 	err=rv.iCaller.Duplicate(RThread(),EOwnerProcess);
   150 	if (err!=KErrNone)
   151 		return;
   152 	RThread server;
   153 	err=server.Create(rv.iStreamName,ThreadFunction,2048,4096,65536,(TAny*)&rv,EOwnerProcess);
   154 	if (err==KErrNone) 
   155 		{
   156 		server.Resume();
   157 		User::WaitForRequest(status);
   158 		server.Close();
   159 		}
   160 	rv.iCaller.Close();
   161 	}
   162 
   163 TInt CWin32Stream::ThreadFunction(TAny* aPtr)
   164 	{
   165 	struct rendezvous* rvp=(struct rendezvous*)aPtr;
   166 	TInt err=KErrNoMemory;
   167 	CWin32Stream* stream = new CWin32Stream();
   168 	if (stream!=0)
   169 		err=stream->Init(rvp->iStream, rvp->iStreamName);
   170 	rvp->iCaller.RequestComplete(rvp->iStatus,err);	// let the caller continue
   171 	if (err==KErrNone)
   172 		{
   173 		FOREVER
   174 			stream->HandleMessage();
   175 		}
   176 	else
   177 		{
   178 		delete stream;
   179 		}
   180 	return err;
   181 	}
   182 
   183 TInt CWin32Stream::Init(TInt aStream, const TDesC& aStreamName)
   184 	{
   185 	iHandle = GetStdHandle((STD_INPUT_HANDLE)-(int)aStream);
   186 	if (iHandle==INVALID_HANDLE_VALUE)
   187 		return KErrNotFound;
   188 
   189 #ifdef ESTW32_LOGGING
   190 	static char* logs[3]={ "x:\\stdin.log", "x:\\stdout.log", "x:\\stderr.log"};
   191 	iLogHandle=CreateFile(logs[aStream], GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
   192 #else
   193 	iLogHandle=INVALID_HANDLE_VALUE;
   194 #endif
   195 
   196 	return iServer.CreateGlobal(aStreamName);
   197 	}
   198 
   199 void CWin32Stream::HandleMessage()
   200 	{
   201 	iServer.Receive(iMessage);
   202 	TInt err=KErrNone;
   203 	TInt f=iMessage.Function();
   204 	switch (f)
   205 		{
   206 	case RMessage2::EConnect:
   207 	case RMessage2::EDisConnect:
   208 		// RServer2 connection management - nothing interesting to be done
   209 		break;
   210 
   211 	case EWin32Read:
   212 		err=ReadStream(iMessage);
   213 		break;
   214 	case EWin32Write:
   215 		err=WriteStream(iMessage);
   216 		break;
   217 	case EWin32Flush:
   218 		FlushStream();
   219 		break;
   220 
   221 	default:
   222 		err=KErrNotSupported;
   223 		break;
   224 		}
   225 	iMessage.Complete(err);
   226 	}
   227 
   228 TInt CWin32Stream::ReadStream(RMessage2& aMessage)
   229 	{
   230 	TDes8* bufDes = (TDes8*)(aMessage.Ptr0());
   231 	int length = aMessage.Int1();
   232 	unsigned long nbytes;
   233 
   234 	if (ReadFile(iHandle, (TAny*)(bufDes->Ptr()), length, &nbytes, 0) && nbytes>0)
   235 		{
   236 		bufDes->SetLength(nbytes);
   237 		return KErrNone;
   238 		}
   239 	return MapWin32Error(KErrEof);
   240 	}
   241 
   242 TInt CWin32Stream::WriteStream(RMessage2& aMessage)
   243 	{
   244 	TDesC8* bufDes = (TDesC8*)(aMessage.Ptr0());
   245 	int length = aMessage.Int1();
   246 	int offset = 0;
   247 	unsigned long nbytes;
   248 
   249 #ifdef ESTW32_LOGGING
   250 	WriteFile(iLogHandle, bufDes->Ptr(), length, &nbytes, 0);
   251 	FlushFileBuffers(iLogHandle);
   252 #endif
   253 
   254 	while (length>offset)
   255 		{
   256 		if (!WriteFile(iHandle, bufDes->Ptr()+offset, length-offset, &nbytes, 0))
   257 			return MapWin32Error(KErrEof);
   258 		offset+=nbytes;
   259 		}
   260 	return KErrNone;
   261 	}
   262 
   263 void CWin32Stream::FlushStream()
   264 	{
   265 	FlushFileBuffers(iHandle);	// don't care if it works or not
   266 	}
   267 
   268 #include <winerror.h>
   269 
   270 TInt CWin32Stream::MapWin32Error(TInt aDefault)
   271 	{
   272 	switch (GetLastError())
   273 		{
   274 	case ERROR_INVALID_HANDLE:
   275 		return KErrBadHandle;
   276 	case ERROR_HANDLE_EOF:
   277 		return KErrEof;
   278 		}
   279 	return aDefault;
   280 	}