// UC_KSVR.CPP
//
// Copyright (c) 1995-1999 Symbian Ltd.  All rights reserved.
//

#include "uc_std.h"
#include "e32uid.h"

//#define __DEBUG_IMAGE__ 1
#if defined(__DEBUG_IMAGE__) && defined (__EPOC32__)
#define __IF_DEBUG(t) {RDebug::t;}
#else
#define __IF_DEBUG(t)
#endif

const TInt KMaxLibraryEntryPoints = 0x100;

EXPORT_C RNotifier::RNotifier()
	:iButtonVal(NULL,0)
//
// Constructor
//
	{
	}

EXPORT_C TInt RNotifier::Connect()
//
// Connect to the notify server
//
	{

	return(CreateSession(__NOTIFIER_NAME,TVersion(KNotifierMajorVersionNumber,KNotifierMinorVersionNumber,KNotifierBuildVersionNumber),2));
	}

EXPORT_C void RNotifier::Notify(const TDesC& aLine1,const TDesC& aLine2,const TDesC& aBut1,const TDesC& aBut2, TInt& aButtonVal, TRequestStatus& aStatus)
//
// Send notify message to server
//
	{

	iButtonVal.Set((TText*)&aButtonVal,4,4);
	TNotifyInfo &info=iInfo();
	info.iLine1=&aLine1;
	info.iLine2=&aLine2;
	info.iButton1=&aBut1;
	info.iButton2=&aBut2;
	info.iButtonVal=&iButtonVal;
	TAny *p[KMaxMessageArguments];
	p[0]=(TAny*)(&iInfo);
	SendReceive(ENotifierNotify,&p[0],aStatus);
	return;
	}

EXPORT_C TInt RNotifier::InfoPrint(const TDesC& aDes)
//
// Send infoprint message to server
//
	{

	TAny *p[KMaxMessageArguments];
	p[0]=(TAny*)(&aDes);
	return(SendReceive(ENotifierInfoPrint,&p[0]));
	}

EXPORT_C TInt RChunk::CreateLocal(TInt aSize,TInt aMaxSize,TOwnerType aType)
	{

	__ASSERT_ALWAYS(aMaxSize>=0,Panic(EChkCreateMaxSizeNegative));
	__ASSERT_ALWAYS(aSize>=0,Panic(EChkCreateSizeNotPositive));
	__ASSERT_ALWAYS(aMaxSize>=aSize,Panic(EChkCreateMaxLessThanMin));
	TPckgBuf<TChunkCreate> argPckg;
	TChunkCreate &arg=argPckg();
	arg.iSize=aSize;
	arg.iMaxSize=aMaxSize;
	arg.iDllStatic=EFalse;
	TPtr8 h((TUint8 *)&iHandle,sizeof(TInt));
	TAny *p[KMaxMessageArguments];
	p[0]=(&h);
	p[1]=(TAny*)KCurrentProcessHandle;
	p[2]=&argPckg;
	TInt msgNum=(aType==EOwnerThread)?ESvChunkCreateLocal|KThreadHandle:ESvChunkCreateLocal;
	return(SvSendReceive(msgNum,&p[0]));
	}

EXPORT_C TInt RChunk::CreateGlobal(const TDesC &aName,TInt aSize,TInt aMaxSize,TOwnerType aType)
	{

	__ASSERT_ALWAYS(aMaxSize>=0,Panic(EChkCreateMaxSizeNegative));
	__ASSERT_ALWAYS(aSize>=0,Panic(EChkCreateSizeNotPositive));
	__ASSERT_ALWAYS(aMaxSize>=aSize,Panic(EChkCreateMaxLessThanMin));
	TPckgBuf<TChunkCreate> argPckg;
	TChunkCreate &arg=argPckg();
	arg.iSize=aSize;
	arg.iMaxSize=aMaxSize;
	arg.iDllStatic=EFalse;
	TPtr8 h((TUint8 *)&iHandle,sizeof(TInt));
	TAny *p[KMaxMessageArguments];
	p[0]=(&h);
	p[1]=(TAny*)&aName;
	p[2]=&argPckg;
	TInt msgNum=(aType==EOwnerThread)?ESvChunkCreateGlobal|KThreadHandle:ESvChunkCreateGlobal;
	return(SvSendReceive(msgNum,&p[0]));
	}

EXPORT_C TInt RChunk::CreateDoubleEndedLocal(TInt aInitialBottom, TInt aInitialTop,TInt aMaxSize,TOwnerType aType)
	{
	__ASSERT_ALWAYS(aMaxSize>=0,Panic(EChkCreateMaxSizeNegative));
	__ASSERT_ALWAYS(aInitialBottom>=0,Panic(EChkCreateBottomNegative));
	__ASSERT_ALWAYS(aInitialTop>=0,Panic(EChkCreateTopNegative));
	__ASSERT_ALWAYS(aInitialTop>=aInitialBottom,Panic(EChkCreateTopLessThanBottom));
	__ASSERT_ALWAYS(aInitialTop<=aMaxSize,Panic(EChkCreateTopBiggerThanMax));
	TPckgBuf<TDoubleEndedChunkCreate> argPckg;
	TDoubleEndedChunkCreate &arg=argPckg();
	arg.iInitialBottom=aInitialBottom;
	arg.iInitialTop=aInitialTop;
	arg.iMaxSize=aMaxSize;
	arg.iDllStatic=EFalse;
	TPtr8 h((TUint8 *)&iHandle,sizeof(TInt));
	TAny *p[KMaxMessageArguments];
	p[0]=(&h);
	p[1]=(TAny*)KCurrentProcessHandle;
	p[2]=&argPckg;
	TInt msgNum=(aType==EOwnerThread)?ESvChunkCreateDoubleEndedLocal|KThreadHandle:ESvChunkCreateDoubleEndedLocal;
	return(SvSendReceive(msgNum,&p[0]));
	}

EXPORT_C TInt RChunk::CreateDoubleEndedGlobal(const TDesC &aName,TInt aInitialBottom,TInt aInitialTop,TInt aMaxSize,TOwnerType aType)
	{
	__ASSERT_ALWAYS(aMaxSize>=0,Panic(EChkCreateMaxSizeNegative));
	__ASSERT_ALWAYS(aInitialBottom>=0,Panic(EChkCreateBottomNegative));
	__ASSERT_ALWAYS(aInitialTop>=0,Panic(EChkCreateTopNegative));
	__ASSERT_ALWAYS(aInitialTop>=aInitialBottom,Panic(EChkCreateTopLessThanBottom));
	__ASSERT_ALWAYS(aInitialTop<=aMaxSize,Panic(EChkCreateTopBiggerThanMax));
	TPckgBuf<TDoubleEndedChunkCreate> argPckg;
	TDoubleEndedChunkCreate &arg=argPckg();
	arg.iInitialBottom=aInitialBottom;
	arg.iInitialTop=aInitialTop;
	arg.iMaxSize=aMaxSize;
	arg.iDllStatic=EFalse;
	TPtr8 h((TUint8 *)&iHandle,sizeof(TInt));
	TAny *p[KMaxMessageArguments];
	p[0]=(&h);
	p[1]=(TAny*)&aName;
	p[2]=&argPckg;
	TInt msgNum=(aType==EOwnerThread)?ESvChunkCreateDoubleEndedGlobal|KThreadHandle:ESvChunkCreateDoubleEndedGlobal;
	return(SvSendReceive(msgNum,&p[0]));
	}

EXPORT_C TInt RChunk::CreateDllStatic(TInt aSize,TInt aMaxSize,TOwnerType aType)
	{

	__ASSERT_ALWAYS(aMaxSize>=0,Panic(EChkCreateMaxSizeNegative));
	__ASSERT_ALWAYS(aSize>=0,Panic(EChkCreateSizeNotPositive));
	__ASSERT_ALWAYS(aMaxSize>=aSize,Panic(EChkCreateMaxLessThanMin));
	TPckgBuf<TChunkCreate> argPckg;
	TChunkCreate &arg=argPckg();
	arg.iSize=aSize;
	arg.iMaxSize=aMaxSize;
	arg.iDllStatic=ETrue;
	TPtr8 h((TUint8 *)&iHandle,sizeof(TInt));
	TAny *p[KMaxMessageArguments];
	p[0]=(&h);
	p[1]=(TAny*)KCurrentProcessHandle;
	p[2]=&argPckg;
	TInt msgNum=(aType==EOwnerThread)?ESvChunkCreateLocal|KThreadHandle:ESvChunkCreateLocal;
	return(SvSendReceive(msgNum,&p[0]));
	}

EXPORT_C TInt RChunk::OpenGlobal(const TDesC &aName,TBool isReadOnly,TOwnerType aType)
//
// Open a global Chunk.
//
	{

	TPtr8 h((TUint8 *)&iHandle,sizeof(TInt));
	TAny *p[KMaxMessageArguments];
	p[0]=(&h);
	p[1]=(TAny*)&aName;
	p[2]=(TAny*)isReadOnly;
	TInt msgNum=(aType==EOwnerThread)?ESvChunkOpen|KThreadHandle:ESvChunkOpen;
	return(SvSendReceive(msgNum,&p[0]));
	}

EXPORT_C TInt RChunk::Adjust(TInt aNewSize) const
//
// Adjust the Chunks size.
//
	{

	__ASSERT_ALWAYS(aNewSize>=0,Panic(EChkAdjustNewSizeNegative));
	TInt p[KMaxMessageArguments];
	p[0]=iHandle;
	p[1]=aNewSize;
	return(SvSendReceive(ESvChunkAdjust,&p[0]));
	}

EXPORT_C TInt RChunk::AdjustDoubleEnded(TInt aBottom, TInt aTop) const
	{
	__ASSERT_ALWAYS(aBottom>=0,Panic(EChkAdjustBottomNegative));
	__ASSERT_ALWAYS(aTop>=0,Panic(EChkAdjustTopNegative));
	__ASSERT_ALWAYS(aTop>=aBottom,Panic(EChkAdjustTopLessThanBottom));
	TInt p[KMaxMessageArguments];
	p[0]=iHandle;
	p[1]=aBottom;
	p[2]=aTop;
	return(SvSendReceive(ESvChunkAdjustDoubleEnded,&p[0]));
	}

EXPORT_C TInt RDevice::Open(const TDesC &aName,TOwnerType aType)
//
// Open a device by name
//
	{

	TPtr8 h((TUint8 *)&iHandle,sizeof(TInt));
	TAny *p[KMaxMessageArguments];
	p[0]=(&h);
	p[1]=(TAny *)&aName;
	TInt msgNum=(aType==EOwnerThread)?ESvLogicalDeviceOpen|KThreadHandle:ESvLogicalDeviceOpen;
	return(SvSendReceive(msgNum,&p[0]));
	}

LOCAL_C TInt CreateChannel(TInt &aHandle,const TDesC &aLogicalDevice,const TVersion &aVer,const TDesC *aChan,TInt aUnit,const TDesC *aPhysicalDevice,const TDesC8 *anInfo,TOwnerType aType)
//
// Call the kernel to create a channel on a device.
//
	{

	TPckgBuf<TChannelDoCreate> argPckg;
	TChannelDoCreate &arg=argPckg();
	arg.iVer=aVer;
	arg.iName=aChan;
	arg.iPhysicalDevice=aPhysicalDevice;
	arg.iInfo=anInfo;
	TPtr8 h((TUint8 *)&aHandle,sizeof(TInt));
	TAny *p[KMaxMessageArguments];
	p[0]=(&h);
	p[1]=(TAny *)&aLogicalDevice;
	p[2]=(TAny *)aUnit;
	p[3]=(&argPckg);
	TInt msgNum=(aType==EOwnerThread)?ESvChannelCreate|KThreadHandle:ESvChannelCreate;
	return(SvSendReceive(msgNum,&p[0]));
	}

EXPORT_C TInt RLogicalChannel::DoCreate(const TDesC &aLogicalDevice,const TVersion &aVer,const TDesC *aChan,TInt aUnit,const TDesC *aPhysicalDevice,const TDesC8 *anInfo,TOwnerType aType)
//
// Call the kernel to create a channel on a device.
//
	{

	return(CreateChannel(iHandle,aLogicalDevice,aVer,aChan,aUnit,aPhysicalDevice,anInfo,aType));
	}

EXPORT_C TInt RLogicalChannel::DoSvControl(TInt aFunction)
//
// Call the devices control function.
//
	{

	TAny *p[KMaxMessageArguments];
	p[0]=(TAny *)iHandle;
	p[1]=(TAny *)aFunction;
	p[2]=NULL;
	p[3]=NULL;
	return(SvSendReceive(ESvChannelControl,&p[0]));
	}

EXPORT_C TInt RLogicalChannel::DoSvControl(TInt aFunction,TAny *a1)
//
// Call the devices control function.
//
	{

	TAny *p[KMaxMessageArguments];
	p[0]=(TAny *)iHandle;
	p[1]=(TAny *)aFunction;
	p[2]=a1;
	p[3]=NULL;
	return(SvSendReceive(ESvChannelControl,&p[0]));
	}

EXPORT_C TInt RLogicalChannel::DoSvControl(TInt aFunction,TAny *a1,TAny *a2)
//
// Call the devices control function.
//
	{

	TAny *p[KMaxMessageArguments];
	p[0]=(TAny *)iHandle;
	p[1]=(TAny *)aFunction;
	p[2]=a1;
	p[3]=a2;
	return(SvSendReceive(ESvChannelControl,&p[0]));
	}

TInt MBusDev::DoAsyncStart()
//
// Perform an asynchronous start of the device
//
	{

	if (iStartInfo&KBusDevPhase1Start)
		{
		TRequestStatus rs=KRequestPending;

    	TAny *p[KMaxMessageArguments];
    	p[0]=(TAny *)KBusDevPhase1Start;
    	p[1]=(TAny *)&rs;
    	p[2]=(TAny *)(iStartInfo&KBusDevSocketInfoMask);
    	SvSendReceiveCheck(ESvBusDevAsyncStart,&p[0]);

		User::WaitForRequest(rs);
		return(rs.Int());
		}
	else
		return(KErrNone);
	}

TInt MBusDev::DoAsyncLateOpen(TInt aHandle)
//
// For a device which needs a further asynchronous operation after
// opening a channel
//
	{

	if (iStartInfo&KBusDevPhase2Start)
		{
		TRequestStatus rs=KRequestPending;

    	TAny *p[KMaxMessageArguments];
    	p[0]=(TAny *)KBusDevPhase2Start;
    	p[1]=(TAny *)&rs;
    	p[2]=(TAny *)aHandle;
    	p[3]=(TAny *)(iStartInfo&KBusDevSocketInfoMask);
    	SvSendReceiveCheck(ESvBusDevAsyncStart,&p[0]);

		User::WaitForRequest(rs);
		return(rs.Int());
		}
	else
		return(KErrNone);
	}

EXPORT_C TInt RBusLogicalChannel::DoCreate(const TDesC &aLogicalDevice,const TVersion &aVer,const TDesC *aChan,TInt aUnit,const TDesC *aPhysicalDevice,const TDesC8 *anInfo,TOwnerType aType)
//
// Call the kernel to create a channel on a device.
//
	{

	// Check if the device requires an asynchronous open
	if (CheckOpenMode(aLogicalDevice,aUnit)==KErrNone)
		return(CreateChannel(iHandle,aLogicalDevice,aVer,aChan,aUnit,aPhysicalDevice,anInfo,aType));
	else
		{
        // Possible initial asynchronous operation required before attempting to open device
        TInt r;
        if ((r=DoAsyncStart())!=KErrNone)
			return(r);

        // Now we can create a channel on the device 
		if ((r=CreateChannel(iHandle,aLogicalDevice,aVer,aChan,aUnit,aPhysicalDevice,anInfo,aType))!=KErrNone)
			return(r);

        // Possible further asynchronous operation required before device is fully open
		return(DoAsyncLateOpen(iHandle));
		}
	}

EXPORT_C TInt RBusLogicalChannel::DoSvControl(TInt aFunction)
//
// Call the devices control function.
//
	{

	TInt r;
	if ((r=CheckBusStatus())!=KErrNone)
        return(r);
    else
        {
	    TAny *p[KMaxMessageArguments];
	    p[0]=(TAny *)iHandle;
	    p[1]=(TAny *)aFunction;
	    p[2]=NULL;
	    p[3]=NULL;
	    return(SvSendReceive(ESvChannelControl,&p[0]));
        }
	}

EXPORT_C TInt RBusLogicalChannel::DoSvControl(TInt aFunction,TAny *a1)
//
// Call the devices control function.
//
	{

	TInt r;
	if ((r=CheckBusStatus())!=KErrNone)
        return(r);
    else
        {
	    TAny *p[KMaxMessageArguments];
	    p[0]=(TAny *)iHandle;
	    p[1]=(TAny *)aFunction;
	    p[2]=a1;
	    p[3]=NULL;
	    return(SvSendReceive(ESvChannelControl,&p[0]));
        }
	}

EXPORT_C TInt RBusLogicalChannel::DoSvControl(TInt aFunction,TAny *a1,TAny *a2)
//
// Call the devices control function.
//
	{

	TInt r;
	if ((r=CheckBusStatus())!=KErrNone)
        return(r);
    else
        {
	    TAny *p[KMaxMessageArguments];
	    p[0]=(TAny *)iHandle;
	    p[1]=(TAny *)aFunction;
	    p[2]=a1;
	    p[3]=a2;
	    return(SvSendReceive(ESvChannelControl,&p[0]));
        }
	}

EXPORT_C TInt RHandleBase::Duplicate(const RThread &aSrc,TOwnerType aType)
//
// Duplicate the current handle from aSrc to this process.
//
	{

	TPtr8 h((TUint8 *)&iHandle,sizeof(TInt));
	TAny *p[KMaxMessageArguments];
	p[0]=(&h);
	p[1]=(TAny *)aSrc.iHandle;
	p[2]=(TAny *)iHandle;
	TInt msgNum=(aType==EOwnerThread)?ESvHandleDuplicate|KThreadHandle:ESvHandleDuplicate;
	return(SvSendReceive(msgNum,&p[0]));
	}

EXPORT_C TInt RHandleBase::Open(const TFindHandleBase &aFindHandle,TOwnerType aType)
//
// Open a handle given its find handle.
//
	{

	TPtr8 h((TUint8 *)&iHandle,sizeof(TInt));
	TAny *p[KMaxMessageArguments];
	p[0]=(&h);
	p[1]=(TAny *)aFindHandle.Handle();
	TInt msgNum=(aType==EOwnerThread)?ESvFindHandleOpen|KThreadHandle:ESvFindHandleOpen;
	return(SvSendReceive(msgNum,&p[0]));
	}

EXPORT_C void RHandleBase::Close()
//
// Close a handle.
//
	{

	__IF_DEBUG(Print(_L("RHandleBase::Close")));
	if (iHandle!=KNullHandle)
		{
//
// We take a copy of the handle and set it to zero before the close in case this
// object is actually a Chunk created in its own heap in which case the close
// will destroy the object as well.
//
		TInt p[KMaxMessageArguments];
		p[0]=iHandle;
		iHandle=KNullHandle;
		if ((p[0]&CObjectIx::ENoClose)==0)
			SvSendReceiveCheck(ESvHandleClose,&p[0]);
		}
	}

EXPORT_C TInt RServer::CreateGlobal(const TDesC &aName)
//
// Create a new server.
//
	{

	TPtr8 h((TUint8 *)&iHandle,sizeof(TInt));
	TAny *p[KMaxMessageArguments];
	p[0]=(&h);
	p[1]=(TAny *)&aName;
	return(SvSendReceive(ESvServerCreate,&p[0]));
	}

EXPORT_C TInt RSessionBase::CreateSession(const TDesC &aServer,const TVersion &aVersion,TInt aMessageSlots,TTimeIntervalMicroSeconds32 aDelayTime,TInt aRetryCount)
//
// Create a session with the server.
//
	{


	__ASSERT_ALWAYS(aDelayTime.Int()>=0,Panic(ESesDelayTimeNegative));
	__ASSERT_ALWAYS(aRetryCount>=0,Panic(ESesRetryCountNegative));
	TPckgBuf<TCreateSession> argPckg;
	TCreateSession &arg=argPckg();
	arg.iVer=aVersion;
	arg.iMessageSlots=aMessageSlots;
	TPtr8 h((TUint8 *)&iHandle,sizeof(TInt));
	TAny *session;
	TPtr8 s((TUint8 *)&session,sizeof(TAny *));
	TAny *p[KMaxMessageArguments];
	p[0]=(&h);
	p[1]=(TAny *)&aServer;
	p[2]=(&argPckg);
	p[3]=(&s);
	TInt r=SvSendReceive(ESvSessionCreate,&p[0]);
	if (r!=KErrNone)
		return(r);
	iDelayTime=aDelayTime;
	iRetryCount=aRetryCount;
	struct
		{
		TAny *session; // Ptr0()
		TDesC8 *version; // Ptr1()
		TAny *p[2];
		} a;
	a.session=session;
	TPckgC<TVersion> v(aVersion);
	a.version=(&v);
	r=SendConnect((TInt *)&a);
	if (r!=KErrNone)
		Close();
	return r;
	}

EXPORT_C TInt RMutex::CreateLocal(TOwnerType aType)
//
// Create a local mutex.
//
	{

	TPtr8 h((TUint8 *)&iHandle,sizeof(TInt));
	TAny *p[KMaxMessageArguments];
	p[0]=(&h);
	p[1]=(TAny *)KCurrentProcessHandle;
	p[2]=NULL;
	TInt msgNum=(aType==EOwnerThread)?ESvMutexCreate|KThreadHandle:ESvMutexCreate;
	return(SvSendReceive(msgNum,&p[0]));
	}

EXPORT_C TInt RMutex::CreateGlobal(const TDesC &aName,TOwnerType aType)
//
// Create a global mutex.
//
	{

	TPtr8 h((TUint8 *)&iHandle,sizeof(TInt));
	TAny *p[KMaxMessageArguments];
	p[0]=(&h);
	p[1]=NULL;
	p[2]=(TAny *)&aName;
	TInt msgNum=(aType==EOwnerThread)?ESvMutexCreate|KThreadHandle:ESvMutexCreate;
	return(SvSendReceive(msgNum,&p[0]));
	}

EXPORT_C TInt RMutex::OpenGlobal(const TDesC &aName,TOwnerType aType)
//
// Open a global mutex.
//
	{

	TPtr8 h((TUint8 *)&iHandle,sizeof(TInt));
	TAny *p[KMaxMessageArguments];
	p[0]=(&h);
	p[1]=(TAny *)&aName;
	TInt msgNum=(aType==EOwnerThread)?ESvMutexOpen|KThreadHandle:ESvMutexOpen;
	return(SvSendReceive(msgNum,&p[0]));
	}

EXPORT_C TInt RSemaphore::CreateLocal(TInt aCount,TOwnerType aType)
//
// Create a local semaphore.
//
	{

	__ASSERT_ALWAYS(aCount>=0,Panic(ESemCreateCountNegative));
	TPtr8 h((TUint8 *)&iHandle,sizeof(TInt));
	TAny *p[KMaxMessageArguments];
	p[0]=(&h);
	p[1]=(TAny *)KCurrentProcessHandle;
	p[2]=NULL;
	p[3]=(TAny *)aCount;
	TInt msgNum=(aType==EOwnerThread)?ESvSemaphoreCreate|KThreadHandle:ESvSemaphoreCreate;
	return(SvSendReceive(msgNum,&p[0]));
	}

EXPORT_C TInt RSemaphore::CreateGlobal(const TDesC &aName,TInt aCount,TOwnerType aType)
//
// Create a global semaphore.
//
	{

	__ASSERT_ALWAYS(aCount>=0,Panic(ESemCreateCountNegative));
	TPtr8 h((TUint8 *)&iHandle,sizeof(TInt));
	TAny *p[KMaxMessageArguments];
	p[0]=(&h);
	p[1]=NULL;
	p[2]=(TAny *)&aName;
	p[3]=(TAny *)aCount;
	TInt msgNum=(aType==EOwnerThread)?ESvSemaphoreCreate|KThreadHandle:ESvSemaphoreCreate;
	return(SvSendReceive(msgNum,&p[0]));
	}

EXPORT_C TInt RSemaphore::OpenGlobal(const TDesC &aName,TOwnerType aType)
//
// Open a global semaphore.
//
	{

	TPtr8 h((TUint8 *)&iHandle,sizeof(TInt));
	TAny *p[KMaxMessageArguments];
	p[0]=(&h);
	p[1]=(TAny *)&aName;
	TInt msgNum=(aType==EOwnerThread)?ESvSemaphoreOpen|KThreadHandle:ESvSemaphoreOpen;
	return(SvSendReceive(msgNum,&p[0]));
	}

EXPORT_C TInt RCriticalSection::CreateLocal(TOwnerType aType)
//
// Create a local semaphore.
//
	{

	iBlocked=1;
	return(RSemaphore::CreateLocal(0,aType));
	}

EXPORT_C TInt RTimer::CreateLocal()
//
// Create a local timer.
//
	{

	TPtr8 h((TUint8 *)&iHandle,sizeof(TInt));
	TAny *p[KMaxMessageArguments];
	p[0]=(&h);
	return(SvSendReceive(ESvTimerCreate,&p[0]));
	}

EXPORT_C TInt RProcess::Open(const TDesC &aName,TOwnerType aType)
//
// Open a named process.
//
	{

	TPtr8 h((TUint8 *)&iHandle,sizeof(TInt));
	TAny *p[KMaxMessageArguments];
	p[0]=(&h);
	p[1]=(TAny *)&aName;
	TInt msgNum=(aType==EOwnerThread)?ESvProcessOpen|KThreadHandle:ESvProcessOpen;
	return(SvSendReceive(msgNum,&p[0]));
	}

EXPORT_C TInt RProcess::Open(TProcessId aId,TOwnerType aType)
//
// Open a process by Id.
//
	{

	TPtr8 h((TUint8 *)&iHandle,sizeof(TInt));
	TAny *p[KMaxMessageArguments];
	p[0]=(&h);
	p[1]=(TAny*)*(TUint*)&aId;
	TInt msgNum=(aType==EOwnerThread)?ESvProcessOpenById|KThreadHandle:ESvProcessOpenById;
	return(SvSendReceive(msgNum,&p[0]));
	}

EXPORT_C TInt RProcess::Rename(const TDesC &aName)
//
// Rename the process.
//
	{

	TAny *p[KMaxMessageArguments];
	p[0]=(TAny *)iHandle;
	p[1]=(TAny *)&aName;
	return(SvSendReceive(ESvProcessRename,&p[0]));
	}

EXPORT_C void RProcess::Kill(TInt aReason)
//
// Kill a process and all its threads.
//
	{

	TInt p[KMaxMessageArguments];
	p[0]=iHandle;
	p[1]=aReason;
	SvSendReceiveCheck(ESvProcessKill,&p[0]);
	}

EXPORT_C void RProcess::Terminate(TInt aReason)
//
// Terminate a process and all its threads.
//
	{

	TInt p[KMaxMessageArguments];
	p[0]=iHandle;
	p[1]=aReason;
	SvSendReceiveCheck(ESvProcessTerminate,&p[0]);
	}

EXPORT_C void RProcess::Panic(const TDesC &aCategory,TInt aReason)
//
// Panic a process and all its threads.
//
	{

	TAny *p[KMaxMessageArguments];
	p[0]=(TAny *)iHandle;
	p[1]=(TAny *)aReason;
	p[2]=(TAny *)&aCategory;
	SvSendReceiveCheck(ESvProcessPanic,&p[0]);
	}

EXPORT_C TInt RProcess::Owner(RProcess &anOwner) const
//
// Get the process which started this process.
//
	{

	TAny* p[KMaxMessageArguments];
	p[0]=(TAny*)iHandle;
	p[1]=(TAny*)&anOwner;
	return(SvSendReceive(ESvProcessOwner,&p[0]));
	}

EXPORT_C void RProcess::Logon(TRequestStatus &aStatus) const
//
// Logon to a process async.
//
	{

	aStatus=KRequestPending;
	TAny *p[KMaxMessageArguments];
	p[0]=(TAny *)iHandle;
	p[1]=(TAny *)&aStatus;
	SvSendReceiveCheck(ESvProcessLogon,&p[0]);
	}

EXPORT_C TInt RProcess::LogonCancel(TRequestStatus &aStatus) const
//
// Logoff from an aync logon.
//
	{

	TAny *p[KMaxMessageArguments];
	p[0]=(TAny *)iHandle;
	p[1]=(TAny *)&aStatus;
	return(SvSendReceive(ESvProcessLogonCancel,&p[0]));
	}

EXPORT_C TInt RThread::Create(const TDesC &aName,TThreadFunction aFunction,TInt aStackSize,TAny *aPtr,RLibrary* aLibrary,RProcess* aProcess,RHeap* aHeap, TInt aHeapMinSize,TInt aHeapMaxSize,TOwnerType aType)
//
// Start a new thread executing in the current process.
//
	{

	RHeap* pH=aHeap;
    if(pH==NULL)
        {
	    __ASSERT_ALWAYS(aHeapMinSize>=KMinHeapSize,::Panic(EThrdHeapMinTooSmall));
	    __ASSERT_ALWAYS(aHeapMaxSize>=aHeapMinSize,::Panic(EThrdHeapMaxLessThanMin));
        pH=&User::Heap();
        }
	__ASSERT_ALWAYS(pH->Type()==RHeap::EChunkNormal || pH->Type()==RHeap::EChunkStack,::Panic(EThrdHeapNotChunkType));
	__ASSERT_ALWAYS(aStackSize>=0,::Panic(EThrdStackSizeNegative));
	TPckgBuf<TThreadCreate> argPckg;
	TThreadCreate &arg=argPckg();
	arg.iFunction=aFunction;
	arg.iStackSize=aStackSize;

	if (aHeap!=NULL)
		{
		arg.iHeap=pH;
		arg.iHeapMinSize=0;
		arg.iHeapMaxSize=0;
		}
	else
		{
		arg.iHeap=NULL;
		arg.iHeapMinSize=aHeapMinSize;
		arg.iHeapMaxSize=aHeapMaxSize;
		}
	arg.iPtr=aPtr;
	if (aLibrary)
		arg.iLibraryHandle=aLibrary->Handle();
	else
		arg.iLibraryHandle=NULL;
	TPtr8 h((TUint8 *)&iHandle,sizeof(TInt));
	TAny *p[KMaxMessageArguments];
	p[0]=(&h);
	if (aProcess)
		p[1]=(TAny *)aProcess->Handle();
	else
		p[1]=(TAny *)KCurrentProcessHandle;
	p[2]=(TAny *)&aName;
	p[3]=(&argPckg);
	TInt msgNum=(aType==EOwnerThread)?ESvThreadCreate|KThreadHandle:ESvThreadCreate;
	return(SvSendReceive(msgNum,&p[0]));
	}

EXPORT_C TInt RThread::Create(const TDesC &aName,TThreadFunction aFunction,TInt aStackSize,TInt aHeapMinSize,TInt aHeapMaxSize,TAny *aPtr,TOwnerType aType)
//
// Start a new thread executing in the current process.
//
	{

	__ASSERT_ALWAYS(aStackSize>=0,::Panic(EThrdStackSizeNegative));
	__ASSERT_ALWAYS(aHeapMinSize>=KMinHeapSize,::Panic(EThrdHeapMinTooSmall));
	__ASSERT_ALWAYS(aHeapMaxSize>=aHeapMinSize,::Panic(EThrdHeapMaxLessThanMin));
	TPckgBuf<TThreadCreate> argPckg;
	TThreadCreate &arg=argPckg();
	arg.iFunction=aFunction;
	arg.iStackSize=aStackSize;
	arg.iHeap=NULL;
	arg.iHeapMinSize=aHeapMinSize;
	arg.iHeapMaxSize=aHeapMaxSize;
	arg.iPtr=aPtr;
	arg.iLibraryHandle=NULL;
	TPtr8 h((TUint8 *)&iHandle,sizeof(TInt));
	TAny *p[KMaxMessageArguments];
	p[0]=(&h);
	p[1]=(TAny *)KCurrentProcessHandle;
	p[2]=(TAny *)&aName;
	p[3]=(&argPckg);
	TInt msgNum=(aType==EOwnerThread)?ESvThreadCreate|KThreadHandle:ESvThreadCreate;
	return(SvSendReceive(msgNum,&p[0]));
	}

EXPORT_C TInt RThread::Create(const TDesC &aName,TThreadFunction aFunction,TInt aStackSize,RHeap *aHeap,TAny *aPtr,TOwnerType aType)
//
// Start a new thread executing in the current process.
//
	{

	RHeap* pH=(aHeap==NULL ? &User::Heap() : aHeap);
	__ASSERT_ALWAYS(pH->Type()==RHeap::EChunkNormal || pH->Type()==RHeap::EChunkStack,::Panic(EThrdHeapNotChunkType));
	__ASSERT_ALWAYS(aStackSize>=0,::Panic(EThrdStackSizeNegative));
	TPckgBuf<TThreadCreate> argPckg;
	TThreadCreate &arg=argPckg();
	arg.iFunction=aFunction;
	arg.iStackSize=aStackSize;
	arg.iHeap=pH;
	arg.iHeapMinSize=0;
	arg.iHeapMaxSize=0;
	arg.iPtr=aPtr;
	arg.iLibraryHandle=NULL;
	TPtr8 h((TUint8 *)&iHandle,sizeof(TInt));
	TAny *p[KMaxMessageArguments];
	p[0]=(&h);
	p[1]=(TAny *)KCurrentProcessHandle;
	p[2]=(TAny *)&aName;
	p[3]=(&argPckg);
	TInt msgNum=(aType==EOwnerThread)?ESvThreadCreate|KThreadHandle:ESvThreadCreate;
	return(SvSendReceive(msgNum,&p[0]));
	}

EXPORT_C TInt RThread::Create(const RProcess &aProcess,const TDesC &aName,TThreadFunction aFunction,TInt aStackSize,TInt aHeapMinSize,TInt aHeapMaxSize,TAny *aPtr,TOwnerType aType)
//
// Start a new thread executing in the specified process.
//
	{

	__ASSERT_ALWAYS(aStackSize>=0,::Panic(EThrdStackSizeNegative));
	__ASSERT_ALWAYS(aHeapMinSize>=KMinHeapSize,::Panic(EThrdHeapMinTooSmall));
	__ASSERT_ALWAYS(aHeapMaxSize>=aHeapMinSize,::Panic(EThrdHeapMaxLessThanMin));
	TPckgBuf<TThreadCreate> argPckg;
	TThreadCreate &arg=argPckg();
	arg.iFunction=aFunction;
	arg.iStackSize=aStackSize;
	arg.iHeap=NULL;
	arg.iHeapMinSize=aHeapMinSize;
	arg.iHeapMaxSize=aHeapMaxSize;
	arg.iPtr=aPtr;
	arg.iLibraryHandle=NULL;
	TPtr8 h((TUint8 *)&iHandle,sizeof(TInt));
	TAny *p[KMaxMessageArguments];
	p[0]=(&h);
	p[1]=(TAny *)aProcess.Handle();
	p[2]=(TAny *)&aName;
	p[3]=(&argPckg);
	TInt msgNum=(aType==EOwnerThread)?ESvThreadCreate|KThreadHandle:ESvThreadCreate;
	return(SvSendReceive(msgNum,&p[0]));
	}

EXPORT_C TInt RThread::SetInitialParameter(TAny *aPtr)
//
// Set the thread's parameter
//
	{
	
	TAny *p[KMaxMessageArguments];
	p[0]=(TAny *)iHandle;
	p[1]=aPtr;
	return(SvSendReceive(ESvThreadSetParameter,&p[0]));
	}

EXPORT_C TInt RThread::Open(const TDesC &aFullName,TOwnerType aType)
//
// Open an already running thread in any process.
//
	{

	TPtr8 h((TUint8 *)&iHandle,sizeof(TInt));
	TAny *p[KMaxMessageArguments];
	p[0]=(&h);
	p[1]=(TAny *)&aFullName;
	TInt msgNum=(aType==EOwnerThread)?ESvThreadOpen|KThreadHandle:ESvThreadOpen;
	return(SvSendReceive(msgNum,&p[0]));
	}

EXPORT_C TInt RThread::Open(TThreadId aId,TOwnerType aType)
//
// Open an already running thread in any process.
//
	{

	TPtr8 h((TUint8 *)&iHandle,sizeof(TInt));
	TAny *p[KMaxMessageArguments];
	p[0]=(&h);
	p[1]=(TAny*)*(TUint*)&aId;
	TInt msgNum=(aType==EOwnerThread)?ESvThreadOpenById|KThreadHandle:ESvThreadOpenById;
	return(SvSendReceive(msgNum,&p[0]));
	}

EXPORT_C TInt RThread::Process(RProcess &aProcess) const
//
// Return the owning process.
//
	{

	TInt h;
	TPtr8 hh((TUint8 *)&h,sizeof(TInt));
	TAny *p[KMaxMessageArguments];
	p[0]=(&hh);
	p[1]=(TAny *)iHandle;
	TInt r=SvSendReceive(ESvThreadProcess,&p[0]);
	if (r==KErrNone)
		aProcess.SetHandle(h);
	return(r);
	}

EXPORT_C TInt RThread::Rename(const TDesC &aName) const
//
// Rename the thread.
//
	{

	TAny *p[KMaxMessageArguments];
	p[0]=(TAny *)iHandle;
	p[1]=(TAny *)&aName;
	return(SvSendReceive(ESvThreadRename,&p[0]));
	}

EXPORT_C void RThread::Kill(TInt aReason)
//
// Kill the thread.
//
	{

	TInt p[KMaxMessageArguments];
	p[0]=iHandle;
	p[1]=aReason;
	SvSendReceiveCheck(ESvThreadKill,&p[0]);
	}

EXPORT_C void RThread::Terminate(TInt aReason)
//
// Terminate the thread.
//
	{

	TInt p[KMaxMessageArguments];
	p[0]=iHandle;
	p[1]=aReason;
	SvSendReceiveCheck(ESvThreadTerminate,&p[0]);
	}

EXPORT_C void RThread::Panic(const TDesC &aCategory,TInt aReason)
//
// Panic the thread.
//
	{
	
#if defined(__WINS__) && defined(_DEBUG)
	if (User::JustInTime())
		{
		TUint32 victimWin32ID=WinsEpocThreadWinID(Exec::ThreadId(iHandle));
		TFullName victimName(FullName());
		TBuf<0x100> category(aCategory);
		TFullName killerName(RThread().FullName());
		ThreadPanicBreakpoint2(victimWin32ID,victimName.PtrZ(),category.PtrZ(),aReason,killerName.PtrZ());
		}
#endif

	TAny *p[KMaxMessageArguments];
	p[0]=(TAny *)iHandle;
	p[1]=(TAny *)aReason;
	p[2]=(TAny *)&aCategory;
	SvSendReceiveCheck(ESvThreadPanic,&p[0]);
	}

EXPORT_C void RThread::Logon(TRequestStatus &aStatus) const
//
// Logon async to the thread.
//
	{

	aStatus=KRequestPending;
	TAny *p[KMaxMessageArguments];
	p[0]=(TAny *)iHandle;
	p[1]=(TAny *)&aStatus;
	SvSendReceiveCheck(ESvThreadLogon,&p[0]);
	}

EXPORT_C TInt RThread::LogonCancel(TRequestStatus &aStatus) const
//
// Logoff from the thread.
//
	{

	TAny *p[KMaxMessageArguments];
	p[0]=(TAny *)iHandle;
	p[1]=(TAny *)&aStatus;
	return(SvSendReceive(ESvThreadLogonCancel,&p[0]));
	}

EXPORT_C RHeap* RThread::Heap()
//
//
//
	{

	RHeap* heap;
	TAny *p[KMaxMessageArguments];
	p[0]=(TAny *)iHandle;
	p[1]=(TAny *)&heap;
	SvSendReceiveCheck(ESvThreadGetHeap,&p[0]);
	return(heap);
	}

EXPORT_C TInt TBusLocalDrive::Connect(TInt aDriveNumber,TBool &aChangedFlag)
//
// Connect to the drive.
//
	{

	__ASSERT_ALWAYS(aDriveNumber>=0 && aDriveNumber<KMaxLocalDrives,Panic(EDriveOutOfRange));

	// First, get data on whether an asynchronous start is required on the drive. If a
	// start isn't required, still mark mount status as not ready so it opens on next access.
	TInt r;
	if ((r=CheckOpenMode(_L("Media"),aDriveNumber))==KErrNone)
		r=KErrNotReady;
	SetStatus(r);

	TPtr8 pD((TUint8 *)&iDrive,sizeof(TAny *));
	TAny *p[KMaxMessageArguments];
	p[0]=(TAny*)aDriveNumber;
	p[1]=(TAny*)&Status();
	p[2]=(TAny*)&aChangedFlag;
	p[3]=(&pD);
	return(SvSendReceive(ESvDriveConnect,&p[0]));
	}

EXPORT_C void TBusLocalDrive::Disconnect()
//
// Disconnect from the drive.
//
	{

	if (iDrive!=NULL)
		{
		TAny *p[KMaxMessageArguments];
		p[0]=iDrive;
		p[1]=(TAny *)&Status();
		SvSendReceiveCheck(ESvDriveDisconnect,&p[0]);
		}
	iDrive=NULL;
	}

TInt TBusLocalDrive::Open(TAny* aDrive,TInt &aMountStatus,TInt aStartResult)
//
// Open the connected drive
//
    {
	TAny *p[KMaxMessageArguments];
	p[0]=aDrive;
	p[1]=(TAny *)&aMountStatus;
	p[2]=(TAny *)aStartResult;
	return(SvSendReceive(ESvDriveOpen,&p[0]));
    }

EXPORT_C TInt TBusLocalDrive::Enlarge(TInt aLength)
//
// Inrease the size of the connected drive by the specified length (in bytes).
//
	{
	__ASSERT_DEBUG(iDrive!=NULL,Panic(EDriveNotConnected));
	if (aLength<0)
		return(KErrArgument);
	TInt r=CheckMount();
	if (r!=KErrNone)
		return(r);
	TInt p[KMaxMessageArguments];
	p[0]=(TInt)iDrive;
	p[1]=aLength;
	return(SvSendReceive(ESvDriveEnlarge,&p[0]));
	}

EXPORT_C TInt TBusLocalDrive::ReduceSize(TInt aPos,TInt aLength)
//
// Reduce the size of the connected drive by removing the specified length
// (in bytes) starting at the specified position.
//
	{
	__ASSERT_DEBUG(iDrive!=NULL,Panic(EDriveNotConnected));
	if (aLength<0)
		return(KErrArgument);
	TInt r=CheckMount();
	if (r!=KErrNone)
		return(r);
	TInt p[KMaxMessageArguments];
	p[0]=(TInt)iDrive;
	p[1]=aPos;
	p[2]=aLength;
	return(SvSendReceive(ESvDriveReduce,&p[0]));
	}

EXPORT_C TInt TLocalDrive::Connect(TInt aDriveNumber,TBool &aChangedFlag)
//
// Connect to the drive.
//
	{

	__ASSERT_ALWAYS(aDriveNumber>=0 && aDriveNumber<KMaxLocalDrives,Panic(EDriveOutOfRange));
	TPtr8 pD((TUint8 *)&iDrive,sizeof(TAny *));
	TAny *p[KMaxMessageArguments];
	p[0]=(TAny*)aDriveNumber;
	p[1]=(TAny*)&iStatus;
	p[2]=(TAny*)&aChangedFlag;
	p[3]=(&pD);
	return(SvSendReceive(ESvDriveConnect,&p[0]));
	}

EXPORT_C void TLocalDrive::Disconnect()
//
// Disconnect from the drive.
//
	{

	if (iDrive!=NULL)
		{
		TAny *p[KMaxMessageArguments];
		p[0]=iDrive;
		p[1]=(TAny *)&iStatus;
		SvSendReceiveCheck(ESvDriveDisconnect,&p[0]);
		}
	iDrive=NULL;
	}

EXPORT_C TInt TLocalDrive::Enlarge(TInt /*aLength*/)
//
// Inrease the size of the connected drive by the specified length (in bytes).
//
	{

	return(KErrNotSupported);
	}

EXPORT_C TInt TLocalDrive::ReduceSize(TInt /*aPos*/,TInt /*aLength*/)
//
// Reduce the size of the connected drive by removing the specified length
// (in bytes) starting at the specified position.
//
	{

	return(KErrNotSupported);
	}

EXPORT_C void User::__DbgMarkStart(RHeap::TDbgHeapType aHeapType)
//
// Call MarkStart for the default heap
//
	{

	if (aHeapType==RHeap::EUser)
		Exec::Heap()->__DbgMarkStart();
	else
		{
		TInt p[KMaxMessageArguments];
		p[0]=aHeapType;
		SvSendReceiveCheck(ESvHeapMarkStart,&p[0]);
		}
	}

EXPORT_C void User::__DbgMarkCheck(RHeap::TDbgHeapType aHeapType,TBool aCountAll,TInt aCount,const TDesC8 &aFileName,TInt aLineNum)
//
// Call CheckNum for the default heap
//
	{

	if (aHeapType==RHeap::EUser)
		Exec::Heap()->__DbgMarkCheck(aCountAll,aCount,aFileName,aLineNum);
	else
		{
		TInt p[KMaxMessageArguments];
		p[0]=(aHeapType|(aCountAll<<31));
		p[1]=aCount;
		p[2]=(TInt)&aFileName;
		p[3]=aLineNum;
		SvSendReceiveCheck(ESvHeapMarkCheck,&p[0]);
		}
	}

EXPORT_C TUint32 User::__DbgMarkEnd(RHeap::TDbgHeapType aHeapType,TInt aCount)
//
// Call CheckHeap for the default heap
//
	{

	if (aHeapType==RHeap::EUser)
		{
		TUint32 badCell=Exec::Heap()->__DbgMarkEnd(aCount);
		if (badCell!=0)
			{
			TBuf<0x10> info=_L("ALLOC: ");
			info.AppendFormat(_L("%x\n"), badCell);
			User::Panic(info,0);
			}
		return(badCell);
		}
	else
		{
		TInt p[KMaxMessageArguments];
		p[0]=aHeapType;
		p[1]=aCount;
		SvSendReceiveCheck(ESvHeapMarkEnd,&p[0]);
		}
	return(0);
	}

EXPORT_C void User::__DbgSetAllocFail(RHeap::TDbgHeapType aHeapType,RHeap::TAllocFail aType,TInt aValue)
//
// Set the failure rate for allocating from the default user heap
//
	{

	if (aHeapType==RHeap::EUser)
		Exec::Heap()->__DbgSetAllocFail(aType,aValue);
	else
		{
		TInt p[KMaxMessageArguments];
		p[0]=aHeapType;
		p[1]=aType;
		p[2]=aValue;
		SvSendReceiveCheck(ESvHeapSetAllocFail,&p[0]);
		}
	}

EXPORT_C TInt RProcess::Create(const TDesC &aFileName,const TDesC &aCommand,TOwnerType aType)
//
// Execute a process
//
	{

	RLoader loader;
	TInt r=loader.Connect();
#if defined(__WINS__) && defined(_DEBUG)
	if (r==KErrNotFound)
		Panic(_L("No Loader"),0);
#endif
	if (r==KErrNone)
		r=loader.LoadProcess(iHandle,aFileName,aCommand,aType);
	loader.Close();
	return(r);
	}

EXPORT_C TInt RProcess::Create(const TDesC &aFileName,const TDesC &aCommand,const TUidType &aUidType, TOwnerType aType)
//
// Execute a process by name and uid
//
	{

	RLoader loader;
	TInt r=loader.Connect();
#if defined(__WINS__) && defined(_DEBUG)
	if (r==KErrNotFound)
		Panic(_L("No Loader"),0);
#endif
	if (r==KErrNone)
		r=loader.LoadProcess(iHandle,aFileName,aCommand,aUidType,aType);
	loader.Close();
	return(r);
	}

EXPORT_C TInt User::LoadLogicalDevice(const TDesC &aFileName)
//
// Load a logical device driver DLL with extension .LDD
//
	{

	RLoader loader;
	TInt r=loader.Connect();
#if defined(__WINS__) && defined(_DEBUG)
	if (r==KErrNotFound)
		User::Panic(_L("Loader not present"),0);
#endif
	if (r!=KErrNone)
		return(r);

	TInt handle;
	r=loader.LoadLibrary(handle,aFileName,_L(".LDD"),_L(""), TUidType(KNullUid, KLogicalDeviceDriverUid, KNullUid));
	loader.Close();
	if (r!=KErrNone)
		return(r);

	TInt p[KMaxMessageArguments];
	p[0]=handle;
	r=SvSendReceive(ESvLogicalDeviceLoad,&p[0]);
	RHandleBase lib;
	lib.SetHandle(handle);
	lib.Close();
	return(r);
	}

EXPORT_C TInt User::FreeLogicalDevice(const TDesC &aDeviceName)
//
// Free a logical device driver DLL
//
	{

	TAny *p[KMaxMessageArguments];
	p[0]=(TAny *)&aDeviceName;
	return(SvSendReceive(ESvLogicalDeviceFree,&p[0]));
	}

EXPORT_C TInt User::LoadPhysicalDevice(const TDesC &aFileName)
//
// Load a physical device driver DLL with extension .PDD
//
	{

	__IF_DEBUG(Print(_L("User::LoadPhysicalDevice")));
	RLoader loader;
	TInt r=loader.Connect();
#if defined(__WINS__) && defined(_DEBUG)
	if (r==KErrNotFound)
		User::Panic(_L("Loader not present"),0);
#endif
	if (r!=KErrNone)
		return(r);

	TInt handle;
	r=loader.LoadLibrary(handle,aFileName,_L(".PDD"),_L(""), TUidType(KNullUid, KPhysicalDeviceDriverUid, KNullUid));
	loader.Close();
	__IF_DEBUG(Print(_L("LoadLibrary returns %d"),r));
	if (r!=KErrNone)
		return(r);

	__IF_DEBUG(Print(_L("PhysDevice load")));
	TInt p[KMaxMessageArguments];
	p[0]=handle;
	r=SvSendReceive(ESvPhysicalDeviceLoad,&p[0]);
	RHandleBase lib;
	lib.SetHandle(handle);
	lib.Close();
	__IF_DEBUG(Print(_L("LoadPhysicalDevice returns %d"),r));
	return(r);
	}

EXPORT_C TInt User::FreePhysicalDevice(const TDesC &aDeviceName)
//
// Free a physical device driver DLL
//
	{

	TAny *p[KMaxMessageArguments];
	p[0]=(TAny *)&aDeviceName;
	return(SvSendReceive(ESvPhysicalDeviceFree,&p[0]));
	}

EXPORT_C TInt RLoader::Connect()
//
// Connect with the loader.
//
	{

	return(CreateSession(_L("Loader"),Version(),KLoaderMessageSlots));
	}

EXPORT_C TVersion RLoader::Version() const
//
// Return the client side version number.
//
	{

	return(TVersion(KLoaderMajorVersionNumber,KLoaderMinorVersionNumber,KE32BuildVersionNumber));
	}

EXPORT_C TInt RLoader::LoadProcess(TInt& aHandle,const TDesC& aFileName,const TDesC& aCommand,TOwnerType aType)
//
// Execute a process
//
	{

	TUidType type;
	return LoadProcess(aHandle, aFileName, aCommand, type, aType);
	}

EXPORT_C TInt RLoader::LoadProcess(TInt& aHandle,const TDesC& aFileName,const TDesC& aCommand,const TUidType &aUidType,TOwnerType aType)
//
// Execute another process.
//
	{

	TLoaderInfo info;
	info.iType=aUidType; // match these uids only
	if (aFileName.Length()>KMaxFileName)
		return(KErrBadName);
	info.iFileName=aFileName;
	if (info.iFileName.LocateReverse('.')==KErrNotFound)
		{
		if (info.iFileName.Length()>KMaxFileName-4)
			return(KErrBadName);
		info.iFileName+=_L(".EXE");
		}
	TPtrC f=info.iFileName.Mid(info.iFileName.LocateReverse('\\')+1);
	TInt len=f.LocateReverse('.');
	if (len==KErrNotFound)
		len=f.Length();
	info.iRootName=f.Left(len);
	if (info.iRootName.Length()>KMaxOsName)
		return(KErrBadName);
	if (aCommand.Length()>KMaxCommandLine)
		return KErrBadDescriptor;
	info.iCommandLine=aCommand;

	TPckg<TLoaderInfo> infoBuf(info);
	TAny *p[KMaxMessageArguments];
	p[0]=(TAny*)&infoBuf;
	info.iHandleMask=(aType==EOwnerThread)?KThreadHandle:0; // set the thread/process mask
	TInt r=SendReceive(ELoadProcess,&p[0]);
	aHandle=info.iHandle;
	// Close the process if there was an error.  We also need to Kill it
	// because processes maintain an Open() in DProcess::Create() which
	// doesn't get Close()ed until DProcess::Die()
	// This should be done loader side but it is easier to do it
	// here because the handle is relative to this thread.
	if (r!=KErrNone)
		{
		__IF_DEBUG(Print(_L("Killing proc, and closing proc handle %x"), aHandle));
		RProcess p;
		p.SetHandle(aHandle);
		p.Kill(r);
		p.Close();
		}
	__IF_DEBUG(Print(_L("LoadProcess returning %d"),r));
	return(r);
	}

EXPORT_C TInt RLoader::LoadLibrary(TInt& aHandle,const TDesC& aFileName,const TDesC& anExt, const TDesC& aPath)
//
// Load a library
//
	{

	TUidType type;
	return LoadLibrary(aHandle, aFileName, anExt, aPath, type);
	}

EXPORT_C TInt RLoader::LoadLibrary(TInt& aHandle,const TDesC& aFileName,const TDesC& anExt, const TDesC& aPath, const TUidType &aType)
//
// Load a DLL and add on the extension if one isn't there already
//
	{

	__IF_DEBUG(Print(_L("RLoader::LoadLibrary")));
	TLoaderInfo info;
	TPckg<TLoaderInfo> infoBuf(info);
	info.iPath=aPath;
	if (aFileName.Length()>KMaxFileName)
		return(KErrBadName);
	info.iFileName=aFileName;
	if (info.iFileName.LocateReverse('.')==KErrNotFound)
		{
		if (info.iFileName.Length()>KMaxFileName-4)
			return(KErrBadName);
		info.iFileName+=anExt;
		}

	info.iRootName=info.iFileName.Mid(info.iFileName.LocateReverse('\\')+1);
	TInt dot=info.iRootName.LocateReverse('.');
	if (dot==KErrNotFound)
		dot=info.iRootName.Length();
	info.iRootName.SetLength(dot);
	if (info.iRootName.Length()>KMaxName)
		return(KErrBadName);

	// match this type only
	info.iType=aType;

	__IF_DEBUG(Print(_L("RLoader::LoadLibrary - filename %S"),&info.iFileName));

	TAny *p[KMaxMessageArguments];
	p[0]=(TAny*)&infoBuf;
	TInt r=SendReceive(ELoadLibrary,&p[0]);
	aHandle=info.iHandle;
	__IF_DEBUG(Print(_L("LoadLibrary returning %d"),r));
	return r;
	}

EXPORT_C TInt UserSvr::ProcessCreate(TLoaderInfo &anInfo)
//
// Create the process image from the supplied info.
//
	{

	TPckg<TLoaderInfo> infoBuf(anInfo);
	TAny *p[KMaxMessageArguments];
	p[0]=(TAny *)&infoBuf;
	return(SvSendReceive(ESvProcessCreate|anInfo.iHandleMask,&p[0]));
	}

EXPORT_C void UserSvr::ProcessLoaded(TLoaderInfo &anInfo)
//
// Confirm that the process has been loaded O.K.
//
	{

	TPckg<TLoaderInfo> infoBuf(anInfo);
	TAny *p[KMaxMessageArguments];
	p[0]=(TAny *)&infoBuf;
	SvSendReceiveCheck(ESvProcessLoaded,&p[0]);
	}

EXPORT_C TInt UserSvr::LibraryCreateExact(TLoaderInfo &anInfo)
//
// Create the library image from the supplied info, load without mangling the filename.
//
	{

	TPckg<TLoaderInfo> infoBuf(anInfo);
	TAny *p[KMaxMessageArguments];
	p[0]=(TAny *)&infoBuf;
	return(SvSendReceive(ESvLibraryLoadExact|anInfo.iHandleMask,&p[0]));
	}

EXPORT_C void UserSvr::LibraryLoaded(TLoaderInfo &anInfo)
//
// Confirm that the process has been loaded O.K.
//
	{

	TPckg<TLoaderInfo> infoBuf(anInfo);
	TAny *p[KMaxMessageArguments];
	p[0]=(TAny *)&infoBuf;
	SvSendReceiveCheck(ESvLibraryLoaded,&p[0]);
	}

EXPORT_C void UserSvr::CompleteDisConnect(const RMessage* aMessage,TInt aReason)
//
// Called when the CServer has completed the disconnect message from a client.
//
	{

	TAny* p[KMaxMessageArguments];
	p[0]=(TAny*)aMessage;
	p[1]=(TAny*)aReason;
	SvSendReceiveCheck(ESvCompleteDisConnect,&p[0]);
	}

EXPORT_C TInt UserSvr::DllSetTls(TInt aHandle,TAny *aPtr)
//
// Set the value of the Thread Local Storage variable.
//
	{

	TAny* p[KMaxMessageArguments];
	p[0]=(TAny*)aHandle;
	p[1]=aPtr;
	return(SvSendReceive(ESvDllSetTls,&p[0]));
	}

EXPORT_C void UserSvr::DllFreeTls(TInt aHandle)
//
// Remove the Thread Local Storage variable.
//
	{

	TAny* p[KMaxMessageArguments];
	p[0]=(TAny*)aHandle;
	SvSendReceiveCheck(ESvDllFreeTls,&p[0]);
	}

EXPORT_C TInt UserSvr::DllInitialiseData(TInt aHandle)
//
// Initialise dll data
//
	{

	TAny* p[KMaxMessageArguments];
	p[0]=(TAny*)aHandle;
	return SvSendReceive(ESvDllInitialiseData,&p[0]);
	}

EXPORT_C void UserSvr::DllFreeData(TInt aHandle)
//
// Free dll data for this process
//
	{

	TAny* p[KMaxMessageArguments];
	p[0]=(TAny*)aHandle;
	SvSendReceiveCheck(ESvDllFreeData,&p[0]);
	}

EXPORT_C TInt RChangeNotifier::Create()
//
// Create new change notifier
//
	{

	TAny *p[KMaxMessageArguments];
	TPtr8 h((TUint8 *)&iHandle,sizeof(TInt));
	p[0]=(&h);
	p[1]=(TAny*)KCurrentProcessHandle;
	return(SvSendReceive(ESvNotifierCreate,&p[0]));
	}

EXPORT_C TInt RUndertaker::Create()
//
// Create new undertaker
//
	{

	TAny *p[KMaxMessageArguments];
	TPtr8 h((TUint8 *)&iHandle,sizeof(TInt));
	p[0]=(&h);
	p[1]=(TAny*)KCurrentProcessHandle;
	return(SvSendReceive(ESvUndertakerCreate,&p[0]));
	}

EXPORT_C TInt RUndertaker::Logon(TRequestStatus& aStatus, TInt& aThreadHandle) const
//
// Logon to thread watcher.
//
	{
	
	aStatus=KRequestPending;
	aThreadHandle=0;
	TAny* p[KMaxMessageArguments];
	p[0]=(TAny*)iHandle;
	p[1]=(TAny*)&aStatus;
	p[2]=(TAny*)&aThreadHandle;
	return(SvSendReceive(ESvUndertakerLogon,&p[0]));
	}

EXPORT_C TInt RUndertaker::LogonCancel() const
//
// Logoff from thread watcher.
//
	{
	
	TAny* p[KMaxMessageArguments];
	p[0]=(TAny*)iHandle;
	return(SvSendReceive(ESvUndertakerLogonCancel,&p[0]));
	}

EXPORT_C TInt UserSvr::DllGlobalAlloc(TInt aHandle,TInt aSize)
//
// Allocated the Dll global data.
//
	{

	TInt p[KMaxMessageArguments];
	p[0]=aHandle;
	p[1]=aSize;
	return(SvSendReceive(ESvDllGlobalAlloc,&p[0]));
	}

EXPORT_C void TRegistryCategory::SetItemL(const TDesC8& aName,const TDesC8& aValue)
//
// Set an item in the registry. Leave on error.
//
	{

	TAny* p[KMaxMessageArguments];
	p[0]=(TAny*)&aName;
	p[1]=(TAny*)&aValue;
	TPtrC8 pG((TUint8*)&iUid,sizeof(TUid));
	p[2]=(TAny*)&pG;
	User::LeaveIfError(SvSendReceive(ESvRegistrySetItem,&p[0]));
	}

EXPORT_C void TRegistryCategory::DeleteItemL(const TDesC8& aName)
//
// Delete an item from the registry by name. Leave on error.
//
	{

	TAny* p[KMaxMessageArguments];
	p[0]=(TAny*)&aName;
	TPtrC8 pG((TUint8*)&iUid,sizeof(TUid));
	p[1]=(TAny*)&pG;
	User::LeaveIfError(SvSendReceive(ESvRegistryDeleteItem,&p[0]));
	}

EXPORT_C void TRegistryCategory::DeleteAllItems()
//
// Delete all items from the registry for this category.
//
	{

	TAny* p[KMaxMessageArguments];
	TPtrC8 pG((TUint8*)&iUid,sizeof(TUid));
	p[0]=(TAny*)&pG;
	SvSendReceiveCheck(ESvRegistryDeleteAllItems,&p[0]);
	}

EXPORT_C TInt User::SetMachineConfiguration(const TDesC8& aConfig)
//
// Set the machine configuration
//
    {

	TAny* p[KMaxMessageArguments];
	p[0]=(TAny*)&aConfig;
	return(SvSendReceive(ESvSetMachineConfiguration,&p[0]));
    }

EXPORT_C TInt User::CompressAllHeaps()
//
// Compress all the chunks containing heaps.
//
	{

	TAny* p[KMaxMessageArguments];
	return(SvSendReceive(ESvChunkCompressAll,&p[0]));
	}

EXPORT_C TInt RDebug::Open(TInt aMaxBreak,TInt aMaxWatch,TInt aMaxPanic,TUint aDebugLimit)
//
// Open a debugging session
//
	{

	TAny* p[KMaxMessageArguments];
	p[0]=(TAny*)aMaxBreak;
	p[1]=(TAny*)aMaxWatch;
	p[2]=(TAny*)aMaxPanic;
	p[3]=(TAny*)aDebugLimit;
	return(SvSendReceive(ESvDebugOpen,&p[0]));
	}

EXPORT_C TInt RDebug::Close()
//
// Close a debugging session
//
	{

	TAny* p[KMaxMessageArguments];
    return(SvSendReceive(ESvDebugClose,&p[0]));
	}

EXPORT_C TInt RDebug::KillThread(const TThreadId aId)
//
// Kill the thread
//
    {

	TAny* p[KMaxMessageArguments];
	p[0]=*(TAny**)&aId;
	return(SvSendReceive(ESvDebugKillThread,&p[0]));
    }

EXPORT_C TInt Password::SetEnabled(const TPassword& aPassword,TBool aIsEnabled)
//
// Set the password enabled state
//
	{

	TAny* p[KMaxMessageArguments];
	p[0]=(TAny*)&aPassword;
	p[1]=(TAny*)aIsEnabled;
    return(SvSendReceive(ESvPasswordSetEnabled,&p[0]));
	}

EXPORT_C TInt Password::Set(const TPassword& anOldPassword,const TPassword& aNewPassword)
//
// Set the password to a new password
//
	{

	TAny* p[KMaxMessageArguments];
	p[0]=(TAny*)&anOldPassword;
	p[1]=(TAny*)&aNewPassword;
    return(SvSendReceive(ESvPasswordSet,&p[0]));
	}

TInt RMmu::MmuFunction(TMmuFunction aFunction, TMmuParams& params)
//
// Call the MMU debugging sub-system
//
	{

//	RDebug::Print(_L("RMmu::MmuFunction %d"),aFunction);
	TPckg<TMmuParams> paramBuf(params);
	TAny *p[KMaxMessageArguments];
	p[0]=(TAny*)aFunction;
	p[1]=(TAny*)&paramBuf;
	return(SvSendReceive(ESvMmu,&p[0]));
	}

EXPORT_C void RMmu::MmuInfo(TMmuInfo& anInfo)
	{

//	RDebug::Print(_L("RMmu::MmuInfo"));

	TPckg<TMmuInfo> infoBuf(anInfo);
	TAny *p[KMaxMessageArguments];
	p[0]=(TAny*)&infoBuf;
	SvSendReceive(ESvMmuInfo,&p[0]);
	}

EXPORT_C TInt RMmu::GetNumFreePages()
	{

	TMmuParams p;
	MmuFunction(EGetNumFreePages,p);
	return(p.num);
	}

EXPORT_C TLinAddr RMmu::AllocPageTableL()
	{

	TMmuParams p;
	MmuFunction(EAllocPageTable,p);
	return(p.linAddr1);
	}

EXPORT_C void RMmu::FreePageTable(TLinAddr anAddr)
	{

	TMmuParams p;
	p.linAddr1=anAddr;
	MmuFunction(EFreePageTable,p);
	}

EXPORT_C void RMmu::ChunkCreate(RChunk& aChunk,const TDesC& /*aName*/,TInt aSize,TInt aMaxSize,TUint32 aChunkType)
	{

	TMmuParams p;
	p.size=aSize;
	p.maxSize=aMaxSize;
	p.chunkType=aChunkType;
	MmuFunction(EChunkCreate,p);
	aChunk.SetHandle(p.handle);
	}

EXPORT_C void RMmu::ChunkAdjustUser(RChunk& aChunk,TInt aNewSize)
	{

	TMmuParams p;
	p.handle=aChunk.Handle();
	p.size=aNewSize;
	MmuFunction(EChunkAdjustUser,p);
	}

EXPORT_C TUint32 RMmu::ChunkBase(RChunk& aChunk)
	{

	TMmuParams p;
	p.handle=aChunk.Handle();
	MmuFunction(EChunkBase,p);
	return(p.linAddr1);
	}

EXPORT_C TUint32 RMmu::ChunkEnd(RChunk& aChunk)
	{

	TMmuParams p;
	p.handle=aChunk.Handle();
	MmuFunction(EChunkEnd,p);
	return(p.linAddr1);
	}

EXPORT_C void RMmu::ChunkApplyCorrectPermissions(RChunk& aChunk)
	{

	TMmuParams p;
	p.handle=aChunk.Handle();
	MmuFunction(EChunkApplyCorrectPermissions,p);
	}

EXPORT_C void RMmu::ChunkMoveToRunAddress(RChunk& aChunk,TUint32 aRunAddress)
	{

	TMmuParams p;
	p.handle=aChunk.Handle();
	p.linAddr1=aRunAddress;
	MmuFunction(EChunkMoveToRunAddress,p);
	}

EXPORT_C void RMmu::ChunkMoveToHomeSection(RChunk& aChunk)
	{

	TMmuParams p;
	p.handle=aChunk.Handle();
	MmuFunction(EChunkMoveToHomeSection,p);
	}


EXPORT_C void RMmu::GetPagePerms(TUint32 anAddr,TUint32& aPriv, TUint32& aPerm)
	{

	TMmuParams p;
	p.linAddr1=anAddr;
	MmuFunction(EGetPagePerms,p);
	aPriv=p.priv;
	aPerm=p.perm;
	}

EXPORT_C void RMmu::SetRamFailIn(TInt aNum)
	{

	TMmuParams p;
	p.num=aNum;
	MmuFunction(ESetRamFailIn,p);
	}

EXPORT_C TUint32 RMmu::PhysicalAddress(TUint32 aLinAddr)
	{

	TMmuParams p;
	p.linAddr1=aLinAddr;
	MmuFunction(EPhysicalAddress,p);
	return(p.phyAddr1);
	}

EXPORT_C TUint32 RMmu::LinearAddress(TUint32 aPhysAddr)
	{

	TMmuParams p;
	p.phyAddr1=aPhysAddr;
	MmuFunction(ELinearAddress,p);
	return(p.linAddr1);
	}

EXPORT_C void UserPcCardCntrl::PwrDown(TInt aSocket)
//
// Re-implemented user UserSvr function - need to continue supporting this function.
//
    {

	if (aSocket<0)
        UserSvr::ForceRemountMedia(ERemovableMedia0);
    }

EXPORT_C TInt UserPcCardCntrl::NotifyChange(TInt /*aSocket*/,TRequestStatus *aReqStat)
//
// Re-implemented user UserSvr function - need to continue supporting this function.
//
	{

    return(UserSvr::MediaChangeNotify(ERemovableMedia0,aReqStat));
	}

EXPORT_C void UserSvr::ForceRemountMedia(TMediaDevice aDevice)
//
// Force a remount on the next media access
//
	{

	TInt p[KMaxMessageArguments];
	p[0]=EUserMediaRemount;
	p[1]=(TInt)aDevice;
    SvSendReceive(ESvUserMediaFunction,&p[0]);
	}

EXPORT_C TInt UserSvr::MediaChangeNotify(TMediaDevice aDevice,TRequestStatus *aReqStat)
//
// Callback notification of media insertion or removal
//

	{

	TInt p[KMaxMessageArguments];
	p[0]=EUserMediaNotifyChange;
	p[1]=(TInt)aDevice;
	p[2]=(TInt)aReqStat;
    return(SvSendReceive(ESvUserMediaFunction,&p[0]));
	}

EXPORT_C TInt UserSvr::ChangeLocale(RLibrary aLibrary)
	{	
	TInt p[KMaxMessageArguments];
	p[0]=aLibrary.Handle();
	return(SvSendReceive(ESvChangeLocale,&p[0]));
	}

EXPORT_C TInt UserSvr::DllAddDependency(TAny *anImportingDll, TAny *anExportingDll)
//
//	Make a record in the kernel that anImportingDll depends on anExportingDll
//
	{
	TInt p[KMaxMessageArguments];
	p[0]=(TInt)anImportingDll;
	p[1]=(TInt)anExportingDll;
	return(SvSendReceive(ESvDllAddDependency,&p[0]));
	}

EXPORT_C TInt UserSvr::ExeAddDependency(TAny *anImportingExe, TAny *anExportingDll)
//
//	Make a record in the kernel that the process anImportingExe depends on anExportingDll
//
	{
	TInt p[KMaxMessageArguments];
	p[0]=0;
	p[1]=(TInt)anExportingDll;
	p[2]=(TInt)anImportingExe;
	return(SvSendReceive(ESvDllAddDependency,&p[0]));
	}

EXPORT_C TInt UserSvr::ResetMachine(TMachineStartupType aType)
//
//	Reset the machine. Currently only aType==EStartupWarmReset is supported.
//
	{
	TInt p[KMaxMessageArguments];
	p[0]=(TInt)aType;
	return(SvSendReceive(ESvResetMachine,&p[0]));
	}

