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