Trying to figure out how to implement my WINC like compatibility layer. Going the emulation way is probably not so smart. We should not use the kernel but rather hook native functions in the Exec calls.
// 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);
// DEF140387:
// If this is not the first call to RequestNotifications then if the
// user just got an overflow notification (and requested again)
// then its possible that iClientTail is not zero now.
// We should set iClientHead to iClientTail, otherwise the client
// can receive another overflow straight away.
notifyRequest->iClientHead = notifyRequest->iClientTail;
}
else
{
notifyRequest->SetActive(CFsNotifyRequest::EInactive);
}
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