1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000
1.2 +++ b/os/kernelhwsrv/userlibandfileserver/fileserver/sfsrv/cl_notification.cpp Fri Jun 15 03:10:57 2012 +0200
1.3 @@ -0,0 +1,525 @@
1.4 +// Copyright (c) 2008-2009 Nokia Corporation and/or its subsidiary(-ies).
1.5 +// All rights reserved.
1.6 +// This component and the accompanying materials are made available
1.7 +// under the terms of the License "Eclipse Public License v1.0"
1.8 +// which accompanies this distribution, and is available
1.9 +// at the URL "http://www.eclipse.org/legal/epl-v10.html".
1.10 +//
1.11 +// Initial Contributors:
1.12 +// Nokia Corporation - initial contribution.
1.13 +//
1.14 +// Contributors:
1.15 +//
1.16 +// Description:
1.17 +// f32\sfsrv\cl_notification.cpp
1.18 +//
1.19 +//
1.20 +#include "cl_std.h"
1.21 +#include "cl_notification.h"
1.22 +
1.23 +#ifdef SYMBIAN_F32_ENHANCED_CHANGE_NOTIFICATION
1.24 +/*
1.25 + * The order of the data in the buffer is:
1.26 + * Word1 : NotificationSize (2 bytes) , PathSize (2 bytes)
1.27 + * Word2 : NewNameSize (2 bytes) , NotificationType (2 bytes)
1.28 + * Word3 : UID - NOT YET SUPPORTED
1.29 + * Word(s) : Path (TText8) , [Any sub-class members]
1.30 + *
1.31 + * The notification size should be located at *this
1.32 + */
1.33 +TInt TFsNotification::NotificationSize() const
1.34 + {
1.35 + TInt word1 = *(TInt*)this;
1.36 + return (word1 >> 16);
1.37 + }
1.38 +
1.39 +/*
1.40 + * The order of the data in the buffer is:
1.41 + * Word1 : NotificationSize (2 bytes) , PathSize (2 bytes)
1.42 + * Word2 : NewNameSize (2 bytes) , NotificationType (2 bytes)
1.43 + * Word3 : UID - NOT YET SUPPORTED
1.44 + * Word(s) : Path (TText8) , [Any sub-class members]
1.45 + *
1.46 + * The notification type should be located at:
1.47 + * *this + sizeof(NotificationSize) + sizeof(PathSize) + sizeof(NewNameSize)
1.48 + */
1.49 +EXPORT_C TFsNotification::TFsNotificationType TFsNotification::NotificationType() const
1.50 + {
1.51 + TUint* word2 = PtrAdd((TUint*)this, sizeof(TUint));
1.52 + TFsNotificationType ret = (TFsNotificationType)(*word2 & 0x0000FFFF);
1.53 + //Check it is a valid type
1.54 + __ASSERT_DEBUG(!((TInt)ret & ~KNotificationValidFiltersMask) || (ret == EOverflow), Panic(ENotificationPanic));
1.55 + return ret; //Returns the lower 2 bytes of Word2
1.56 + }
1.57 +
1.58 +/*
1.59 + * The order of the data in the buffer is:
1.60 + * Word1 : NotificationSize (2 bytes) , PathSize (2 bytes)
1.61 + * Word2 : NewNameSize (2 bytes) , NotificationType (2 bytes)
1.62 + * Word3 : UID - NOT YET SUPPORTED
1.63 + * Word(s) : Path (TText8) , [Any sub-class members]
1.64 + *
1.65 + * The path size should be located at *this + sizeof(NotificationSize)
1.66 + */
1.67 +TInt TFsNotification::PathSize() const
1.68 + {
1.69 + //Notification of type EOverflow does not have a path associated with it
1.70 + __ASSERT_DEBUG(NotificationType() != EOverflow,Panic(ENotificationPanic));
1.71 + TUint ret = (*(TUint*)this & 0x0000FFFF); //Returns the lower 2 bytes of Word1
1.72 + return (TInt)ret;
1.73 + }
1.74 +
1.75 +/*
1.76 + * The order of the data in the buffer is:
1.77 + * Word1 : NotificationSize (2 bytes) , PathSize (2 bytes)
1.78 + * Word2 : NewNameSize (2 bytes) , NotificationType (2 bytes)
1.79 + * Word3 : UID - NOT YET SUPPORTED
1.80 + * Word(s) : Path (TText8) , [Any sub-class members]
1.81 + *
1.82 + * The path should be located at: *this + KNotificationHeaderSize
1.83 + */
1.84 +EXPORT_C TInt TFsNotification::Path(TPtrC& aPath) const
1.85 + {
1.86 + //Notification of type EOverflow does not have a path associated with it
1.87 + if(NotificationType() == EOverflow)
1.88 + return KErrNotSupported;
1.89 +
1.90 + TUint16* pathPtr = PtrAdd((TUint16*)this, KNotificationHeaderSize);
1.91 + aPath.Set(pathPtr,PathSize()/2);
1.92 + return KErrNone;
1.93 + }
1.94 +
1.95 +/*
1.96 + * The order of the data in the buffer is:
1.97 + * Word1 : NotificationSize (2 bytes) , PathSize (2 bytes)
1.98 + * Word2 : NewNameSize (2 bytes) , NotificationType (2 bytes)
1.99 + * Word3 : UID - NOT YET SUPPORTED
1.100 + * Word(s) : Path (TText8) , [Any sub-class members]
1.101 + *
1.102 + * The new name size should be located at: *this + sizeof(NotificationSize) + sizeof(PathSize)
1.103 + */
1.104 +TInt TFsNotification::NewNameSize() const
1.105 + {
1.106 + //The only notifications containing a new name are ERename, EVolumeName and EDriveName
1.107 + __ASSERT_DEBUG((NotificationType() == ERename ||
1.108 + NotificationType() == EVolumeName ||
1.109 + NotificationType() == EDriveName),Panic(ENotificationPanic));
1.110 + TInt* word2 = PtrAdd((TInt*)this, sizeof(TInt));
1.111 + return ((*word2) >> 16);
1.112 + }
1.113 +
1.114 +/*
1.115 + * The order of the data in the buffer is:
1.116 + * Word1 : NotificationSize (2 bytes) , PathSize (2 bytes)
1.117 + * Word2 : NewNameSize (2 bytes) , NotificationType (2 bytes)
1.118 + * Word3 : UID - NOT YET SUPPORTED
1.119 + * Word(s) : Path (TText8) , [Any sub-class members]
1.120 + *
1.121 + * The new name should be located at: *this + KNotificationHeaderSize + Align4(PathSize)
1.122 + */
1.123 +EXPORT_C TInt TFsNotification::NewName(TPtrC& aNewName) const
1.124 + {
1.125 + //Only ERename, EVolumeName and EDriveName have second paths
1.126 + //Notification of type EOverflow does not have a path associated with it
1.127 + TFsNotificationType notificationType = NotificationType();
1.128 + if((notificationType != ERename &&
1.129 + notificationType != EVolumeName &&
1.130 + notificationType != EDriveName) ||
1.131 + notificationType == EOverflow)
1.132 + {
1.133 + return KErrNotSupported;
1.134 + }
1.135 +
1.136 + TUint16* pathPtr = PtrAdd((TUint16*)this, KNotificationHeaderSize + Align4(PathSize()));
1.137 + aNewName.Set(pathPtr,NewNameSize()/2);
1.138 + return KErrNone;
1.139 + }
1.140 +
1.141 +/*
1.142 + * The order of the data in the buffer is:
1.143 + * Word1 : NotificationSize (2 bytes) , PathSize (2 bytes)
1.144 + * Word2 : NewNameSize (2 bytes) , NotificationType (2 bytes)
1.145 + * Word3 : UID - NOT YET SUPPORTED
1.146 + * Word(s) : Path (TText8) , [Any sub-class members]
1.147 + *
1.148 + * The attribute should be located at: *this + KNotificationHeaderSize + Align4(PathSize)
1.149 + */
1.150 +EXPORT_C TInt TFsNotification::Attributes(TUint& aSetAtt, TUint& aClearAtt) const
1.151 + {
1.152 + if(NotificationType() != EAttribute)
1.153 + return KErrNotSupported;
1.154 +
1.155 + TUint* clearAttptr = PtrAdd((TUint*)this, KNotificationHeaderSize + Align4(PathSize()));
1.156 + aClearAtt = *clearAttptr;
1.157 + aSetAtt = *PtrAdd((TUint*)clearAttptr, sizeof(TUint));
1.158 + return KErrNone;
1.159 + }
1.160 +
1.161 +/*
1.162 + * The order of the data in the buffer is:
1.163 + * Word1 : NotificationSize (2 bytes) , PathSize (2 bytes)
1.164 + * Word2 : NewNameSize (2 bytes) , NotificationType (2 bytes)
1.165 + * Word3 : UID - NOT YET SUPPORTED
1.166 + * Word(s) : Path (TText8) , [Any sub-class members]
1.167 + *
1.168 + * The size should be located at: *this + KNotificationHeaderSize + Align4(PathSize)
1.169 + */
1.170 +EXPORT_C TInt TFsNotification::FileSize(TInt64& aSize) const
1.171 + {
1.172 + if(NotificationType() != EFileChange)
1.173 + return KErrNotSupported;
1.174 +
1.175 + aSize = *PtrAdd((TInt64*)this, KNotificationHeaderSize + Align4(PathSize()));
1.176 + return KErrNone;
1.177 + }
1.178 +
1.179 +/*
1.180 + * The order of the data in the buffer is:
1.181 + * Word1 : NotificationSize (2 bytes) , PathSize (2 bytes)
1.182 + * Word2 : NewNameSize (2 bytes) , NotificationType (2 bytes)
1.183 + * Word3 : UID
1.184 + * Word(s) : Path (TText8) , [Any sub-class members]
1.185 +
1.186 +EXPORT_C TInt TFsNotification::DriveNumber(TInt& aDriveNumber) const
1.187 + {
1.188 + TPtrC path(NULL,0);
1.189 + TInt r = Path(path);
1.190 + if(r == KErrNone)
1.191 + {
1.192 + if(path.Length() >= 2 && ((TChar)path[1]==(TChar)':'))
1.193 + {
1.194 + r = RFs::CharToDrive(path[0],aDriveNumber);
1.195 + }
1.196 + }
1.197 + return r;
1.198 + }
1.199 + */
1.200 +
1.201 +/*
1.202 + * The order of the data in the buffer is:
1.203 + * Word1 : NotificationSize (2 bytes) , PathSize (2 bytes)
1.204 + * Word2 : NewNameSize (2 bytes) , NotificationType (2 bytes)
1.205 + * Word3 : UID
1.206 + * Word(s) : Path (TText8) , [Any sub-class members]
1.207 +
1.208 +EXPORT_C TInt TFsNotification::UID(TUid& aUID) const
1.209 + {
1.210 + TUint* word3 = PtrAdd((TUint*)this, sizeof(TUint)*2);
1.211 + aUID.iUid = *word3;
1.212 + return KErrNone;
1.213 + }
1.214 + */
1.215 +
1.216 +
1.217 +CFsNotificationList* CFsNotificationList::NewL(TInt aBufferSize)
1.218 + {
1.219 + CFsNotificationList* self = new(ELeave) CFsNotificationList;
1.220 + CleanupStack::PushL(self);
1.221 + self->iBuf = HBufC8::NewL(aBufferSize);
1.222 + self->iBufferPtr.Set((TUint8*)self->iBuf->Ptr(),0,self->iBuf->Des().MaxSize());
1.223 + CleanupStack::Pop(self);
1.224 + return self;
1.225 + }
1.226 +
1.227 +CFsNotificationList::CFsNotificationList()
1.228 +: iTailPckg(iTail), iBufferPtr(NULL,0)
1.229 + {
1.230 + }
1.231 +
1.232 +CFsNotificationList::~CFsNotificationList()
1.233 + {
1.234 + delete iBuf;
1.235 + }
1.236 +
1.237 +TInt CFsNotificationList::BufferSize() const
1.238 + {
1.239 + return iBuf->Size();
1.240 + }
1.241 +
1.242 +const TFsNotification * CFsNotificationList::NextNotification()
1.243 + {
1.244 + TFsNotification* notification;
1.245 +
1.246 + if(iHead == iTail)
1.247 + {
1.248 + return NULL;
1.249 + }
1.250 + TUint* startptr = (TUint*)iBuf->Ptr();
1.251 + TUint* nptr = PtrAdd(startptr, iHead);
1.252 + TInt bufferSize = iBuf->Des().MaxSize();
1.253 + TUint* endOfBuffer = PtrAdd(startptr, bufferSize);
1.254 +
1.255 + if(*nptr == KNotificationBufferFiller || nptr == endOfBuffer)
1.256 + {
1.257 + iHead = 0;
1.258 + notification = (TFsNotification*)startptr;
1.259 + }
1.260 + else
1.261 + {
1.262 + notification = (TFsNotification*)nptr;
1.263 + }
1.264 + iHead += notification->NotificationSize();
1.265 + if(iHead == bufferSize)
1.266 + iHead = 0;
1.267 +
1.268 + return notification;
1.269 + }
1.270 +
1.271 +
1.272 +EXPORT_C CFsNotify* CFsNotify::NewL(RFs& aFs, TInt aBufferSize)
1.273 + {
1.274 + CFsNotify* self=new(ELeave) CFsNotify;
1.275 + CleanupStack::PushL(self);
1.276 +
1.277 + //Making sure buffer size is at least minimally large and not too big
1.278 + if(aBufferSize > (KMaxTInt/2))
1.279 + {
1.280 + User::Leave(KErrArgument);
1.281 + }
1.282 + else if(aBufferSize < KMinNotificationBufferSize)
1.283 + {
1.284 + aBufferSize = KMinNotificationBufferSize;
1.285 + }
1.286 +
1.287 + self->ConstructL(aFs, Align4(aBufferSize));
1.288 + CleanupStack::Pop(self);
1.289 + return self;
1.290 + }
1.291 +
1.292 +void CFsNotify::ConstructL(RFs& aFs,TInt aBufferSize)
1.293 + {
1.294 + iBody = new(ELeave) CFsNotifyBody();
1.295 + iBody->iBuffer = CFsNotificationList::NewL(aBufferSize);
1.296 + User::LeaveIfError(iBody->iFsNotify.Open(aFs,iBody->iBuffer,iBody->iBufferStatus));
1.297 + }
1.298 +
1.299 +CFsNotify::CFsNotify()
1.300 + {
1.301 + }
1.302 +
1.303 +EXPORT_C CFsNotify::~CFsNotify()
1.304 + {
1.305 + if(iBody)
1.306 + {
1.307 + if(iBody->iBuffer)
1.308 + {
1.309 + iBody->iBuffer->iTail = 0;
1.310 + iBody->iBuffer->iHead = 0;
1.311 + iBody->iFsNotify.Close();
1.312 + delete iBody->iBuffer;
1.313 + }
1.314 + }
1.315 + delete iBody;
1.316 + }
1.317 +
1.318 +CFsNotifyBody::CFsNotifyBody()
1.319 + {
1.320 + }
1.321 +
1.322 +CFsNotifyBody::~CFsNotifyBody()
1.323 + {
1.324 + }
1.325 +
1.326 +EXPORT_C TInt CFsNotify::AddNotification(TUint aNotificationType, const TDesC& aPath, const TDesC& aFilename)
1.327 + {
1.328 + if(aNotificationType == 0 || (aPath.Length() <= 0 && aFilename.Length() <= 0))
1.329 + return KErrArgument;
1.330 +
1.331 + return iBody->iFsNotify.AddNotification(aNotificationType, aPath, aFilename);
1.332 + }
1.333 +
1.334 +//Removes notification request, does not close session
1.335 +EXPORT_C TInt CFsNotify::RemoveNotifications()
1.336 + {
1.337 + return iBody->iFsNotify.RemoveNotifications();
1.338 + }
1.339 +
1.340 +EXPORT_C TInt CFsNotify::RequestNotifications(TRequestStatus& aStatus)
1.341 + {
1.342 + if(aStatus == KRequestPending || ((iBody->iClientStatus != NULL) && (*iBody->iClientStatus == KRequestPending)))
1.343 + return KErrInUse;
1.344 +
1.345 + iBody->iClientStatus = &aStatus;
1.346 + //Read the new notifications which will start at tail.
1.347 + //(Also this forbids user access outside permitted range)
1.348 + iBody->iBuffer->iHead = iBody->iBuffer->iTail;
1.349 + iBody->iFsNotify.RequestNotifications(aStatus, iBody->iBuffer->iTailPckg);
1.350 + return KErrNone;
1.351 + }
1.352 +
1.353 +//Cancels notification request, does not close session
1.354 +EXPORT_C TInt CFsNotify::CancelNotifications(TRequestStatus& aStatus)
1.355 + {
1.356 + if(aStatus != KRequestPending || &aStatus != iBody->iClientStatus)
1.357 + return KErrInUse;
1.358 +
1.359 + TInt r = iBody->iFsNotify.CancelNotifications();
1.360 + aStatus = !KRequestPending;
1.361 + iBody->iBuffer->iHead = 0;
1.362 + iBody->iBuffer->iTail = 0;
1.363 + return r;
1.364 + }
1.365 +
1.366 +EXPORT_C const TFsNotification * CFsNotify::NextNotification()
1.367 + {
1.368 + return iBody->iBuffer->NextNotification();
1.369 + }
1.370 +
1.371 +
1.372 +TInt RFsNotify::Open(RFs& aFs, CFsNotificationList* aBuffer, TRequestStatus& aBufferStatus)
1.373 + {
1.374 + if(aBuffer == NULL || aBuffer->iBuf == NULL || &aFs == NULL || &aBufferStatus==NULL)
1.375 + return KErrArgument;
1.376 +
1.377 + TInt err = CreateSubSession(aFs,EFsNotificationOpen);
1.378 + if (err == KErrNone)
1.379 + {
1.380 + aBufferStatus = KRequestPending;
1.381 + //memclr((TUint8*)aBuffer->iBuf->Ptr(),aBuffer->iBuf->Des().MaxSize());
1.382 + SendReceive(EFsNotificationBuffer, TIpcArgs(&aBuffer->iBufferPtr,aBuffer->iBuf->Des().MaxSize()), aBufferStatus);
1.383 + }
1.384 + return err;
1.385 + }
1.386 +
1.387 +void RFsNotify::Close()
1.388 + {
1.389 + CloseSubSession(EFsNotificationSubClose);
1.390 + }
1.391 +
1.392 +/*
1.393 +[Re]Issues notification request
1.394 +Updates buffer, if supplied.
1.395 +
1.396 +@return - last readable index of buffer.
1.397 +*/
1.398 +void RFsNotify::RequestNotifications(TRequestStatus& aStatus, TPckg<TInt>& aTailPckg)
1.399 + {
1.400 + aStatus = KRequestPending;
1.401 + SendReceive(EFsNotificationRequest,TIpcArgs(&aTailPckg),aStatus);
1.402 + }
1.403 +
1.404 +TInt RFsNotify::CancelNotifications()
1.405 + {
1.406 + //there can only be one outstanding notification request at a time
1.407 + return (SendReceive(EFsNotificationCancel));
1.408 + }
1.409 +
1.410 +//Adds notification filter
1.411 +TInt RFsNotify::AddNotification(TUint aNotificationType, const TDesC& aPath, const TDesC& aFilename)
1.412 + {
1.413 + if(aNotificationType == 0 || (aPath.Length() <= 0 && aFilename.Length() <= 0))
1.414 + return KErrArgument;
1.415 +
1.416 + return (SendReceive(EFsNotificationAdd,TIpcArgs(aNotificationType,&aPath,&aFilename)));
1.417 + }
1.418 +
1.419 +//Removes request, does not close session
1.420 +TInt RFsNotify::RemoveNotifications()
1.421 + {
1.422 + return(SendReceive(EFsNotificationRemove));
1.423 + }
1.424 +#else //SYMBIAN_F32_ENHANCED_CHANGE_NOTIFICATION
1.425 +
1.426 +EXPORT_C TFsNotification::TFsNotificationType TFsNotification::NotificationType() const
1.427 + {
1.428 + Panic(ENotificationPanic);
1.429 + return (TFsNotification::TFsNotificationType)0;
1.430 + }
1.431 +
1.432 +EXPORT_C TInt TFsNotification::Path(TPtrC&) const
1.433 + {
1.434 + Panic(ENotificationPanic);
1.435 + return KErrNotSupported;
1.436 + }
1.437 +
1.438 +EXPORT_C TInt TFsNotification::NewName(TPtrC&) const
1.439 + {
1.440 + Panic(ENotificationPanic);
1.441 + return KErrNotSupported;
1.442 + }
1.443 +
1.444 +EXPORT_C TInt TFsNotification::Attributes(TUint&,TUint&) const
1.445 + {
1.446 + Panic(ENotificationPanic);
1.447 + return KErrNotSupported;
1.448 + }
1.449 +
1.450 +EXPORT_C TInt TFsNotification::FileSize(TInt64&) const
1.451 + {
1.452 + Panic(ENotificationPanic);
1.453 + return KErrNotSupported;
1.454 + }
1.455 +
1.456 +/*
1.457 +EXPORT_C TInt TFsNotification::DriveNumber(TInt&) const
1.458 + {
1.459 + Panic(ENotificationPanic);
1.460 + return KErrNotSupported;
1.461 + }
1.462 +
1.463 +EXPORT_C TInt TFsNotification::UID(TUid& aUID) const
1.464 + {
1.465 + Panic(ENotificationPanic);
1.466 + return KErrNotSupported;
1.467 + }
1.468 +*/
1.469 +
1.470 +EXPORT_C CFsNotify* CFsNotify::NewL(RFs& , TInt)
1.471 + {
1.472 + Panic(ENotificationPanic);
1.473 + User::Leave(KErrNotSupported);
1.474 + return NULL;
1.475 + }
1.476 +
1.477 +EXPORT_C CFsNotify::~CFsNotify()
1.478 + {
1.479 + Panic(ENotificationPanic);
1.480 + }
1.481 +
1.482 +EXPORT_C TInt CFsNotify::AddNotification(TUint, const TDesC&, const TDesC&)
1.483 + {
1.484 + Panic(ENotificationPanic);
1.485 + return KErrNotSupported;
1.486 + }
1.487 +
1.488 +EXPORT_C TInt CFsNotify::RemoveNotifications()
1.489 + {
1.490 + Panic(ENotificationPanic);
1.491 + return KErrNotSupported;
1.492 + }
1.493 +
1.494 +EXPORT_C TInt CFsNotify::RequestNotifications(TRequestStatus&)
1.495 + {
1.496 + Panic(ENotificationPanic);
1.497 + return KErrNotSupported;
1.498 + }
1.499 +
1.500 +EXPORT_C TInt CFsNotify::CancelNotifications(TRequestStatus&)
1.501 + {
1.502 + Panic(ENotificationPanic);
1.503 + return KErrNotSupported;
1.504 + }
1.505 +
1.506 +EXPORT_C const TFsNotification * CFsNotify::NextNotification()
1.507 + {
1.508 + Panic(ENotificationPanic);
1.509 + return NULL;
1.510 + }
1.511 +
1.512 +CFsNotificationList::~CFsNotificationList()
1.513 + {
1.514 + Panic(ENotificationPanic);
1.515 + }
1.516 +
1.517 +CFsNotifyBody::CFsNotifyBody()
1.518 + {
1.519 + Panic(ENotificationPanic);
1.520 + }
1.521 +
1.522 +CFsNotifyBody::~CFsNotifyBody()
1.523 + {
1.524 + Panic(ENotificationPanic);
1.525 + }
1.526 +
1.527 +#endif //SYMBIAN_F32_ENHANCED_CHANGE_NOTIFICATION
1.528 +