userlibandfileserver/fileserver/sfile/sf_notify.cpp
changeset 299 b5a01337d018
parent 286 48e57fb1237e
--- a/userlibandfileserver/fileserver/sfile/sf_notify.cpp	Tue Oct 26 12:49:20 2010 +0100
+++ b/userlibandfileserver/fileserver/sfile/sf_notify.cpp	Mon Nov 01 20:11:36 2010 +0000
@@ -16,14 +16,866 @@
 //
 
 #include "sf_std.h"
+#include "sf_notifier.h"
+#include "sf_pool.h"
 
-
+#ifdef SYMBIAN_F32_ENHANCED_CHANGE_NOTIFICATION
+#include <f32notification.h>
+#endif
 
 TChangeQue FsNotify::iChangeQues[KMaxNotifyQues];
 TDiskSpaceQue FsNotify::iDiskSpaceQues[KMaxDiskQues];
 TDebugQue FsNotify::iDebugQue;
 TDismountNotifyQue FsNotify::iDismountNotifyQue;
 
+_LIT(KEmptyString,"");
+
+CFsNotificationInfoBody::CFsNotificationInfoBody()
+: iSrc(KEmptyString),
+  iSrcBuf(KEmptyString),
+  iDest(KEmptyString),
+  iDestDriveStored(EFalse),
+  iFunction(KErrNotFound),
+  iData(KErrNotFound), 
+#ifdef SYMBIAN_F32_ENHANCED_CHANGE_NOTIFICATION
+  iNotificationType(TFsNotification::EOverflow),
+#else
+  iNotificationType(KErrNotFound),
+#endif
+  iUid(TUid::Null())
+    {
+    }
+
+CFsNotificationInfo::CFsNotificationInfo()
+    {
+    }
+
+/*
+ * These do not get deleted, they get Freed via CFsNotificationInfo::Free.
+ */
+CFsNotificationInfo::~CFsNotificationInfo()
+    {
+    Fault(ENotificationInfoDeletion);
+    }
+
+TInt CFsNotificationInfo::Init(TInt aFunction, TInt aDriveNum)
+    {
+    //Clean notification before use
+    CleanNotification();
+    
+    iBody->iFunction = aFunction;
+    TInt err = SetDriveNumber(aDriveNum);
+    if(err != KErrNone)
+        {
+        return err;
+        }
+ 
+    //Set notification type
+#ifdef SYMBIAN_F32_ENHANCED_CHANGE_NOTIFICATION
+    CFsNotificationInfo::NotificationType(iBody->iFunction, iBody->iNotificationType);
+#else
+    iBody->iNotificationType = KErrNotSupported;
+#endif   
+    return KErrNone;
+    }
+
+void CFsNotificationInfo::CleanNotification()
+    {
+    //Clear all variables 
+    TParsePtrC empty(KEmptyString);
+    memcpy(&iBody->iSrc,&empty,sizeof(TParsePtrC));
+    memcpy(&iBody->iDest,&empty,sizeof(TParsePtrC));
+    iBody->iData = KErrNotFound;
+    iBody->iRequest = NULL;
+    iBody->iDriveNumber = KErrNotFound;
+    iBody->iUid = TUid::Null();
+    iBody->iDestDriveStored = EFalse;
+#ifdef SYMBIAN_F32_ENHANCED_CHANGE_NOTIFICATION
+    iBody->iNotificationType=TFsNotification::EOverflow;
+#else
+    iBody->iNotificationType=KErrNotFound;
+#endif
+    }
+
+EXPORT_C CFsNotificationInfo* CFsNotificationInfo::Allocate(const CMountCB& aMount, TInt aFunction)
+    {
+    CFsNotificationInfo* info = NotificationInfoPool->Allocate();
+    __ASSERT_DEBUG(info,User::Panic(_L("CFsNotificationInfo::Allocate, Could not allocate"),KErrNotFound));
+    
+    TInt driveNum = aMount.Drive().DriveNumber();
+    __ASSERT_ALWAYS((driveNum >= EDriveA && driveNum <= EDriveZ), User::Panic(_L("CFsNotificationInfo::Allocate - Invalid Drive Num"),KErrArgument));
+    TInt err = info->Init(aFunction,driveNum);
+    if(err != KErrNone)
+        {
+        Free(info);
+        return NULL;
+        }
+    return info;
+    }
+
+
+CFsNotificationInfo* CFsNotificationInfo::Allocate(CFsMessageRequest& aRequest)
+    {
+    //Get a notification Info block from the pool.
+    CFsNotificationInfo* notificationInfo = NotificationInfoPool->Allocate();
+    
+    //Set the function and call Init.
+    TInt function = aRequest.Operation()->Function();
+    notificationInfo->iBody->iFunction = function;
+    TInt err = notificationInfo->Init(function,aRequest.DriveNumber());
+    if(err != KErrNone)
+        {
+        CFsNotificationInfo::Free(notificationInfo);
+        return NULL;
+        }
+
+    //Set request
+    notificationInfo->SetRequest(&aRequest);
+
+	//Set UID
+    notificationInfo->SetUid(aRequest.Uid()); 
+
+    //Set notification type
+#ifdef SYMBIAN_F32_ENHANCED_CHANGE_NOTIFICATION
+    CFsNotificationInfo::SetData(&aRequest,notificationInfo);
+#endif    
+    
+    CFsClientMessageRequest& msgRequest = (CFsClientMessageRequest&)aRequest;
+    
+    //Get and store Src
+    CFsNotificationInfo::PathName(msgRequest,notificationInfo->Source());
+    
+	//Get and store NewName/Dest
+    switch(function)
+        {
+        case EFsFileRename:
+        case EFsRename:    
+        case EFsReplace:   
+        case EFsSetDriveName:
+        case EFsSetVolume:
+            {
+            CFsNotificationInfo::NewPathName((CFsClientMessageRequest&)aRequest,notificationInfo->NewName());
+            notificationInfo->iBody->iDestDriveStored = ETrue;
+            }
+        default:
+            break;
+        }
+    return notificationInfo;
+    }
+
+CFsNotificationInfo* CFsNotificationInfo::Allocate(TInt aFunction, TInt aDrive)
+    {
+    //Get a notification Info block from the pool.
+    CFsNotificationInfo* notificationInfo = NotificationInfoPool->Allocate();
+    
+    //Set the function and call Init.
+    notificationInfo->iBody->iFunction = aFunction;
+    TInt err = notificationInfo->Init(aFunction,aDrive);
+    if(err != KErrNone)
+        {
+        CFsNotificationInfo::Free(notificationInfo);
+        return NULL;
+        }
+    
+    //Set request (NULL)
+    notificationInfo->SetRequest(NULL);
+	
+	//Set UID (KNullUid)
+    notificationInfo->SetUid(TUid::Null());
+    return notificationInfo;
+    }
+
+EXPORT_C void CFsNotificationInfo::Free(CFsNotificationInfo*& aNotificationInfo)
+    {
+    __ASSERT_DEBUG(aNotificationInfo,User::Panic(_L("CFsNotificationInfo::Free - KErrArgument"), KErrArgument));
+    NotificationInfoPool->Free(aNotificationInfo);    
+    aNotificationInfo = NULL;
+    }
+
+
+TInt CFsNotificationInfo::Initialise()
+    {
+    //Have to trap as sf_main.cpp commonInitialize doesn't.
+    TRAPD(r, NotificationInfoPool = CFsPool<CFsNotificationInfo>::New(KMaxDrives,CFsNotificationInfo::New));
+    if(r != KErrNone)
+        return r;
+    if(!NotificationInfoPool)
+        return KErrNoMemory;
+    return KErrNone;
+    }
+
+CFsNotificationInfo* CFsNotificationInfo::New()
+    {
+    CFsNotificationInfo* info = new CFsNotificationInfo;
+    __ASSERT_ALWAYS(info,Fault(ENotifyPoolCreation));
+    info->iBody = new CFsNotificationInfoBody();
+    __ASSERT_ALWAYS(info->iBody,Fault(ENotifyPoolCreation));
+    return info;
+    }
+
+EXPORT_C TInt CFsNotificationInfo::SetSourceName(const TDesC& aSrc)
+    {
+    //Add the aSrc to a TParsePtrC (no copying the filename)
+    TParsePtrC sourceParsePtr(aSrc);
+    
+    if(sourceParsePtr.DrivePresent() || !sourceParsePtr.FullName().Length())
+        return KErrArgument;
+    
+    switch(iBody->iFunction)
+        {
+
+        case EFsFileWrite:          //EParseSrc | EFileShare
+        case EFsFileSetSize:        //EParseSrc | EFileShare
+        case EFsFileSetAtt:         //EParseDst | EParseSrc, - should not use these; has share.
+        case EFsFileSet:            //EParseSrc | EFileShare
+        case EFsFileSetModified:    //EParseSrc | EFileShare - new
+        case EFsFileWriteDirty:     //EFileShare
+        case EFsFileCreate:         //EParseSrc
+        case EFsFileTemp:           //EParseSrc - new
+        case EFsFileRename:         //EParseDst | EParseSrc,
+        case EFsFileReplace:        //EParseSrc
+            {
+            //Should look like this:  \[path\]filename
+            if(!sourceParsePtr.Name().Length())
+                {
+                return KErrArgument;
+                }
+            break;
+            }
+        case EFsDelete:             //EParseSrc
+        case EFsSetEntry:           //EParseSrc,
+        case EFsRename:             //EParseDst | EParseSrc,
+        case EFsReplace:            //EParseDst | EParseSrc,
+            {
+            if(!sourceParsePtr.PathPresent() && !sourceParsePtr.NamePresent())
+                {
+                return KErrArgument;
+                }
+            break;
+            }
+        case EFsRmDir:              //EParseSrc
+        case EFsMkDir:              //EParseSrc
+            {
+            if(!sourceParsePtr.PathPresent())
+                {
+                return KErrArgument;
+                }
+            break;
+            }
+      /*case EFsFormatNext:         //EParseSrc
+        case EFsDismountFileSystem: //0
+        case EFsMountFileSystem:    //0
+        case EFsSetVolume:          //0
+        case EFsSetDriveName:       //ESync
+        case EFsRawDiskWrite:       //EParseSrc
+        case EFsMountFileSystemScan: */
+        default:
+            {
+            __ASSERT_DEBUG(EFalse,User::Panic(_L("CFsNotificationInfo::SetSourceName Invalid Operation"),KErrArgument));
+            return KErrNotSupported;
+            }
+        }
+    memcpy(&iBody->iSrc,&sourceParsePtr,sizeof(TParsePtrC));
+    return KErrNone;
+    }
+
+EXPORT_C TInt CFsNotificationInfo::SetNewName(const TDesC& aDest)
+    {
+    //Add the aSrc to a TParsePtr for some validation without copying the filename
+    TParsePtrC destParsePtr(aDest);
+    
+    if(destParsePtr.DrivePresent() || !destParsePtr.FullName().Length())
+        return KErrArgument;
+    
+    switch(iBody->iFunction)
+        {
+        case EFsFileRename:         //EParseDst | EParseSrc,
+        case EFsRename:             //EParseDst | EParseSrc,
+        case EFsReplace:            //EParseDst | EParseSrc,
+            {
+            if(!destParsePtr.PathPresent() && !destParsePtr.NamePresent())
+                {
+                return KErrArgument;
+                }
+            break;
+            }
+        case EFsSetDriveName:
+        case EFsSetVolume:
+            {
+            if(!destParsePtr.NamePresent())
+                {
+                return KErrArgument;
+                }
+            break;
+            }            
+        default:
+            {
+            __ASSERT_DEBUG(ETrue,User::Panic(_L("CFsNotificationInfo::SetNewName Invalid Operation"),KErrArgument));
+            }
+        }
+    
+    memcpy(&iBody->iDest,&destParsePtr,sizeof(TParsePtrC));
+    return KErrNone;
+    }
+
+EXPORT_C TInt CFsNotificationInfo::SetFilesize(TInt64 aFilesize)
+    {
+    if(aFilesize<0)
+        return KErrArgument;
+    
+    iBody->iData = aFilesize;
+    return KErrNone;
+    }
+EXPORT_C TInt CFsNotificationInfo::SetAttributes(TUint aSet,TUint aCleared)
+    {
+    iBody->iData = MAKE_TUINT64(aSet,aCleared);
+    return KErrNone;
+    }
+
+EXPORT_C TInt CFsNotificationInfo::SetUid(const TUid& aUid)
+    {
+    iBody->iUid = aUid;
+    return KErrNone;
+    }
+
+
+TInt CFsNotificationInfo::SetDriveNumber(TInt aDriveNumber) 
+    {
+    if(aDriveNumber >= EDriveA && aDriveNumber <= EDriveZ)
+        {
+        iBody->iDriveNumber = aDriveNumber;
+        return KErrNone;
+        }
+    return KErrArgument;    
+    }
+void CFsNotificationInfo::SetRequest(CFsRequest* aRequest)
+    {
+    iBody->iRequest = aRequest;
+    }
+TInt CFsNotificationInfo::Function() 
+    { return iBody->iFunction; }
+TInt CFsNotificationInfo::DriveNumber() 
+    { return iBody->iDriveNumber; }
+TParsePtrC& CFsNotificationInfo::Source() 
+    {
+    switch(iBody->iFunction)
+        {
+        case EFsFormatNext:         //EParseSrc
+        case EFsDismountFileSystem: //0
+        case EFsMountFileSystem:    //0
+        case EFsSetVolume:          //0
+        case EFsSetDriveName:       //ESync
+        case EFsRawDiskWrite:       //EParseSrc
+        case EFsMountFileSystemScan:
+            {
+            _LIT(KFormatDrive,"?:");
+            iBody->iSrcBuf = KFormatDrive;
+            iBody->iSrcBuf[0] = TText(DriveNumber() + 'A');
+            TParsePtrC parse(iBody->iSrcBuf);
+            memcpy(&iBody->iSrc,&parse,sizeof(TParsePtrC));
+            }
+        }
+    return iBody->iSrc;
+    }
+TParsePtrC& CFsNotificationInfo::NewName() 
+    { return iBody->iDest; }
+CFsRequest* CFsNotificationInfo::Request() 
+    { return iBody->iRequest; }
+TInt64* CFsNotificationInfo::Data() 
+    { return &iBody->iData; }
+TUid& CFsNotificationInfo::Uid()
+    { return iBody->iUid; }
+TNotificationType& CFsNotificationInfo::NotificationType()
+    { return iBody->iNotificationType; }
+TBool CFsNotificationInfo::DestDriveIsSet()
+    { return iBody->iDestDriveStored; }
+TInt CFsNotificationInfo::SourceSize()
+    {
+    TInt size = Source().FullName().Size();
+    if(NotificationType()!=TFsNotification::EMediaChange    &&
+       NotificationType()!=TFsNotification::EDriveName      && 
+       NotificationType()!=TFsNotification::EVolumeName)
+        {
+        size += sizeof(TText)*2;
+        }
+    return size;    
+    }
+TInt CFsNotificationInfo::NewNameSize()
+    {
+    TInt size = NewName().FullName().Size();
+    if(!DestDriveIsSet())
+        size += sizeof(TText)*2;
+    return size;  
+    }
+
+//Get the path of the file, folder or drive name based on the TFsMessage function
+void CFsNotificationInfo::PathName(CFsClientMessageRequest& aRequest, TParsePtrC& aPath)
+    {
+    __PRINT(_L("CFsNotificationInfo::PathName"));
+    //Get the notification type
+    TInt function = aRequest.Operation()->Function();
+    
+    //Get the filename(s)
+    switch(function)
+        {
+        case EFsFileWrite:          //EParseSrc | EFileShare
+        case EFsFileSetSize:        //EParseSrc | EFileShare
+        case EFsFileSetAtt:         //EParseDst | EParseSrc, - should not use these; has share.
+        case EFsFileSet:            //EParseSrc | EFileShare
+        case EFsFileSetModified:    //EParseSrc | EFileShare - new
+        case EFsFileWriteDirty:     //EFileShare
+            {
+            CFileShare* share = NULL;
+            CFileCB* file = NULL;
+            GetFileFromScratch(&aRequest,share,file);
+            TParsePtrC ptrC(file->iFileName->Des());
+            memcpy(&aPath,&ptrC,sizeof(TParsePtrC));
+            break;
+            }
+        case EFsFileCreate:         //EParseSrc
+        case EFsFileTemp:           //EParseSrc - new
+        case EFsDelete:             //EParseSrc
+        case EFsSetEntry:           //EParseSrc,
+        case EFsFileRename:         //EParseDst | EParseSrc,
+        case EFsRename:             //EParseDst | EParseSrc,
+        case EFsReplace:            //EParseDst | EParseSrc,
+        case EFsFileReplace:        //EParseSrc
+            {
+            TParsePtrC parsePtrC(aRequest.Src().FullName().Mid(2)); //Don't want drive letter
+            memcpy(&aPath,&parsePtrC,sizeof(TParsePtrC));
+            break;
+            }
+        case EFsRmDir:              //EParseSrc
+        case EFsMkDir:              //EParseSrc
+            {
+            TParsePtrC parsePtrC(aRequest.Src().Path());
+            memcpy(&aPath,&parsePtrC,sizeof(TParsePtrC));
+            break;
+            
+            //aPath.Set(aRequest.Src().DriveAndPath(),NULL,NULL);
+            //break;
+            }
+        case EFsFormatNext:         //EParseSrc
+        case EFsDismountFileSystem: //0
+        case EFsMountFileSystem:    //0
+        case EFsSetVolume:          //0
+        case EFsSetDriveName:       //ESync
+        case EFsRawDiskWrite:       //EParseSrc
+        case EFsLockDrive:
+        case EFsUnlockDrive:
+        case EFsReserveDriveSpace:
+        case EFsMountFileSystemScan:
+            {
+            break;
+            }
+        default:
+            ASSERT(0);
+            break;
+        }
+    }
+
+//Get the new path of the file, folder or drive name based on the TFsMessage function
+void CFsNotificationInfo::NewPathName(CFsClientMessageRequest& aRequest, TParsePtrC& aNewPath)
+    {
+    __PRINT(_L("CFsNotificationInfo::NewPathName"));
+    //Get the notification type
+    TInt function = aRequest.Operation()->Function();
+
+    //Get the filename(s)
+    switch(function)
+        {
+        case EFsFileRename:         //EParseDst | EParseSrc,
+        case EFsRename:             //EParseDst | EParseSrc,
+        case EFsReplace:            //EParseDst | EParseSrc,
+            {
+            //We must provide the drive letter too as in the case
+            //of the file being monitored being renamed to a 
+            //different drive.
+            //In that case we need to provide the new drive letter to the client.
+            TParsePtrC ptrC(aRequest.Dest().FullName());
+            memcpy(&aNewPath,&ptrC,sizeof(TParsePtrC));
+            break;
+            }
+        case EFsSetVolume:          //EParseDst
+        case EFsSetDriveName:       //ESync | EParseDst
+            {
+            TParsePtrC ptrC(aRequest.Dest().FullName());
+            memcpy(&aNewPath,&ptrC,sizeof(TParsePtrC));
+            break;
+            }
+        default:
+            {
+            ASSERT(0);
+            }
+        }
+    }
+
+//Get the size of the notification based on its type
+TInt CFsNotificationInfo::NotificationSize(CFsNotificationInfo& aRequest)
+    {
+    __PRINT(_L("CFsNotificationInfo::NotificationSize"));
+    
+    /*
+     * If there are no new names, the order of the data in the buffer is:
+     * Word1   : NotificationSize (2 bytes) , PathSize (2 bytes)
+     * Word2   : NotificationType (Lower 2 bytes)
+     * Word3   : UID
+     * Word(s) : Path (TText8) , [Any sub-class members]
+     * 
+     * Else for notification types ERename, EVolumeName and EDriveName the order is:
+     * Word1   : NotificationSize (2 bytes) , PathSize (2 bytes)
+     * Word2   : NewNameSize (2 bytes) , NotificationType (2 bytes)
+     * Word3   : UID
+     * Word(s) : Path (TText8) , NewName (TText8)
+     * 
+     * EOverflow size: KNotificationHeaderSize
+     */ 
+    
+    //Size of the filename +(with '<drive>:')
+    TInt size = KNotificationHeaderSize + Align4(aRequest.SourceSize());
+    
+    switch(aRequest.NotificationType())
+        {
+        //NewName
+        case TFsNotification::ERename:
+        case TFsNotification::EVolumeName:
+        case TFsNotification::EDriveName:
+            {
+            if(!aRequest.NewName().FullName().Length())
+                __ASSERT_ALWAYS(false,User::Panic(_L("CFsNotificationInfo::NotificationSize"),KErrArgument));
+            
+            size += Align4(aRequest.NewNameSize());
+            break;
+            }
+        case TFsNotification::EFileChange:
+            {
+            size += sizeof(TInt64);
+            break;
+            }
+        case TFsNotification::EAttribute:
+            {
+            size += sizeof(TUint64);
+            break;
+            }
+        case TFsNotification::ECreate: 
+        case TFsNotification::EDelete:
+        case TFsNotification::EMediaChange:
+            {
+            break;
+            }
+        default:
+            {
+            ASSERT(0);
+            break;
+            }
+        }
+    return (TUint16) size;
+    }
+
+
+TNotificationType CFsNotificationInfo::NotificationType(TInt& aIndex)
+    {
+    __PRINT(_L("CFsNotificationInfo::NotificationType(TInt)"));
+    __ASSERT_DEBUG(aIndex < KNumRegisterableFilters, Fault(ENotificationFault));
+    
+    switch(aIndex) //No break statements here on purpose
+        {
+        case 7 : return TFsNotification::EMediaChange;
+        case 6 : return TFsNotification::EDriveName;
+        case 5 : return TFsNotification::EVolumeName;
+        case 4 : return TFsNotification::EDelete;
+        case 3 : return TFsNotification::EAttribute;
+        case 2 : return TFsNotification::ECreate;
+        case 1 : return TFsNotification::ERename;
+        case 0 : return TFsNotification::EFileChange;
+        default: ASSERT(0); return (TFsNotification::TFsNotificationType) 0;
+        }
+    }
+
+//Get the array index of the notification based on its type
+TInt CFsNotificationInfo::TypeToIndex(TNotificationType aType)
+    {
+    __PRINT(_L("CFsNotificationInfo::ArrayIndex"));
+
+    TInt index = 0; 
+    switch(aType) //No break statements here on purpose
+        {
+        case TFsNotification::EMediaChange: index++;
+        case TFsNotification::EDriveName:   index++;
+        case TFsNotification::EVolumeName:  index++;
+        case TFsNotification::EDelete:      index++;
+        case TFsNotification::EAttribute:   index++;
+        case TFsNotification::ECreate:      index++;
+        case TFsNotification::ERename:      index++;
+        case TFsNotification::EFileChange:  // skip;
+        default: break;
+        }
+    __ASSERT_DEBUG(index < KNumRegisterableFilters, Fault(ENotificationFault));
+    return index;
+    }
+
+TInt CFsNotificationInfo::DriveNumber(const TPtrC& aPath)
+    {
+    if(aPath.Length() >= 1)
+        {
+        TInt drive;
+        TInt r = RFs::CharToDrive(aPath[0],drive);
+        if(r!=KErrNone)
+            return KErrNotFound;
+        return drive;
+        }
+    return KErrNotFound;
+    }
+
+//Get the attributes set and cleared
+void CFsNotificationInfo::Attributes(CFsMessageRequest& aRequest, TUint& aSet, TUint& aClear)
+    {
+    __PRINT(_L("CFsNotificationInfo::Attributes"));
+
+    TInt function = aRequest.Operation()->Function();
+    const RMessage2& msg = aRequest.Message();
+
+    //Client notification
+    switch(function)
+        {
+        case EFsFileSet:
+            {
+            aSet = msg.Int1();
+            aClear = msg.Int2();
+            break;
+            }
+        case EFsFileSetAtt:
+            {
+            aSet = msg.Int0();
+            aClear = msg.Int1();
+            break;
+            }
+        case EFsSetEntry:
+            {
+            aSet = msg.Int2();
+            aClear = msg.Int3();
+            break;
+            }
+        default:
+            {
+            ASSERT(0);
+            break;
+            }
+        }
+    }
+
+TInt64 CFsNotificationInfo::FileSize(CFsMessageRequest& aRequest)
+    {
+    CFileShare* share = NULL;
+    CFileCB* file = NULL;
+    GetFileFromScratch(&aRequest, share, file);
+    TInt64 size = file->CachedSize64();
+    return size;
+    }
+
+
+void CFsNotificationInfo::SetData(CFsMessageRequest* aRequest, CFsNotificationInfo* aNotificationInfo)
+    {
+    TInt function = aRequest->Operation()->Function();
+    
+    switch(function)
+        {
+        case EFsFileWrite:
+        case EFsFileWriteDirty:
+        case EFsFileSetSize:
+            {
+            aNotificationInfo->SetFilesize(FileSize(*aRequest));
+            break;
+            }
+        case EFsSetEntry:
+        case EFsFileSetAtt:
+        case EFsFileSet:
+            {
+            TUint set = 0;
+            TUint clear = 0;
+            Attributes(*aRequest,set,clear);
+            *(aNotificationInfo->Data())= MAKE_TUINT64(set,clear);
+            break;
+            }
+        default:
+            {
+            return;
+            }
+        }
+    }
+
+TInt CFsNotificationInfo::ValidateNotification(CFsNotificationInfo& aNotificationInfo)
+    {
+    //Validate UID
+    if(aNotificationInfo.Uid() == TUid::Null())
+        {
+        __ASSERT_DEBUG(false,User::Panic(_L("::ValidateNotification - Uid not set"),KErrArgument));
+        return KErrArgument;
+        }
+   
+    switch(aNotificationInfo.Function())
+        {
+        case EFsFileWrite:
+        case EFsFileWriteDirty:
+        case EFsFileSetSize:
+            {
+            if(*aNotificationInfo.Data() == -1)
+                {
+                __ASSERT_DEBUG(false,User::Panic(_L("::ValidateNotification - File size not set"),KErrArgument));
+                return KErrArgument;
+                }
+            if(!aNotificationInfo.Source().FullName().Length())
+                {
+                __ASSERT_DEBUG(false,User::Panic(_L("::ValidateNotification - Source Name not set"),KErrArgument));
+                return KErrArgument;
+                }
+            if(aNotificationInfo.NewName().FullName().Length())
+                {
+                __ASSERT_DEBUG(false,User::Panic(_L("::ValidateNotification - New Name set in err"),KErrArgument));
+                return KErrArgument;
+                }
+            break;
+            }
+        case EFsRename:
+        case EFsFileRename:
+        case EFsReplace:
+        case EFsSetVolume:
+        case EFsSetDriveName:
+            {
+            if(!aNotificationInfo.Source().FullName().Length())
+                {
+                __ASSERT_DEBUG(false,User::Panic(_L("::ValidateNotification - Source Name not set"),KErrArgument));
+                return KErrArgument;
+                }
+            if(!aNotificationInfo.NewName().FullName().Length())
+                {
+                __ASSERT_DEBUG(false,User::Panic(_L("::ValidateNotification - New Name not set"),KErrArgument));
+                return KErrArgument;
+                }
+            if(*aNotificationInfo.Data() != -1)
+                {
+                __ASSERT_DEBUG(false,User::Panic(_L("::ValidateNotification - Data set in err"),KErrArgument));
+                return KErrArgument;
+                }
+            break;
+            }
+        case EFsMkDir:
+        case EFsFileCreate:
+        case EFsFileReplace:
+        case EFsDelete:
+        case EFsRmDir:
+            {
+            if(!aNotificationInfo.Source().FullName().Length())
+                {
+                __ASSERT_DEBUG(false,User::Panic(_L("::ValidateNotification - Source Name not set"),KErrArgument));
+                return KErrArgument;
+                }
+            if(aNotificationInfo.NewName().FullName().Length())
+                {
+                __ASSERT_DEBUG(false,User::Panic(_L("::ValidateNotification - New Name set in err"),KErrArgument));
+                return KErrArgument;
+                }
+            if(*aNotificationInfo.Data() != -1)
+                {
+                __ASSERT_DEBUG(false,User::Panic(_L("::ValidateNotification - Data set in err"),KErrArgument));
+                return KErrArgument;
+                }
+            break;
+            }
+        case EFsFileSetAtt:
+        case EFsFileSet:
+        case EFsSetEntry:
+            {
+            if(!aNotificationInfo.Source().FullName().Length())
+                {
+                __ASSERT_DEBUG(false,User::Panic(_L("::ValidateNotification - Source Name not set"),KErrArgument));
+                return KErrArgument;
+                }
+            if(*aNotificationInfo.Data() == -1)
+                {
+                __ASSERT_DEBUG(false,User::Panic(_L("::ValidateNotification - Attributes not set"),KErrArgument));
+                return KErrArgument;
+                }
+            if(aNotificationInfo.NewName().FullName().Length())
+                {
+                __ASSERT_DEBUG(false,User::Panic(_L("::ValidateNotification - New Name set in err"),KErrArgument));
+                return KErrArgument;
+                }               
+            break;
+            }
+        case EFsDismountFileSystem:
+        case EFsMountFileSystem:
+        case EFsFormatNext:
+        case EFsRawDiskWrite:
+        case EFsMountFileSystemScan:
+            {
+            if(aNotificationInfo.NewName().FullName().Length())
+                {
+                __ASSERT_DEBUG(false,User::Panic(_L("::ValidateNotification - New Name set in err"),KErrArgument));
+                return KErrArgument;
+                }               
+            if(aNotificationInfo.Source().FullName().Length())
+                {
+                __ASSERT_DEBUG(false,User::Panic(_L("::ValidateNotification - Source Name set in err"),KErrArgument));
+                return KErrArgument;
+                }
+            if(*aNotificationInfo.Data() != -1)
+                {
+                __ASSERT_DEBUG(false,User::Panic(_L("::ValidateNotification - Data set in err"),KErrArgument));
+                return KErrArgument;
+                }
+            break;
+            }
+        default:
+            {
+            break;
+            }
+        }
+    return KErrNone;
+    }
+
+TUint CFsNotificationInfo::NotifyType(TInt aFunction)
+//
+//  Convert aFunction that caused the notification to a 
+//  value corresponding to the correct TNotifyType enum  
+//
+    {
+    switch (aFunction)
+        {
+        case EFsFileCreate:
+        case EFsFileReplace:
+        case EFsDelete:
+        case EFsReplace:
+        case EFsFileRename:
+            return(ENotifyFile|ENotifyEntry);   
+        case EFsMkDir:
+        case EFsRmDir:
+            return(ENotifyDir|ENotifyEntry);    
+        case EFsRename:                 
+            return(ENotifyDir|ENotifyFile|ENotifyEntry);                    
+        case EFsSetVolume:                  
+            return(ENotifyDisk|ENotifyEntry);   
+        case EFsFileSet:
+        case EFsFileSetAtt:
+        case EFsFileSetModified:
+        case EFsFileSetSize:
+        case EFsSetEntry:
+            return(ENotifyAttributes);  
+        case EFsFileWrite:
+        case EFsFileWriteDirty:
+            return(ENotifyWrite);   
+        case EFsRawDiskWrite:
+        case EFsLockDrive:
+        case EFsUnlockDrive:
+            return(ENotifyDisk);    
+        case EFsFileTemp:       
+        case EFsSetDriveName:
+            return(ENotifyAll); 
+        default:
+            return(0);
+        }
+    }
+
 void CNotifyInfo::Initialise(TInfoType aType,TRequestStatus* aStatus,const RMessagePtr2& aMessage,CSessionFs* aSession)
 //
 //
@@ -67,16 +919,16 @@
 	CNotifyInfo::Initialise(EStdChange,aStatus,aMessage,aSession);
 	}
 
-TUint CStdChangeInfo::RequestNotifyType(CFsRequest* aRequest)
+TUint CStdChangeInfo::RequestNotifyType(CFsNotificationInfo* aRequest)
 //
 // return notification type for the request
 //
 	{
-	TUint notifyType=aRequest->Operation()->NotifyType();
-	if(aRequest->Operation()->Function()==EFsRename)
+    TUint notifyType=CFsNotificationInfo::NotifyType(aRequest->Function());
+    if(aRequest->Function()==EFsRename)
 		{
 		__ASSERT_DEBUG(notifyType==(ENotifyDir|ENotifyFile|ENotifyEntry),Fault(EStdChangeRequestType));
-		if(aRequest->Src().NamePresent())
+        if(aRequest->Source().NamePresent())
 			notifyType=ENotifyFile|ENotifyEntry;
 		else
 			notifyType=ENotifyDir|ENotifyEntry;
@@ -84,12 +936,13 @@
 	return(notifyType);						
 	}
 
-TBool CStdChangeInfo::IsMatching(CFsRequest* aRequest)
+
+TBool CStdChangeInfo::IsMatching(CFsNotificationInfo* aNotificationInfo)
 //
 // return ETrue if operation type of request matches that of change notification
 //
-	{
-	if((iChangeType&ENotifyAll) || (iChangeType&aRequest->Operation()->NotifyType()))
+    {
+    if((iChangeType&ENotifyAll) || (iChangeType&CFsNotificationInfo::NotifyType(aNotificationInfo->Function())))
 		return(ETrue);
 	else
 		return(EFalse);
@@ -107,17 +960,17 @@
 	}
 
 
-TBool CExtChangeInfo::IsMatching(CFsRequest* aRequest)
+TBool CExtChangeInfo::IsMatching(CFsNotificationInfo* aRequest)
 //
 // return ETrue if operation notify type of request matches that of change notification
 // and paths match
 //
-	{
-	TInt function=aRequest->Operation()->Function();
+    {
+    TInt function=aRequest->Function();
 	//	if a rename occurred inform any requests if their path has been changed regardless of the notification type
 	if(function==EFsRename)				
 		{		
-		TBuf<KMaxFileName> renamePath=aRequest->Src().FullName().Mid(2);		
+        TBuf<KMaxFileName> renamePath=aRequest->Source().FullName();        
 		renamePath+=_L("*");
 		if (iName.MatchF(renamePath)!=KErrNotFound)	
 			return(ETrue);
@@ -127,18 +980,14 @@
 	//Special case where the dir the notifier is setup on has just been created
 	if(function==EFsMkDir)	
 		{		
-		TInt notDrive;
-		RFs::CharToDrive(aRequest->Src().Drive()[0],notDrive);	//can not fail as the drive letter has been parsed already
-		if(aRequest->Src().Path().MatchF(iName) == 0 && aRequest->DriveNumber() == notDrive)
+        if(aRequest->Source().Path().MatchF(iName) == 0)
 			return ETrue;
 		}
 	
-	//Special case where  the File the notifier is setup on has just been created by temp as the name is not known unti it has been created
+	//Special case where  the File the notifier is setup on has just been created by temp as the name is not known until it has been created
 	if(function==EFsRename||function==EFsFileOpen||function==EFsFileCreate||function==EFsFileReplace)
 		{
-		TInt notDrive;
-		RFs::CharToDrive(aRequest->Src().Drive()[0],notDrive);	//can not fail as the drive letter has been parsed already
-		if(aRequest->Src().FullName().Mid(2).MatchF(iName) == 0 && aRequest->DriveNumber() == notDrive)
+        if(aRequest->Source().FullName().MatchF(iName) == 0)
 			return ETrue;
 		}
 	
@@ -162,13 +1011,10 @@
 			TBuf<KMaxFileName> root=iName;
 			root+=_L("*");	
 			
-			// NB share may be NULL if file server has initiated a flush of the file cache
-			CFileShare* share;
-			CFileCB* fileCache;
-			GetFileFromScratch(aRequest, share, fileCache);
-			if (share && share->File().FileName().MatchF(root) != KErrNotFound)
-				return(ETrue);
-
+                if (aRequest->Source().FullName().MatchF(root) != KErrNotFound)
+                    {
+                    return(ETrue);
+                    }
 			}
 			break;
 			case EFsSetDriveName:
@@ -186,18 +1032,26 @@
 				TBuf<KMaxFileName> root = iName;
 				root+=_L("*");	
 				
-				if(aRequest->Src().FullName().Mid(2).MatchF(root)!=KErrNotFound)
+                if(aRequest->Source().FullName().MatchF(root)!=KErrNotFound)
 					return(ETrue);	
 				else if(function==EFsRename||function==EFsReplace||function==EFsFileRename)
 					{
 					// - rename/replace causes the file/path to disappear
-					if(aRequest->Dest().FullName().Mid(2).MatchF(root)!=KErrNotFound)
+				    TPtrC newName;
+				    if(aRequest->DestDriveIsSet())
+				        newName.Set(aRequest->NewName().FullName().Mid(2));
+				    else
+				        newName.Set(aRequest->NewName().FullName());
+                    if(newName.MatchF(root)!=KErrNotFound)
 						{
 						return(ETrue);
 						}
 
 					// - rename/replace causes the file/path to arrive
-					root=aRequest->Dest().FullName().Mid(2);
+                    if(aRequest->DestDriveIsSet())
+                        root=aRequest->NewName().FullName().Mid(2);
+                    else
+                        root=aRequest->NewName().FullName();
 					root+=_L("*");
 
 					if (iName.MatchF(root)!=KErrNotFound)
@@ -416,7 +1270,7 @@
 	iQLock.Signal();
 	}
 
-void TChangeQue::CheckChange(CFsRequest* aRequest)
+void TChangeQue::CheckChange(CFsNotificationInfo& aRequest)
 //
 // complete any notification in que that matches aRequest
 //
@@ -429,9 +1283,9 @@
 		__ASSERT_DEBUG(info->Type()==CNotifyInfo::EStdChange||info->Type()==CNotifyInfo::EExtChange,Fault(EChangeQueType));
 		TBool isMatching;
 		if(info->Type()==CNotifyInfo::EStdChange)
-			isMatching=((CStdChangeInfo*)info)->IsMatching(aRequest);
+			isMatching=((CStdChangeInfo*)info)->IsMatching(&aRequest);
 		else
-			isMatching=((CExtChangeInfo*)info)->IsMatching(aRequest);
+			isMatching=((CExtChangeInfo*)info)->IsMatching(&aRequest);
 		if(isMatching)
 			{
 			__PRINT1(_L("TChangeQue::CheckChange()-Matching info=0x%x"),info);
@@ -842,17 +1696,18 @@
 	return(KErrNone);
 	}
 
-void FsNotify::HandleChange(CFsRequest* aRequest,TInt aDrive)
+
+void FsNotify::HandleChange(CFsNotificationInfo& aNotificationInfo)
 //
 // Check whether any change notifications need to be completed due to aRequest on aDrive
 //
-	{
-	__PRINT2(_L("FsNotify::HandleChange() aRequest=0x%x, aDrive=%d"),aRequest,aDrive);
-	if(!aRequest->IsChangeNotify())
-		return;
-	iChangeQues[ChangeIndex(aDrive)].CheckChange(aRequest);
-	iChangeQues[ChangeIndex(KDriveInvalid)].CheckChange(aRequest);
-	}
+    {
+    __PRINT1(_L("FsNotify::HandleChange(TFsNotificationInfo) DriveNumber=%d"),aNotificationInfo.DriveNumber());
+    if(aNotificationInfo.Request() && !aNotificationInfo.Request()->IsChangeNotify())
+        return;
+    iChangeQues[ChangeIndex(aNotificationInfo.DriveNumber())].CheckChange(aNotificationInfo);
+    iChangeQues[ChangeIndex(KDriveInvalid)].CheckChange(aNotificationInfo);
+    }
 	
 
 void FsNotify::HandleDiskSpace(CFsRequest* aRequest,TInt aDrive)