userlibandfileserver/fileserver/sfile/sf_notifier_handlers.cpp
author Tom Cosgrove <tom.cosgrove@nokia.com>
Fri, 28 May 2010 16:29:07 +0100
changeset 30 8aab599e3476
parent 4 56f325a607ea
permissions -rw-r--r--
Fix for bug 2283 (RVCT 4.0 support is missing from PDK 3.0.h) Have multiple extension sections in the bld.inf, one for each version of the compiler. The RVCT version building the tools will build the runtime libraries for its version, but make sure we extract all the other versions from zip archives. Also add the archive for RVCT4.

// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
// All rights reserved.
// This component and the accompanying materials are made available
// under the terms of the License "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:
// f32\sfile\sf_notifier_handlers.cpp
// 
//
#include "sf_std.h"
#include "sf_notifier.h"

#ifdef SYMBIAN_F32_ENHANCED_CHANGE_NOTIFICATION

TInt TFsNotificationOpen::Initialise(CFsRequest* /*aRequest*/)
	{
	return KErrNone;
	}

TInt TFsNotificationOpen::DoRequestL(CFsRequest* aRequest)
	{
	__PRINT(_L("TFsNotificationOpen::DoRequestL()"));
	//Check whether we've got a notification manager 
	//If not, create it and call OpenL
	if(!FsNotificationManager::IsInitialised())
		{
		FsNotificationManager::OpenL();
		}
	
	//Create a new CFsNotifyRequest and add it to the manager
	CFsNotifyRequest* notifyRequest = CFsNotifyRequest::NewL();

	//Get handle and add request to manager and Session->Handles
	TInt handle = 0;
	TBool addedToManager = EFalse;
	TRAPD(ret,HandleRequestL(aRequest, notifyRequest, handle,addedToManager));	
	if (ret!=KErrNone)
		{
		//Remove request from Session->Handles if it was already added
		if (handle!=0)
			aRequest->Session()->Handles().Remove(handle,ETrue);
		
		//Remove request from manager
		if(addedToManager)
			{
			FsNotificationManager::Lock();
			FsNotificationManager::RemoveNotificationRequest(notifyRequest);
			FsNotificationManager::Unlock();
			}
		delete notifyRequest;
		return(ret);
		}
	
	notifyRequest->iSession = aRequest->Session();
	aRequest->Session()->IncResourceCount();
	return ret;
	}

//Get handle and add request to Session->Handles
void TFsNotificationOpen::HandleRequestL(CFsRequest* aRequest, CFsNotifyRequest* aNotifyRequest, TInt& aHandle,TBool& aAddedToManager)
	{
	aAddedToManager = EFalse;
	FsNotificationManager::AddNotificationRequestL(aNotifyRequest);
	aAddedToManager = ETrue;
	aHandle = aRequest->Session()->Handles().AddL(aNotifyRequest,ETrue);
	TPtrC8 pH((TUint8*)&aHandle, sizeof(TInt));
	aRequest->WriteL(KMsgPtr3,pH);
	}

TInt TFsNotificationBuffer::Initialise(CFsRequest* /*aRequest*/)
	{
	return KErrNone;
	}

TInt TFsNotificationBuffer::DoRequestL(CFsRequest* aRequest)
	{
	__PRINT(_L("TFsNotificationBuffer::DoRequestL()"));
	HBufC8* buffer = (HBufC8*)(aRequest->Message().Ptr0());
	TInt handle = aRequest->Message().Int3();
	CFsNotifyRequest* notifyRequest = (CFsNotifyRequest*)SessionObjectFromHandle(handle,0,aRequest->Session());
	if(!notifyRequest)
		return KErrBadHandle;
	if(!buffer)
		return KErrArgument;

	notifyRequest->iClientBufferSize = aRequest->Message().Int1();
	notifyRequest->iBufferMsg = aRequest->Message();
	return KErrNone;
	}

TInt TFsNotificationRequest::Initialise(CFsRequest* aRequest)
	{
	TInt handle = aRequest->Message().Int3();	
	CFsNotifyRequest* notifyRequest = (CFsNotifyRequest*)SessionObjectFromHandle(handle,0,aRequest->Session());
	if(!notifyRequest)
		return KErrBadHandle;
	
	//Check the tail's validity
	TInt tail;
	TPckg<TInt> tailPkg(tail);
	TInt r = aRequest->Read(KMsgPtr0,tailPkg);
	
	if(r!=KErrNone || tail < 0 || tail > notifyRequest->iClientBufferSize)
		return KErrArgument;
		
	return KErrNone;
	}

TInt TFsNotificationRequest::DoRequestL(CFsRequest* aRequest)
	{
	__PRINT(_L("TFsNotificationRequest::DoRequestL()"));
	//We need to check whether there is anything in the buffer
	//If so we should complete straight away.
	FsNotificationManager::Lock();
	
	//Get notification request
	TInt handle = aRequest->Message().Int3();	
	CFsNotifyRequest* notifyRequest = (CFsNotifyRequest*)SessionObjectFromHandle(handle,0,aRequest->Session());
	if(!notifyRequest)
		{
		FsNotificationManager::Unlock();
		return KErrBadHandle;
		}
	
	TInt r = notifyRequest->SetClientMessage(aRequest->Message());
	if(r != KErrNone)
		{
		FsNotificationManager::Unlock();
		return r;
		}

	CFsNotifyRequest::TNotifyRequestStatus status = notifyRequest->ActiveStatus();
	if(status==CFsNotifyRequest::EOutstanding ||
		status==CFsNotifyRequest::EOutstandingOverflow)
		{
		notifyRequest->CompleteClientRequest(KErrNone);
		}

	//Update Status
	if(status!=CFsNotifyRequest::EOutstandingOverflow)
		{
		notifyRequest->SetActive(CFsNotifyRequest::EActive);
		// RDebug::Print(_L("TFsNotificationRequest::DoRequestL Not-OutOver- iClientHead==%d, iClientTail==%d"),notifyRequest->iClientHead,notifyRequest->iClientTail);
		}
	else
		{
		notifyRequest->SetActive(CFsNotifyRequest::EInactive);
		
		// RDebug::Print(_L("TFsNotificationRequest::DoRequestL OutOver- iClientHead==%d, iClientTail==%d"),notifyRequest->iClientHead,notifyRequest->iClientTail);
		
		// If the user is in OutstandingOverflow notification state, 
		// then we can set iClientHead to be equal to iServerTail now.
		// That way if the client requests again and the state will go 
		// back to active, the server will see that buffer as empty 
		// rather than full/overflow.
		
		notifyRequest->iClientHead = notifyRequest->iClientTail;
		}
	FsNotificationManager::Unlock();
	return r;
	}

TInt TFsNotificationCancel::Initialise(CFsRequest* /*aRequest*/)
	{
	return KErrNone;
	}

TInt TFsNotificationCancel::DoRequestL(CFsRequest* aRequest)
	{
	__PRINT(_L("TFsNotificationCancel::DoRequestL()"));
	FsNotificationManager::Lock();
	
	//Get notification request and deactivate filter
	TInt handle = aRequest->Message().Int3();	
	CFsNotifyRequest* notifyRequest = (CFsNotifyRequest*)SessionObjectFromHandle(handle,0,aRequest->Session());
	if(!notifyRequest)
		{
		FsNotificationManager::Unlock();
		return KErrBadHandle;
		}
	
	if(notifyRequest->ClientMsgHandle()!=0)
		{	
		notifyRequest->SetActive(CFsNotifyRequest::EInactive);
		notifyRequest->CompleteClientRequest(KErrCancel,ETrue);
		}
	FsNotificationManager::Unlock();
	return KErrNone;
	}

TInt TFsNotificationSubClose::Initialise(CFsRequest* /*aRequest*/)
	{
	return KErrNone;
	}

TInt TFsNotificationSubClose::DoRequestL(CFsRequest* aRequest)
	{
	__PRINT(_L("TFsNotificationSubClose::DoRequestL()"));
	FsNotificationManager::Lock();
	
	//We need to complete the buffer request here as this type of request is not
	//completed in the normal way as it is kept open in order that we can access the buffer
	//in the client-side for the lifetime of this subsession.
	TInt handle = aRequest->Message().Int3();
	CFsNotifyRequest* notifyRequest = (CFsNotifyRequest*) SessionObjectFromHandle(handle,0,aRequest->Session());
	if(!notifyRequest)
		{
		FsNotificationManager::Unlock();
		return KErrBadHandle;
		}
	
	notifyRequest->RemoveFilters();
	notifyRequest->CloseNotification(); //Completes the buffer and the client requests.
	
	TInt count = FsNotificationManager::Count();
	
	//Also deletes notifyRequest
	aRequest->Session()->Handles().Remove(handle,ETrue);
	if(count==1)
		{
		//If this is the last request then we need to remove the manager
		FsNotificationManager::Close();
		}
	
	FsNotificationManager::Unlock();
	aRequest->Session()->DecResourceCount();
	notifyRequest = NULL;

	return(KErrNone);
	}

TInt TFsNotificationAdd::Initialise(CFsRequest* aRequest)
	{
	__PRINT(_L("TFsNotificationAdd::Initialise()"));
	TUint filter = (TUint) aRequest->Message().Int0();
	//If it's AllOps then it's ok
	if (filter!=TFsNotification::EAllOps)
		{

		TInt invalid = filter & ~KNotificationValidFiltersMask;
		//Check: Non-valid values ARE NOT set
		//		 and valid values ARE set.
		if(invalid || !filter)
			{
			return KErrArgument;
			}
		}
	
	TFileName path;
	TInt r = aRequest->Read(KMsgPtr1,path);
	if(r != KErrNone)
		{
		return r;
		}
	
	if(path.Length() >= 2)
		r=PathCheck(aRequest,path.Mid(2),&KCapFsSysFileTemp,&KCapFsPriFileTemp,&KCapFsROFileTemp, __PLATSEC_DIAGNOSTIC_STRING("Notification Add Filter"));
	return r;
	}

TInt TFsNotificationAdd::DoRequestL(CFsRequest* aRequest)
	{
	__PRINT(_L("TFsNotificationAdd::DoRequestL()"));
	TInt handle = aRequest->Message().Int3();
	CFsNotifyRequest* notifyRequest = (CFsNotifyRequest*) SessionObjectFromHandle(handle,0,aRequest->Session());
	if(!notifyRequest)
		return KErrBadHandle;
	
	TFileName path;
	aRequest->Read(KMsgPtr1,path);
	
	TFileName filename;
	TInt r = aRequest->Read(KMsgPtr2,filename);
	if(r!= KErrNone)
		return r;
	
	__PRINT2(_L("TFsNotificationAdd::AddNotification() path=%S, filename=%S"),&path,&filename);
	
	//If this is a path starting with 'drive-letter:'
	TInt driveNum = FsNotificationHelper::DriveNumber(path);
	if(path.Length() >= 2 && (driveNum < 0 || driveNum > 25) && ((TChar)driveNum)!=((TChar)'?') && ((TChar)path[1])==(TChar)':')
		{
		return KErrPathNotFound;
		}

	CleanupStack::PushL(notifyRequest);
	CFsNotificationPathFilter* filter = CFsNotificationPathFilter::NewL(path,filename);

	//Bitmask of filter types
	TUint filterMask = (TUint) aRequest->Message().Int0();
	
	r = notifyRequest->AddFilterL(filter,filterMask);
	CleanupStack::Pop(notifyRequest);

	if(r == KErrNone)
		{
		FsNotificationManager::Lock();
		//Increment global filter register
		FsNotificationManager::SetFilterRegisterMask(filterMask,(TBool)ETrue);
		FsNotificationManager::Unlock();
		}
	return r;
	}

TInt TFsNotificationRemove::Initialise(CFsRequest* /*aRequest*/)
	{
	__PRINT(_L("TFsNotificationRemove::Initialise()"));
	return KErrNone;
	}

TInt TFsNotificationRemove::DoRequestL(CFsRequest* aRequest)
	{
	__PRINT(_L("TFsNotificationRemove::DoRequestL()"));
	FsNotificationManager::Lock();
	
	TInt handle = aRequest->Message().Int3();
	CFsNotifyRequest* notifyRequest = (CFsNotifyRequest*) SessionObjectFromHandle(handle,0,aRequest->Session());
	if(!notifyRequest)
		{
		FsNotificationManager::Unlock();
		return KErrBadHandle;
		}
	
	TInt r = notifyRequest->RemoveFilters();
	FsNotificationManager::Unlock();
	return r;
	}

#else //SYMBIAN_F32_ENHANCED_CHANGE_NOTIFICATION

CFsObjectCon* FsNotificationManager::iNotifyRequests = NULL;

CFsNotifyRequest::CFsNotifyRequest()
	{
	}

CFsNotifyRequest::~CFsNotifyRequest()
	{
	}

TInt TFsNotificationOpen::Initialise(CFsRequest* /*aRequest*/)
	{
	return KErrNotSupported;
	}

TInt TFsNotificationOpen::DoRequestL(CFsRequest* /*aRequest*/)
	{
	return KErrNotSupported;
	}

void TFsNotificationOpen::HandleRequestL(CFsRequest* /*aRequest*/, CFsNotifyRequest* /*aNotifyRequest*/, TInt& /*aHandle*/,TBool& /*aAddedToManager*/)
	{
	User::Leave(KErrNotSupported);
	}

TInt TFsNotificationBuffer::Initialise(CFsRequest* /*aRequest*/)
	{
	return KErrNotSupported;
	}

TInt TFsNotificationBuffer::DoRequestL(CFsRequest* /*aRequest*/)
	{
	return KErrNotSupported;
	}

TInt TFsNotificationRequest::Initialise(CFsRequest* /*aRequest*/)
	{
	return KErrNotSupported;
	}

TInt TFsNotificationRequest::DoRequestL(CFsRequest* /*aRequest*/)
	{
	return KErrNotSupported;
	}

TInt TFsNotificationCancel::Initialise(CFsRequest* /*aRequest*/)
	{
	return KErrNotSupported;
	}

TInt TFsNotificationCancel::DoRequestL(CFsRequest* /*aRequest*/)
	{
	return KErrNotSupported;
	}

TInt TFsNotificationSubClose::Initialise(CFsRequest* /*aRequest*/)
	{
	return KErrNotSupported;
	}

TInt TFsNotificationSubClose::DoRequestL(CFsRequest* /*aRequest*/)
	{
	return KErrNotSupported;
	}

TInt TFsNotificationAdd::Initialise(CFsRequest* /*aRequest*/)
	{
	return KErrNotSupported;
	}

TInt TFsNotificationAdd::DoRequestL(CFsRequest* /*aRequest*/)
	{
	return KErrNotSupported;
	}

TInt TFsNotificationRemove::Initialise(CFsRequest* /*aRequest*/)
	{
	return KErrNotSupported;
	}

TInt TFsNotificationRemove::DoRequestL(CFsRequest* /*aRequest*/)
	{
	return KErrNotSupported;
	}

#endif //SYMBIAN_F32_ENHANCED_CHANGE_NOTIFICATION