sl@0: // Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies). sl@0: // All rights reserved. sl@0: // This component and the accompanying materials are made available sl@0: // under the terms of the License "Eclipse Public License v1.0" sl@0: // which accompanies this distribution, and is available sl@0: // at the URL "http://www.eclipse.org/legal/epl-v10.html". sl@0: // sl@0: // Initial Contributors: sl@0: // Nokia Corporation - initial contribution. sl@0: // sl@0: // Contributors: sl@0: // sl@0: // Description: sl@0: // f32\sfsrv\cl_notification.cpp sl@0: // sl@0: // sl@0: #include "cl_std.h" sl@0: #include "cl_notification.h" sl@0: sl@0: #ifdef SYMBIAN_F32_ENHANCED_CHANGE_NOTIFICATION sl@0: /* sl@0: * The order of the data in the buffer is: sl@0: * Word1 : NotificationSize (2 bytes) , PathSize (2 bytes) sl@0: * Word2 : NewNameSize (2 bytes) , NotificationType (2 bytes) sl@0: * Word3 : UID - NOT YET SUPPORTED sl@0: * Word(s) : Path (TText8) , [Any sub-class members] sl@0: * sl@0: * The notification size should be located at *this sl@0: */ sl@0: TInt TFsNotification::NotificationSize() const sl@0: { sl@0: TInt word1 = *(TInt*)this; sl@0: return (word1 >> 16); sl@0: } sl@0: sl@0: /* sl@0: * The order of the data in the buffer is: sl@0: * Word1 : NotificationSize (2 bytes) , PathSize (2 bytes) sl@0: * Word2 : NewNameSize (2 bytes) , NotificationType (2 bytes) sl@0: * Word3 : UID - NOT YET SUPPORTED sl@0: * Word(s) : Path (TText8) , [Any sub-class members] sl@0: * sl@0: * The notification type should be located at: sl@0: * *this + sizeof(NotificationSize) + sizeof(PathSize) + sizeof(NewNameSize) sl@0: */ sl@0: EXPORT_C TFsNotification::TFsNotificationType TFsNotification::NotificationType() const sl@0: { sl@0: TUint* word2 = PtrAdd((TUint*)this, sizeof(TUint)); sl@0: TFsNotificationType ret = (TFsNotificationType)(*word2 & 0x0000FFFF); sl@0: //Check it is a valid type sl@0: __ASSERT_DEBUG(!((TInt)ret & ~KNotificationValidFiltersMask) || (ret == EOverflow), Panic(ENotificationPanic)); sl@0: return ret; //Returns the lower 2 bytes of Word2 sl@0: } sl@0: sl@0: /* sl@0: * The order of the data in the buffer is: sl@0: * Word1 : NotificationSize (2 bytes) , PathSize (2 bytes) sl@0: * Word2 : NewNameSize (2 bytes) , NotificationType (2 bytes) sl@0: * Word3 : UID - NOT YET SUPPORTED sl@0: * Word(s) : Path (TText8) , [Any sub-class members] sl@0: * sl@0: * The path size should be located at *this + sizeof(NotificationSize) sl@0: */ sl@0: TInt TFsNotification::PathSize() const sl@0: { sl@0: //Notification of type EOverflow does not have a path associated with it sl@0: __ASSERT_DEBUG(NotificationType() != EOverflow,Panic(ENotificationPanic)); sl@0: TUint ret = (*(TUint*)this & 0x0000FFFF); //Returns the lower 2 bytes of Word1 sl@0: return (TInt)ret; sl@0: } sl@0: sl@0: /* sl@0: * The order of the data in the buffer is: sl@0: * Word1 : NotificationSize (2 bytes) , PathSize (2 bytes) sl@0: * Word2 : NewNameSize (2 bytes) , NotificationType (2 bytes) sl@0: * Word3 : UID - NOT YET SUPPORTED sl@0: * Word(s) : Path (TText8) , [Any sub-class members] sl@0: * sl@0: * The path should be located at: *this + KNotificationHeaderSize sl@0: */ sl@0: EXPORT_C TInt TFsNotification::Path(TPtrC& aPath) const sl@0: { sl@0: //Notification of type EOverflow does not have a path associated with it sl@0: if(NotificationType() == EOverflow) sl@0: return KErrNotSupported; sl@0: sl@0: TUint16* pathPtr = PtrAdd((TUint16*)this, KNotificationHeaderSize); sl@0: aPath.Set(pathPtr,PathSize()/2); sl@0: return KErrNone; sl@0: } sl@0: sl@0: /* sl@0: * The order of the data in the buffer is: sl@0: * Word1 : NotificationSize (2 bytes) , PathSize (2 bytes) sl@0: * Word2 : NewNameSize (2 bytes) , NotificationType (2 bytes) sl@0: * Word3 : UID - NOT YET SUPPORTED sl@0: * Word(s) : Path (TText8) , [Any sub-class members] sl@0: * sl@0: * The new name size should be located at: *this + sizeof(NotificationSize) + sizeof(PathSize) sl@0: */ sl@0: TInt TFsNotification::NewNameSize() const sl@0: { sl@0: //The only notifications containing a new name are ERename, EVolumeName and EDriveName sl@0: __ASSERT_DEBUG((NotificationType() == ERename || sl@0: NotificationType() == EVolumeName || sl@0: NotificationType() == EDriveName),Panic(ENotificationPanic)); sl@0: TInt* word2 = PtrAdd((TInt*)this, sizeof(TInt)); sl@0: return ((*word2) >> 16); sl@0: } sl@0: sl@0: /* sl@0: * The order of the data in the buffer is: sl@0: * Word1 : NotificationSize (2 bytes) , PathSize (2 bytes) sl@0: * Word2 : NewNameSize (2 bytes) , NotificationType (2 bytes) sl@0: * Word3 : UID - NOT YET SUPPORTED sl@0: * Word(s) : Path (TText8) , [Any sub-class members] sl@0: * sl@0: * The new name should be located at: *this + KNotificationHeaderSize + Align4(PathSize) sl@0: */ sl@0: EXPORT_C TInt TFsNotification::NewName(TPtrC& aNewName) const sl@0: { sl@0: //Only ERename, EVolumeName and EDriveName have second paths sl@0: //Notification of type EOverflow does not have a path associated with it sl@0: TFsNotificationType notificationType = NotificationType(); sl@0: if((notificationType != ERename && sl@0: notificationType != EVolumeName && sl@0: notificationType != EDriveName) || sl@0: notificationType == EOverflow) sl@0: { sl@0: return KErrNotSupported; sl@0: } sl@0: sl@0: TUint16* pathPtr = PtrAdd((TUint16*)this, KNotificationHeaderSize + Align4(PathSize())); sl@0: aNewName.Set(pathPtr,NewNameSize()/2); sl@0: return KErrNone; sl@0: } sl@0: sl@0: /* sl@0: * The order of the data in the buffer is: sl@0: * Word1 : NotificationSize (2 bytes) , PathSize (2 bytes) sl@0: * Word2 : NewNameSize (2 bytes) , NotificationType (2 bytes) sl@0: * Word3 : UID - NOT YET SUPPORTED sl@0: * Word(s) : Path (TText8) , [Any sub-class members] sl@0: * sl@0: * The attribute should be located at: *this + KNotificationHeaderSize + Align4(PathSize) sl@0: */ sl@0: EXPORT_C TInt TFsNotification::Attributes(TUint& aSetAtt, TUint& aClearAtt) const sl@0: { sl@0: if(NotificationType() != EAttribute) sl@0: return KErrNotSupported; sl@0: sl@0: TUint* clearAttptr = PtrAdd((TUint*)this, KNotificationHeaderSize + Align4(PathSize())); sl@0: aClearAtt = *clearAttptr; sl@0: aSetAtt = *PtrAdd((TUint*)clearAttptr, sizeof(TUint)); sl@0: return KErrNone; sl@0: } sl@0: sl@0: /* sl@0: * The order of the data in the buffer is: sl@0: * Word1 : NotificationSize (2 bytes) , PathSize (2 bytes) sl@0: * Word2 : NewNameSize (2 bytes) , NotificationType (2 bytes) sl@0: * Word3 : UID - NOT YET SUPPORTED sl@0: * Word(s) : Path (TText8) , [Any sub-class members] sl@0: * sl@0: * The size should be located at: *this + KNotificationHeaderSize + Align4(PathSize) sl@0: */ sl@0: EXPORT_C TInt TFsNotification::FileSize(TInt64& aSize) const sl@0: { sl@0: if(NotificationType() != EFileChange) sl@0: return KErrNotSupported; sl@0: sl@0: aSize = *PtrAdd((TInt64*)this, KNotificationHeaderSize + Align4(PathSize())); sl@0: return KErrNone; sl@0: } sl@0: sl@0: /* sl@0: * The order of the data in the buffer is: sl@0: * Word1 : NotificationSize (2 bytes) , PathSize (2 bytes) sl@0: * Word2 : NewNameSize (2 bytes) , NotificationType (2 bytes) sl@0: * Word3 : UID sl@0: * Word(s) : Path (TText8) , [Any sub-class members] sl@0: sl@0: EXPORT_C TInt TFsNotification::DriveNumber(TInt& aDriveNumber) const sl@0: { sl@0: TPtrC path(NULL,0); sl@0: TInt r = Path(path); sl@0: if(r == KErrNone) sl@0: { sl@0: if(path.Length() >= 2 && ((TChar)path[1]==(TChar)':')) sl@0: { sl@0: r = RFs::CharToDrive(path[0],aDriveNumber); sl@0: } sl@0: } sl@0: return r; sl@0: } sl@0: */ sl@0: sl@0: /* sl@0: * The order of the data in the buffer is: sl@0: * Word1 : NotificationSize (2 bytes) , PathSize (2 bytes) sl@0: * Word2 : NewNameSize (2 bytes) , NotificationType (2 bytes) sl@0: * Word3 : UID sl@0: * Word(s) : Path (TText8) , [Any sub-class members] sl@0: sl@0: EXPORT_C TInt TFsNotification::UID(TUid& aUID) const sl@0: { sl@0: TUint* word3 = PtrAdd((TUint*)this, sizeof(TUint)*2); sl@0: aUID.iUid = *word3; sl@0: return KErrNone; sl@0: } sl@0: */ sl@0: sl@0: sl@0: CFsNotificationList* CFsNotificationList::NewL(TInt aBufferSize) sl@0: { sl@0: CFsNotificationList* self = new(ELeave) CFsNotificationList; sl@0: CleanupStack::PushL(self); sl@0: self->iBuf = HBufC8::NewL(aBufferSize); sl@0: self->iBufferPtr.Set((TUint8*)self->iBuf->Ptr(),0,self->iBuf->Des().MaxSize()); sl@0: CleanupStack::Pop(self); sl@0: return self; sl@0: } sl@0: sl@0: CFsNotificationList::CFsNotificationList() sl@0: : iTailPckg(iTail), iBufferPtr(NULL,0) sl@0: { sl@0: } sl@0: sl@0: CFsNotificationList::~CFsNotificationList() sl@0: { sl@0: delete iBuf; sl@0: } sl@0: sl@0: TInt CFsNotificationList::BufferSize() const sl@0: { sl@0: return iBuf->Size(); sl@0: } sl@0: sl@0: const TFsNotification * CFsNotificationList::NextNotification() sl@0: { sl@0: TFsNotification* notification; sl@0: sl@0: if(iHead == iTail) sl@0: { sl@0: return NULL; sl@0: } sl@0: TUint* startptr = (TUint*)iBuf->Ptr(); sl@0: TUint* nptr = PtrAdd(startptr, iHead); sl@0: TInt bufferSize = iBuf->Des().MaxSize(); sl@0: TUint* endOfBuffer = PtrAdd(startptr, bufferSize); sl@0: sl@0: if(*nptr == KNotificationBufferFiller || nptr == endOfBuffer) sl@0: { sl@0: iHead = 0; sl@0: notification = (TFsNotification*)startptr; sl@0: } sl@0: else sl@0: { sl@0: notification = (TFsNotification*)nptr; sl@0: } sl@0: iHead += notification->NotificationSize(); sl@0: if(iHead == bufferSize) sl@0: iHead = 0; sl@0: sl@0: return notification; sl@0: } sl@0: sl@0: sl@0: EXPORT_C CFsNotify* CFsNotify::NewL(RFs& aFs, TInt aBufferSize) sl@0: { sl@0: CFsNotify* self=new(ELeave) CFsNotify; sl@0: CleanupStack::PushL(self); sl@0: sl@0: //Making sure buffer size is at least minimally large and not too big sl@0: if(aBufferSize > (KMaxTInt/2)) sl@0: { sl@0: User::Leave(KErrArgument); sl@0: } sl@0: else if(aBufferSize < KMinNotificationBufferSize) sl@0: { sl@0: aBufferSize = KMinNotificationBufferSize; sl@0: } sl@0: sl@0: self->ConstructL(aFs, Align4(aBufferSize)); sl@0: CleanupStack::Pop(self); sl@0: return self; sl@0: } sl@0: sl@0: void CFsNotify::ConstructL(RFs& aFs,TInt aBufferSize) sl@0: { sl@0: iBody = new(ELeave) CFsNotifyBody(); sl@0: iBody->iBuffer = CFsNotificationList::NewL(aBufferSize); sl@0: User::LeaveIfError(iBody->iFsNotify.Open(aFs,iBody->iBuffer,iBody->iBufferStatus)); sl@0: } sl@0: sl@0: CFsNotify::CFsNotify() sl@0: { sl@0: } sl@0: sl@0: EXPORT_C CFsNotify::~CFsNotify() sl@0: { sl@0: if(iBody) sl@0: { sl@0: if(iBody->iBuffer) sl@0: { sl@0: iBody->iBuffer->iTail = 0; sl@0: iBody->iBuffer->iHead = 0; sl@0: iBody->iFsNotify.Close(); sl@0: delete iBody->iBuffer; sl@0: } sl@0: } sl@0: delete iBody; sl@0: } sl@0: sl@0: CFsNotifyBody::CFsNotifyBody() sl@0: { sl@0: } sl@0: sl@0: CFsNotifyBody::~CFsNotifyBody() sl@0: { sl@0: } sl@0: sl@0: EXPORT_C TInt CFsNotify::AddNotification(TUint aNotificationType, const TDesC& aPath, const TDesC& aFilename) sl@0: { sl@0: if(aNotificationType == 0 || (aPath.Length() <= 0 && aFilename.Length() <= 0)) sl@0: return KErrArgument; sl@0: sl@0: return iBody->iFsNotify.AddNotification(aNotificationType, aPath, aFilename); sl@0: } sl@0: sl@0: //Removes notification request, does not close session sl@0: EXPORT_C TInt CFsNotify::RemoveNotifications() sl@0: { sl@0: return iBody->iFsNotify.RemoveNotifications(); sl@0: } sl@0: sl@0: EXPORT_C TInt CFsNotify::RequestNotifications(TRequestStatus& aStatus) sl@0: { sl@0: if(aStatus == KRequestPending || ((iBody->iClientStatus != NULL) && (*iBody->iClientStatus == KRequestPending))) sl@0: return KErrInUse; sl@0: sl@0: iBody->iClientStatus = &aStatus; sl@0: //Read the new notifications which will start at tail. sl@0: //(Also this forbids user access outside permitted range) sl@0: iBody->iBuffer->iHead = iBody->iBuffer->iTail; sl@0: iBody->iFsNotify.RequestNotifications(aStatus, iBody->iBuffer->iTailPckg); sl@0: return KErrNone; sl@0: } sl@0: sl@0: //Cancels notification request, does not close session sl@0: EXPORT_C TInt CFsNotify::CancelNotifications(TRequestStatus& aStatus) sl@0: { sl@0: if(aStatus != KRequestPending || &aStatus != iBody->iClientStatus) sl@0: return KErrInUse; sl@0: sl@0: TInt r = iBody->iFsNotify.CancelNotifications(); sl@0: aStatus = !KRequestPending; sl@0: iBody->iBuffer->iHead = 0; sl@0: iBody->iBuffer->iTail = 0; sl@0: return r; sl@0: } sl@0: sl@0: EXPORT_C const TFsNotification * CFsNotify::NextNotification() sl@0: { sl@0: return iBody->iBuffer->NextNotification(); sl@0: } sl@0: sl@0: sl@0: TInt RFsNotify::Open(RFs& aFs, CFsNotificationList* aBuffer, TRequestStatus& aBufferStatus) sl@0: { sl@0: if(aBuffer == NULL || aBuffer->iBuf == NULL || &aFs == NULL || &aBufferStatus==NULL) sl@0: return KErrArgument; sl@0: sl@0: TInt err = CreateSubSession(aFs,EFsNotificationOpen); sl@0: if (err == KErrNone) sl@0: { sl@0: aBufferStatus = KRequestPending; sl@0: //memclr((TUint8*)aBuffer->iBuf->Ptr(),aBuffer->iBuf->Des().MaxSize()); sl@0: SendReceive(EFsNotificationBuffer, TIpcArgs(&aBuffer->iBufferPtr,aBuffer->iBuf->Des().MaxSize()), aBufferStatus); sl@0: } sl@0: return err; sl@0: } sl@0: sl@0: void RFsNotify::Close() sl@0: { sl@0: CloseSubSession(EFsNotificationSubClose); sl@0: } sl@0: sl@0: /* sl@0: [Re]Issues notification request sl@0: Updates buffer, if supplied. sl@0: sl@0: @return - last readable index of buffer. sl@0: */ sl@0: void RFsNotify::RequestNotifications(TRequestStatus& aStatus, TPckg& aTailPckg) sl@0: { sl@0: aStatus = KRequestPending; sl@0: SendReceive(EFsNotificationRequest,TIpcArgs(&aTailPckg),aStatus); sl@0: } sl@0: sl@0: TInt RFsNotify::CancelNotifications() sl@0: { sl@0: //there can only be one outstanding notification request at a time sl@0: return (SendReceive(EFsNotificationCancel)); sl@0: } sl@0: sl@0: //Adds notification filter sl@0: TInt RFsNotify::AddNotification(TUint aNotificationType, const TDesC& aPath, const TDesC& aFilename) sl@0: { sl@0: if(aNotificationType == 0 || (aPath.Length() <= 0 && aFilename.Length() <= 0)) sl@0: return KErrArgument; sl@0: sl@0: return (SendReceive(EFsNotificationAdd,TIpcArgs(aNotificationType,&aPath,&aFilename))); sl@0: } sl@0: sl@0: //Removes request, does not close session sl@0: TInt RFsNotify::RemoveNotifications() sl@0: { sl@0: return(SendReceive(EFsNotificationRemove)); sl@0: } sl@0: #else //SYMBIAN_F32_ENHANCED_CHANGE_NOTIFICATION sl@0: sl@0: EXPORT_C TFsNotification::TFsNotificationType TFsNotification::NotificationType() const sl@0: { sl@0: Panic(ENotificationPanic); sl@0: return (TFsNotification::TFsNotificationType)0; sl@0: } sl@0: sl@0: EXPORT_C TInt TFsNotification::Path(TPtrC&) const sl@0: { sl@0: Panic(ENotificationPanic); sl@0: return KErrNotSupported; sl@0: } sl@0: sl@0: EXPORT_C TInt TFsNotification::NewName(TPtrC&) const sl@0: { sl@0: Panic(ENotificationPanic); sl@0: return KErrNotSupported; sl@0: } sl@0: sl@0: EXPORT_C TInt TFsNotification::Attributes(TUint&,TUint&) const sl@0: { sl@0: Panic(ENotificationPanic); sl@0: return KErrNotSupported; sl@0: } sl@0: sl@0: EXPORT_C TInt TFsNotification::FileSize(TInt64&) const sl@0: { sl@0: Panic(ENotificationPanic); sl@0: return KErrNotSupported; sl@0: } sl@0: sl@0: /* sl@0: EXPORT_C TInt TFsNotification::DriveNumber(TInt&) const sl@0: { sl@0: Panic(ENotificationPanic); sl@0: return KErrNotSupported; sl@0: } sl@0: sl@0: EXPORT_C TInt TFsNotification::UID(TUid& aUID) const sl@0: { sl@0: Panic(ENotificationPanic); sl@0: return KErrNotSupported; sl@0: } sl@0: */ sl@0: sl@0: EXPORT_C CFsNotify* CFsNotify::NewL(RFs& , TInt) sl@0: { sl@0: Panic(ENotificationPanic); sl@0: User::Leave(KErrNotSupported); sl@0: return NULL; sl@0: } sl@0: sl@0: EXPORT_C CFsNotify::~CFsNotify() sl@0: { sl@0: Panic(ENotificationPanic); sl@0: } sl@0: sl@0: EXPORT_C TInt CFsNotify::AddNotification(TUint, const TDesC&, const TDesC&) sl@0: { sl@0: Panic(ENotificationPanic); sl@0: return KErrNotSupported; sl@0: } sl@0: sl@0: EXPORT_C TInt CFsNotify::RemoveNotifications() sl@0: { sl@0: Panic(ENotificationPanic); sl@0: return KErrNotSupported; sl@0: } sl@0: sl@0: EXPORT_C TInt CFsNotify::RequestNotifications(TRequestStatus&) sl@0: { sl@0: Panic(ENotificationPanic); sl@0: return KErrNotSupported; sl@0: } sl@0: sl@0: EXPORT_C TInt CFsNotify::CancelNotifications(TRequestStatus&) sl@0: { sl@0: Panic(ENotificationPanic); sl@0: return KErrNotSupported; sl@0: } sl@0: sl@0: EXPORT_C const TFsNotification * CFsNotify::NextNotification() sl@0: { sl@0: Panic(ENotificationPanic); sl@0: return NULL; sl@0: } sl@0: sl@0: CFsNotificationList::~CFsNotificationList() sl@0: { sl@0: Panic(ENotificationPanic); sl@0: } sl@0: sl@0: CFsNotifyBody::CFsNotifyBody() sl@0: { sl@0: Panic(ENotificationPanic); sl@0: } sl@0: sl@0: CFsNotifyBody::~CFsNotifyBody() sl@0: { sl@0: Panic(ENotificationPanic); sl@0: } sl@0: sl@0: #endif //SYMBIAN_F32_ENHANCED_CHANGE_NOTIFICATION sl@0: