1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/ossrv/genericopenlibs/cstdlib/USTW32/UW32SVR.CPP Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,280 @@
1.4 +// Copyright (c) 1999-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +//
1.18 +
1.19 +
1.20 +#include <e32std.h>
1.21 +#if defined(_UNICODE)
1.22 +#if !defined(UNICODE)
1.23 +#define UNICODE
1.24 +#endif
1.25 +#endif
1.26 +#define WIN32_LEAN_AND_MEAN
1.27 +#pragma warning( disable : 4201 ) // nonstandard extension used : nameless struct/union
1.28 +#include <windows.h>
1.29 +#include <winbase.h>
1.30 +#include <TCHAR.H>
1.31 +#pragma warning( default : 4201 ) // nonstandard extension used : nameless struct/union
1.32 +
1.33 +#include "ESTW32SV.H"
1.34 +
1.35 +#ifndef EKA2
1.36 +GLDEF_C TInt E32Dll(TDllReason)
1.37 + {
1.38 + return KErrNone;
1.39 + }
1.40 +#endif
1.41 +
1.42 +// -------------- CLIENT IMPLEMENTATION -----------------------------
1.43 +
1.44 +EXPORT_C void RWin32Stream::StartServer()
1.45 +//
1.46 +// Static function which spawns the three servers
1.47 +//
1.48 + {
1.49 + CWin32Stream::StartServer(Kstdin);
1.50 + CWin32Stream::StartServer(Kstdout);
1.51 + CWin32Stream::StartServer(Kstderr);
1.52 + }
1.53 +
1.54 +EXPORT_C TInt RWin32Stream::Open(TInt aStream)
1.55 + {
1.56 + TBuf<8> stream;
1.57 + if (CWin32Stream::StreamName(aStream,stream)!=KErrNone)
1.58 + return KErrArgument;
1.59 + TVersion version(1,0,0);
1.60 + return CreateSession(stream,version,1); // only one message allowed - no concurrency
1.61 + }
1.62 +
1.63 +TInt RWin32Stream::CheckEOF(TRequestStatus& aStatus)
1.64 + {
1.65 + if (Handle()!=0)
1.66 + return KErrNone;
1.67 + TRequestStatus* aStatusPtr=&aStatus;
1.68 + User::RequestComplete(aStatusPtr,KErrEof);
1.69 + return KErrEof;
1.70 + }
1.71 +
1.72 +EXPORT_C void RWin32Stream::Read(TRequestStatus& aStatus, TDes8& aDes)
1.73 + {
1.74 + Read(aStatus, aDes, aDes.MaxLength());
1.75 + }
1.76 +
1.77 +EXPORT_C void RWin32Stream::Read(TRequestStatus& aStatus, TDes8& aDes, TInt aLength)
1.78 + {
1.79 + if (CheckEOF(aStatus))
1.80 + return;
1.81 + SendReceive(EWin32Read,TIpcArgs(&aDes,aLength),aStatus);
1.82 + }
1.83 +
1.84 +EXPORT_C void RWin32Stream::Write(TRequestStatus& aStatus, const TDesC8& aDes)
1.85 + {
1.86 + Write(aStatus, aDes, aDes.Length());
1.87 + }
1.88 +
1.89 +EXPORT_C void RWin32Stream::Write(TRequestStatus& aStatus, const TDesC8& aDes, TInt aLength)
1.90 +//
1.91 +// Write aLength bytes
1.92 +//
1.93 + {
1.94 + if (CheckEOF(aStatus))
1.95 + return;
1.96 + SendReceive(EWin32Write,TIpcArgs(&aDes,aLength),aStatus);
1.97 + }
1.98 +
1.99 +EXPORT_C void RWin32Stream::Flush(TRequestStatus& aStatus)
1.100 +//
1.101 +// Flush output
1.102 +//
1.103 + {
1.104 + if (CheckEOF(aStatus))
1.105 + return;
1.106 + SendReceive(EWin32Flush,aStatus);
1.107 + }
1.108 +
1.109 +// -------------- SERVER IMPLEMENTATION -----------------------------
1.110 +//
1.111 +// This is only relevant to WINS, so we know that in truth it's all a single address space
1.112 +// and we can just operate on the descriptors directly.
1.113 +
1.114 +//#define ESTW32_LOGGING // log the stream output into a file
1.115 +
1.116 +TInt CWin32Stream::StreamName(TInt aStream, TDes& aBuf)
1.117 + {
1.118 + switch (aStream)
1.119 + {
1.120 + case Kstdin:
1.121 + aBuf=_L("stdin"); break;
1.122 + case Kstdout:
1.123 + aBuf=_L("stdout"); break;
1.124 + case Kstderr:
1.125 + aBuf=_L("stderr"); break;
1.126 + default:
1.127 + return KErrArgument;
1.128 + }
1.129 + return KErrNone;
1.130 + }
1.131 +
1.132 +struct rendezvous
1.133 + {
1.134 + TRequestStatus* iStatus;
1.135 + TInt iStream;
1.136 + RThread iCaller;
1.137 + TBuf<8> iStreamName;
1.138 + };
1.139 +
1.140 +void CWin32Stream::StartServer(TInt aStream)
1.141 +//
1.142 +// Static function which spawns a server thread
1.143 +//
1.144 + {
1.145 + TRequestStatus status(KRequestPending);
1.146 + struct rendezvous rv;
1.147 + rv.iStatus=&status;
1.148 + rv.iStream=aStream;
1.149 + TInt err=StreamName(aStream,rv.iStreamName);
1.150 + if (err!=KErrNone)
1.151 + return;
1.152 + err=rv.iCaller.Duplicate(RThread(),EOwnerProcess);
1.153 + if (err!=KErrNone)
1.154 + return;
1.155 + RThread server;
1.156 + err=server.Create(rv.iStreamName,ThreadFunction,2048,4096,65536,(TAny*)&rv,EOwnerProcess);
1.157 + if (err==KErrNone)
1.158 + {
1.159 + server.Resume();
1.160 + User::WaitForRequest(status);
1.161 + server.Close();
1.162 + }
1.163 + rv.iCaller.Close();
1.164 + }
1.165 +
1.166 +TInt CWin32Stream::ThreadFunction(TAny* aPtr)
1.167 + {
1.168 + struct rendezvous* rvp=(struct rendezvous*)aPtr;
1.169 + TInt err=KErrNoMemory;
1.170 + CWin32Stream* stream = new CWin32Stream();
1.171 + if (stream!=0)
1.172 + err=stream->Init(rvp->iStream, rvp->iStreamName);
1.173 + rvp->iCaller.RequestComplete(rvp->iStatus,err); // let the caller continue
1.174 + if (err==KErrNone)
1.175 + {
1.176 + FOREVER
1.177 + stream->HandleMessage();
1.178 + }
1.179 + else
1.180 + {
1.181 + delete stream;
1.182 + }
1.183 + return err;
1.184 + }
1.185 +
1.186 +TInt CWin32Stream::Init(TInt aStream, const TDesC& aStreamName)
1.187 + {
1.188 + iHandle = GetStdHandle((STD_INPUT_HANDLE)-(int)aStream);
1.189 + if (iHandle==INVALID_HANDLE_VALUE)
1.190 + return KErrNotFound;
1.191 +
1.192 +#ifdef ESTW32_LOGGING
1.193 + static char* logs[3]={ "x:\\stdin.log", "x:\\stdout.log", "x:\\stderr.log"};
1.194 + iLogHandle=CreateFile(logs[aStream], GENERIC_WRITE, FILE_SHARE_READ, 0, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, 0);
1.195 +#else
1.196 + iLogHandle=INVALID_HANDLE_VALUE;
1.197 +#endif
1.198 +
1.199 + return iServer.CreateGlobal(aStreamName);
1.200 + }
1.201 +
1.202 +void CWin32Stream::HandleMessage()
1.203 + {
1.204 + iServer.Receive(iMessage);
1.205 + TInt err=KErrNone;
1.206 + TInt f=iMessage.Function();
1.207 + switch (f)
1.208 + {
1.209 + case RMessage2::EConnect:
1.210 + case RMessage2::EDisConnect:
1.211 + // RServer2 connection management - nothing interesting to be done
1.212 + break;
1.213 +
1.214 + case EWin32Read:
1.215 + err=ReadStream(iMessage);
1.216 + break;
1.217 + case EWin32Write:
1.218 + err=WriteStream(iMessage);
1.219 + break;
1.220 + case EWin32Flush:
1.221 + FlushStream();
1.222 + break;
1.223 +
1.224 + default:
1.225 + err=KErrNotSupported;
1.226 + break;
1.227 + }
1.228 + iMessage.Complete(err);
1.229 + }
1.230 +
1.231 +TInt CWin32Stream::ReadStream(RMessage2& aMessage)
1.232 + {
1.233 + TDes8* bufDes = (TDes8*)(aMessage.Ptr0());
1.234 + int length = aMessage.Int1();
1.235 + unsigned long nbytes;
1.236 +
1.237 + if (ReadFile(iHandle, (TAny*)(bufDes->Ptr()), length, &nbytes, 0) && nbytes>0)
1.238 + {
1.239 + bufDes->SetLength(nbytes);
1.240 + return KErrNone;
1.241 + }
1.242 + return MapWin32Error(KErrEof);
1.243 + }
1.244 +
1.245 +TInt CWin32Stream::WriteStream(RMessage2& aMessage)
1.246 + {
1.247 + TDesC8* bufDes = (TDesC8*)(aMessage.Ptr0());
1.248 + int length = aMessage.Int1();
1.249 + int offset = 0;
1.250 + unsigned long nbytes;
1.251 +
1.252 +#ifdef ESTW32_LOGGING
1.253 + WriteFile(iLogHandle, bufDes->Ptr(), length, &nbytes, 0);
1.254 + FlushFileBuffers(iLogHandle);
1.255 +#endif
1.256 +
1.257 + while (length>offset)
1.258 + {
1.259 + if (!WriteFile(iHandle, bufDes->Ptr()+offset, length-offset, &nbytes, 0))
1.260 + return MapWin32Error(KErrEof);
1.261 + offset+=nbytes;
1.262 + }
1.263 + return KErrNone;
1.264 + }
1.265 +
1.266 +void CWin32Stream::FlushStream()
1.267 + {
1.268 + FlushFileBuffers(iHandle); // don't care if it works or not
1.269 + }
1.270 +
1.271 +#include <winerror.h>
1.272 +
1.273 +TInt CWin32Stream::MapWin32Error(TInt aDefault)
1.274 + {
1.275 + switch (GetLastError())
1.276 + {
1.277 + case ERROR_INVALID_HANDLE:
1.278 + return KErrBadHandle;
1.279 + case ERROR_HANDLE_EOF:
1.280 + return KErrEof;
1.281 + }
1.282 + return aDefault;
1.283 + }