genericopenlibs/cstdlib/USTW32/UW32SVR.CPP
changeset 0 e4d67989cc36
equal deleted inserted replaced
-1:000000000000 0:e4d67989cc36
       
     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 	}