dosservices/dosserver/src/dosserver.cpp
author Dremov Kirill (Nokia-D-MSW/Tampere) <kirill.dremov@nokia.com>
Wed, 09 Jun 2010 11:04:22 +0300
branchRCL_3
changeset 34 b2f9f823b5fb
parent 0 4e1aa6a622a0
permissions -rw-r--r--
Revision: 201021 Kit: 2010123

/*
* Copyright (c) 2002 Nokia Corporation and/or its subsidiary(-ies). 
* All rights reserved.
* This component and the accompanying materials are made available
* under the terms of "Eclipse Public License v1.0"
* which accompanies this distribution, and is available
* at the URL "http://www.eclipse.org/legal/epl-v10.html".
*
* Initial Contributors:
* Nokia Corporation - initial contribution.
*
* Contributors:
*
* Description: 
*    Implementation for the CDosServer class
*
*/


#include <e32svr.h>
#include <f32file.h>
#include "dosserver.h"
#include "doseventmanager.h"
#include "dosfactorybase.h"
#include "dossession.h"
#include "dos_debug.h"
#include <data_caging_path_literals.hrh>

/*******************************************************
*  DEFINITION OF THE DSY TO BE USED BY THIS DOS SERVER *
********************************************************/

// This file tells the name of the DSY -module to be loaded.
_LIT(KDosServerIniFile,"Z:\\private\\101f6efa\\DosServer.ini");

// The path where the DSY-module binary must recide. This is hardcoded for
// security reasons.
_LIT(KDSYBinaryLocDrive, "z:");

//
// ---------------------------------------------------------
// CDosServer Constructor
// ---------------------------------------------------------
//  
CDosServer::CDosServer()
    : CPolicyServer( CActive::EPriorityStandard, KDosServerPolicy )
{
	iSessionCount=0;
	iContainerIx = NULL;
	iDosFactory = NULL;
	iLibLoaded = EFalse;
	iCurrentFreeDiskSpaceRequest = NULL;
}


//
// ---------------------------------------------------------
// CDosServer Desctructor
// ---------------------------------------------------------
//  
CDosServer::~CDosServer()
{
	COM_TRACE_( "[DOSSERVER]\t CDosServer::~CDosServer()" );

	// Delete our own stuff
	delete iEventManager;

	//We delete here all the open Sessions
	//This is done also by ~CServer but we do it here because it must be done before
	//deleting iContainerIx since iContainerIx will try to delete the CObjects that are
	//referenced by the Session's containers

	CDosSession* session=NULL;
	iSessionIter.SetToFirst();
	while((session = (CDosSession*)(iSessionIter++)) != NULL)
	{
		delete session;
	}
	
	if ( iFileSystemNotifier )
        {
        COM_TRACE_( "CDosServer::~CDosServer(), deleting iFileSytemNotifier" );
        iFileSystemNotifier->Cancel();
        delete iFileSystemNotifier;
        }
	delete iDosFactory;
	delete iContainerIx;

	COM_TRACE_( "[DOSSERVER]\t CDosServer::~CDosServer() - end" );

	//Check if RLibrary::Load() has been called
	if (iLibLoaded) 
	{
		iLib.Close();
		iLibLoaded = EFalse;
	}

    if ( iSaeThread )
    {
    delete iSaeThread;
    }
}  

//
// ---------------------------------------------------------
// CDosServer::ConstructL
// ---------------------------------------------------------
//  

void CDosServer::ConstructL()
{
	User::RenameThread(KDosServerName);
    // set this as a system thread so if it crashes the phone will restart
	User::SetCritical(User::ESystemCritical);
	COM_TRACE_( "CDosServer::ConstructL(), creating iFileSytemNotifier" );
    iFileSystemNotifier = CSharedDataFileSystemNotifier::NewL(*this);

	iEventManager = CDosEventManager::NewL();
	LoadDsyModuleL();
	iContainerIx = CObjectConIx::NewL();
	
	StartL(KDosServerName);
	
    iSaeThread = CSaeThread::NewL();
    iSaeThread->StartThreadL();
}

//
// ---------------------------------------------------------
// CDosServer::NewL
// ---------------------------------------------------------
//  
CDosServer* CDosServer::NewL()
{
    CDosServer* self=new(ELeave) CDosServer;
    CleanupStack::PushL(self);
    self->ConstructL();
    CleanupStack::Pop();

    return self;
}

//
// ---------------------------------------------------------
// CDosServer::LoadDsyModuleL
// ---------------------------------------------------------
//  

void CDosServer::LoadDsyModuleL()
{
	COM_TRACE_( "[DOSSERVER]\t CDosServer::LoadDsyModuleL()" );

	//Finding out the name of the Dsy file.
	RFs fs;
	RFile file;

	User::LeaveIfError(fs.Connect());
	CleanupClosePushL(fs);

	COM_TRACE_( "[DOSSERVER]\t CDosServer::LoadDsyModuleL() - fs connected" );

	COM_TRACE_( "[DOSSERVER]\t Opening file: Z:\\system\\data\\DosServer.ini" );
	COM_TRACE_( "[DOSSERVER]\t error occurs if above file is missing from build!" );

	User::LeaveIfError(file.Open(fs,KDosServerIniFile,EFileRead));
	CleanupClosePushL(file);

	COM_TRACE_( "[DOSSERVER]\t CDosServer::LoadDsyModuleL() - file opened" );

	TBuf8<KMaxFileName> rawFileName;
	
	User::LeaveIfError(file.Read(rawFileName));

	CleanupStack::PopAndDestroy(2); //fs and file are closed

	COM_TRACE_( "[DOSSERVER]\t CDosServer::LoadDsyModuleL() - file readed" );

	HBufC* unicodeFileName = HBufC::NewLC(rawFileName.Length());
	TPtr fileNamePtr(unicodeFileName->Des());
	fileNamePtr.Copy(rawFileName);

	COM_TRACE_1( "[DOSSERVER]\t CDosServer::LoadDsyModuleL() - name: %S", unicodeFileName );

	//Loading of the Dsy module
	TLibraryFunction entryPoint;

	// Check for data caging support;
	// Template parameter defines the maximum length for descriptor. 
	// After copy the length is set to same as the copied descriptor.
	TBuf<128> dsyBinaryLoc(KDC_SHARED_LIB_DIR);
	dsyBinaryLoc.Insert(0, KDSYBinaryLocDrive);

#ifdef _DEBUG // Trace used binary path.
	HBufC* dsyFileName = HBufC::NewLC(dsyBinaryLoc.Length());
	TPtr fNPtr(dsyFileName->Des());
	fNPtr.Copy(dsyBinaryLoc);

	COM_TRACE_1( "[DOSSERVER]\t CDosServer::LoadDsyModuleL() - bin path: %S", dsyFileName );
	CleanupStack::PopAndDestroy(); //dsyFileName
#endif
	User::LeaveIfError(iLib.Load(fileNamePtr, dsyBinaryLoc));

	iLibLoaded = ETrue; //RLibrary::Load() has been called
	entryPoint = iLib.Lookup(1); //Polymorphic DLL only 1 entry point.
	iDosFactory = (CDosFactoryBase *)entryPoint();
	iDosFactory->iEventManager = CONST_CAST(CDosEventManager*,iEventManager);
	CleanupStack::PopAndDestroy(); //unicodeFileName

	COM_TRACE_( "[DOSSERVER]\t CDosServer::LoadDsyModuleL() completed" );
}


//
// ---------------------------------------------------------
// CDosServer::RunError
// ---------------------------------------------------------
//  
TInt CDosServer::RunError(TInt aError)
{
	//
	// Handles an error from CDosSession::ServiceL()
	// Report the error to the client
	//
	COM_TRACE_1( "[DOSSERVER]\t CDosServer::RunError() error: %d", aError );

	Message().Complete(aError);
	ReStart();
	return KErrNone;	// handled the error fully
}

//
// ---------------------------------------------------------
// CDosServer::NewSessionL
// ---------------------------------------------------------
//  

CSession2* CDosServer::NewSessionL(const TVersion&) const
{
	COM_TRACE_( "CDosServer::NewSessionL()" );
	//
	// Create a new client session.
	//
	return new(ELeave) CDosSession();
}

CSession2* CDosServer::NewSessionL(const TVersion& aVersion, const RMessage2& /*aMessage*/) const
{
	return NewSessionL(aVersion);
}
//
// ---------------------------------------------------------
// CDosServer::AddSession
// ---------------------------------------------------------
//  

void CDosServer::AddSession()
{
	//
	// A new session is being created
	//
	++iSessionCount;
	COM_TRACE_1( "[DOSSERVER]\t ** CDosServer - Add session, count: %d", iSessionCount );
}

//
// ---------------------------------------------------------
// CDosServer::DropSession
// ---------------------------------------------------------
//  

void CDosServer::DropSession()
{
	//
	// A session is being destroyed
	//
    iSessionCount--;
	COM_TRACE_1( "[DOSSERVER]\t ** CDosServer - Drop session, count: %d", iSessionCount );
}

//
// ---------------------------------------------------------
// CDosServer::ThreadStart
//
// It Starts the Server's Thread and the Server
// ---------------------------------------------------------
//  

EXPORT_C TInt CDosServer::ThreadStart( CDosServer::TSignal& /*aSignal*/ )
{
    // Get thread that started us
	__UHEAP_MARK;
	TInt err(KErrNone);

    CTrapCleanup* cleanup = NULL;
    CActiveScheduler* scheduler = NULL;
    CDosServer* server = NULL;
	TInt srvErr=KErrNoMemory;

    cleanup = CTrapCleanup::New();
    scheduler = new CActiveScheduler;

    if ( cleanup && scheduler )
    {
        CActiveScheduler::Install( scheduler );
        TRAP(srvErr, server = CDosServer::NewL());      // adds server in scheduler
    }

    if ( !cleanup || !scheduler || srvErr!=KErrNone )
    {
        if ( scheduler ) 
		{
			delete scheduler;
			scheduler = NULL;
		}
		if ( server )
		{
			delete server;
			server = NULL;
		}
		if ( cleanup )
		{
	        delete cleanup;
			cleanup = NULL;
		}
        err = srvErr;
    }

    // signal that we've started
	COM_TRACE_( "CDosServer::ThreadStart - calling SignalClient()" );
	SignalClient();

    if ( err == KErrNone )
    {
        // start fielding requests from clients
        CActiveScheduler::Start();

        // comes here if server gets shut down

        delete scheduler;
		scheduler = NULL;
        delete server;
		server = NULL;
        delete cleanup;
		cleanup = NULL;
    }

    // thread/process exit
	__UHEAP_MARKEND;
    return err;
}

//
// ---------------------------------------------------------
// CDosServer::SignalClient
//
// Signal client we've started.
// ---------------------------------------------------------
//  
void CDosServer::SignalClient()
{
	COM_TRACE_( "[DOSSERVER]\t CDosServer::SignalClient() called" );
	RSemaphore startupSemaphore;
	if ( startupSemaphore.OpenGlobal( KServerStartupSemaphoreName ) == KErrNone )
	{
		//Signal the client:The server might have started up successfully or not
		startupSemaphore.Signal();
		COM_TRACE_( "[DOSSERVER]\t CDosServer::SignalClient() semaphore signalled" );
	}

	startupSemaphore.Close();
	COM_TRACE_( "[DOSSERVER]\t CDosServer::SignalClient() semaphore closed" );

	// No point to return any error; 
	// if signal client fails, startup will freeze anyway.
}

//
// RMessage::Panic() also completes the message. This is:
// (a) important for efficient cleanup within the kernel
// (b) a problem if the message is completed a second time
//
void PanicClient(const RMessage2& aMessage,TDosPanic aPanic)
{
	COM_TRACE_( "[DOSSERVER]\t CDosServer::RMessage::PanicClient() called" );

	aMessage.Panic(KDosServerName,aPanic);
}

//
// ---------------------------------------------------------
// CDosServer::CurrentDiskFreeSpace
//
// Returns current disk space
// ---------------------------------------------------------
//  
TInt* CDosServer::CurrentFreeDiskSpaceRequest()
{
    COM_TRACE_( "CDosServer::CurrentFreeDiskSpaceRequest()" );
    return iCurrentFreeDiskSpaceRequest;    
}

//
// ---------------------------------------------------------
// CDosServer::SetCurrentFreeDiskSpace
//
// Sets new current disk space
// ---------------------------------------------------------
//  
void CDosServer::SetCurrentFreeDiskSpaceRequest(TInt* diskSpace)
{
 COM_TRACE_( "CDosServer::SetCurrentFreeDiskSpaceRequest()" );
    iCurrentFreeDiskSpaceRequest = diskSpace;    
}