userlibandfileserver/fileserver/sfat/sl_disk.cpp
changeset 9 96e5fb8b040d
equal deleted inserted replaced
-1:000000000000 9:96e5fb8b040d
       
     1 // Copyright (c) 1996-2009 Nokia Corporation and/or its subsidiary(-ies).
       
     2 // All rights reserved.
       
     3 // This component and the accompanying materials are made available
       
     4 // under the terms of the License "Eclipse Public License v1.0"
       
     5 // which accompanies this distribution, and is available
       
     6 // at the URL "http://www.eclipse.org/legal/epl-v10.html".
       
     7 //
       
     8 // Initial Contributors:
       
     9 // Nokia Corporation - initial contribution.
       
    10 //
       
    11 // Contributors:
       
    12 //
       
    13 // Description:
       
    14 // f32\sfat\sl_disk.cpp
       
    15 // 
       
    16 //
       
    17 
       
    18 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
       
    19 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
       
    20 //!!
       
    21 //!! WARNING!! DO NOT edit this file !! '\sfat' component is obsolete and is not being used. '\sfat32'replaces it
       
    22 //!!
       
    23 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
       
    24 //!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
       
    25 
       
    26 #include "sl_disk.h"
       
    27 #include "sl_cache.h"
       
    28 #include "sl_dir_cache.h"
       
    29 
       
    30 /**
       
    31 @file
       
    32 */
       
    33 
       
    34 
       
    35 //################################################################################################################################
       
    36 //#     CRawDisk implementation
       
    37 //################################################################################################################################
       
    38 
       
    39 
       
    40 /**
       
    41     Factory function. Constructs objects of the classes derived from CRawDisk.
       
    42     
       
    43     @param  aOwner      reference to the onwning FAT Mount class
       
    44     @param  aLocDrvCaps local drive capabilities from the media driver
       
    45     @return pointer to the constructed object. May be NULL on error.
       
    46 */
       
    47 CRawDisk* CRawDisk::NewL(CFatMountCB& aOwner, const TLocalDriveCaps& aLocDrvCaps)
       
    48 {
       
    49     __PRINT1(_L("CRawDisk::NewL() drv:%d"), aOwner.DriveNumber());
       
    50 
       
    51     if(aLocDrvCaps.iMediaAtt & KMediaAttVariableSize)
       
    52     {//-- this is the RAM drive "attribute"
       
    53         ASSERT((aLocDrvCaps.iDriveAtt & (KDriveAttInternal|KDriveAttLocal)) && aLocDrvCaps.iType == EMediaRam);
       
    54         if(!aLocDrvCaps.iBaseAddress)
       
    55         {
       
    56             ASSERT(0);
       
    57             return NULL;
       
    58         }
       
    59 
       
    60         return CRamDisk::NewL(aOwner);
       
    61     }
       
    62 
       
    63     //-- create CAtaDisk by default
       
    64     return CAtaDisk::NewL(aOwner);
       
    65 }
       
    66 
       
    67 
       
    68 CRawDisk::CRawDisk(CFatMountCB& aOwner)
       
    69     {
       
    70     iFatMount = &aOwner;
       
    71     }
       
    72 
       
    73 /**
       
    74     Default implementation. Initialises and re-initialises the object.
       
    75 */
       
    76 void CRawDisk::InitializeL()
       
    77     {
       
    78     ASSERT(iFatMount);
       
    79     }
       
    80 
       
    81 
       
    82 TInt CRawDisk::GetLastErrorInfo(TDes8& /*aErrorInfo*/) const
       
    83     {
       
    84     return KErrNotSupported;
       
    85     }
       
    86 
       
    87 //################################################################################################################################
       
    88 //##    CAtaDisk class implementation
       
    89 //################################################################################################################################
       
    90 
       
    91 CAtaDisk::CAtaDisk(CFatMountCB& aFatMount)
       
    92          :CRawDisk(aFatMount), iDrive(aFatMount.DriveInterface())
       
    93     {
       
    94     }
       
    95 
       
    96 CAtaDisk::~CAtaDisk()
       
    97     {
       
    98     delete ipDirCache;
       
    99     delete iUidCache;
       
   100     
       
   101     }
       
   102 
       
   103 
       
   104 //-------------------------------------------------------------------------------------
       
   105 
       
   106 /**
       
   107     CAtaDisk factory method.
       
   108     
       
   109     @param  aFatMount reference to the owner.
       
   110     @return pointer to the constructed object.
       
   111 */
       
   112 CAtaDisk* CAtaDisk::NewL(CFatMountCB& aFatMount)
       
   113     {
       
   114     __PRINT1(_L("CAtaDisk::NewL() drv:%d"), aFatMount.DriveNumber());
       
   115 
       
   116     CAtaDisk* pSelf = new (ELeave) CAtaDisk(aFatMount);
       
   117     
       
   118     CleanupStack::PushL(pSelf);
       
   119     
       
   120     pSelf->ConstructL();
       
   121     pSelf->InitializeL();
       
   122     
       
   123     CleanupStack::Pop();
       
   124 
       
   125     return pSelf;
       
   126     }
       
   127 
       
   128 //-------------------------------------------------------------------------------------
       
   129 
       
   130 /** 2nd stage constructor */
       
   131 void CAtaDisk::ConstructL()
       
   132     {
       
   133     //===========================  create data WT cache that is primarily used for caching exacutable modules' UIDs
       
   134     const TUint32 KUidCachePageSzLog2 = 9; //-- 512 bytes in page 
       
   135     const TUint32 KUidCachePages = 64;     //-- 64 pages; total cache size is 32K 
       
   136 
       
   137     iUidCache = CMediaWTCache::NewL(iDrive, KUidCachePages, KUidCachePageSzLog2);
       
   138 
       
   139 
       
   140     //=========================== create directory cache
       
   141     
       
   142     //-- Get dir. cache parameters from config. They may be set in estart.txt for a specified drive.
       
   143     const TUint32 KDirCacheSize = iFatMount->FatConfig().DirCacheSize(); //- Total directory cache size, bytes.
       
   144     const TUint32 KMaxDirCachePageSzLog2 = iFatMount->FatConfig().DirCacheMaxPageSizeLog2(); //- Log2 of the Max. dir. cache page.
       
   145 
       
   146     __PRINT2(_L("CAtaDisk::ConstructL() Dir Cache config:%d,%d"),KDirCacheSize,KMaxDirCachePageSzLog2);
       
   147 
       
   148     ASSERT(KDirCacheSize >= K1KiloByte && KDirCacheSize <= K1MegaByte);
       
   149     ASSERT((KMaxDirCachePageSzLog2 >= KDefSectorSzLog2) && (Pow2(KMaxDirCachePageSzLog2) <= KDirCacheSize));
       
   150 
       
   151     //-- calculate the size and number of pages for the dir. cache. 
       
   152     //-- if the mount's cluster size is less than max. page size from config, the page size will be cluster size.
       
   153     //-- otherwise it will be the value from config. I.e  the minimal page size is cluster size; the maximal page size is taken from config.
       
   154     //-- The number of pages depends on total cache size and page size.
       
   155     const TUint clustSizeLog2 = iFatMount->ClusterSizeLog2(); //-- current FAT cluster size Log2
       
   156     const TUint32 pageSzLog2 = (clustSizeLog2 <= KMaxDirCachePageSzLog2) ? clustSizeLog2 : KMaxDirCachePageSzLog2;
       
   157     const TUint32 numPages = KDirCacheSize / (Pow2(pageSzLog2));
       
   158 
       
   159     ASSERT(!ipDirCache);
       
   160 
       
   161 #ifdef USE_DP_DIR_CACHE
       
   162 
       
   163     //=========================== create Demand Paging type of the directory cache
       
   164 
       
   165     // initialize cache memory manager as all file systems have mounted by now
       
   166     if(CCacheMemoryManagerFactory::CacheMemoryManager())
       
   167         {
       
   168         // Note: the configuration data of min and max cache size are aligned with the memory size it
       
   169         //  occupies in kernel as we are using demand paging subsystem for dynamic cache size support. 
       
   170         //  Therefore, they are refered as 'Mem Size' in following calculation.
       
   171         //  However, 'Data Size' refers to the logical size of a page, i.e. the actual data size each page
       
   172         //  contains.
       
   173         // The constraints we have to consider when setting up the dynamic cache:
       
   174         //  1. each page's data size is aligned with cluster size, unless cluster size is bigger than
       
   175         //      the default maximum page size allowed (typically 32 KB).
       
   176         //  2. if page's data size is smaller than segment size (typically 4 KB), i.e. the unit size of 
       
   177         //      demand paging subsystem's page management, we will still use up the whole segment for
       
   178         //      that page.
       
   179         //  3. the default min and max cache's memory size is pre-defined in  fat_config.cpp file.
       
   180         //      (see KDef_DynamicDirCacheMin & KDef_DynamicDirCacheMax).
       
   181 
       
   182         // calculate page data size (logical view of page size)
       
   183         const TUint32 DefMaxCachePageLog2 = iFatMount->FatConfig().DynamicDirCacheMaxPageSizeLog2();
       
   184         const TUint32 PageDataSizeLog2 = clustSizeLog2 < DefMaxCachePageLog2 ? clustSizeLog2 : DefMaxCachePageLog2;
       
   185         
       
   186         // calculate page number, based on memory size we have reserved
       
   187         const TUint32 SegmentSizeLog2 = CCacheMemoryManagerFactory::CacheMemoryManager()->SegmentSizeInBytesLog2();
       
   188         const TUint32 PageMemSizeLog2 = PageDataSizeLog2 < SegmentSizeLog2 ? SegmentSizeLog2 : PageDataSizeLog2;
       
   189         TUint32 CacheSizeMinInPages = iFatMount->FatConfig().DynamicDirCacheSizeMin() >> PageMemSizeLog2;
       
   190         TUint32 CacheSizeMaxInPages = iFatMount->FatConfig().DynamicDirCacheSizeMax() >> PageMemSizeLog2;
       
   191 
       
   192         // cache memory client is connected via name 
       
   193         TBuf<0x20> clientName = _L("CACHE_MEM_CLIENT:");
       
   194         clientName.Append('A'+iFatMount->DriveNumber());
       
   195 
       
   196         TRAPD(err, ipDirCache = CDynamicDirCache::NewL(iDrive, CacheSizeMinInPages, CacheSizeMaxInPages, PageDataSizeLog2, clientName));
       
   197         if (err == KErrNone)
       
   198             {
       
   199             __PRINT4(_L("CDynamicDirCache::NewL(drv:%C, minPageNum:%u, maxPageNum:%u, pageDataSize:%u)\n"), 'A'+iFatMount->DriveNumber(), CacheSizeMinInPages, CacheSizeMaxInPages, 1<<PageDataSizeLog2);
       
   200             return;
       
   201             }
       
   202         }
       
   203 #endif // USE_DP_DIR_CACHE
       
   204 
       
   205     //=========================== create legacy type of the directory cache
       
   206     ASSERT(!ipDirCache);
       
   207 
       
   208     ipDirCache = CMediaWTCache::NewL(iDrive, numPages, pageSzLog2);
       
   209     __PRINT3(_L("CDirCache::NewL(drive: %C, NumPages=%d, PageSize=%u)"), 'A'+iFatMount->DriveNumber(), numPages, 1<<pageSzLog2);
       
   210     
       
   211     }
       
   212 
       
   213 //-------------------------------------------------------------------------------------
       
   214 
       
   215 /**
       
   216     Initialises and re-initialises the object.
       
   217 */
       
   218 void CAtaDisk::InitializeL()
       
   219 {
       
   220     CRawDisk::InitializeL();
       
   221     
       
   222     //-- there is a little issue here. after formatting FAT mounts's cluster size can change.
       
   223     //-- dir. cache page size depends on the cluster size. This method doesn't change the dir. cache page size.
       
   224     //-- At present it is done in CFatMountCB::InitializeL() that deletes this object and then reconstructs it again.
       
   225 
       
   226     //-- invalidate directory cache here
       
   227     ipDirCache->InvalidateCache();
       
   228     
       
   229     TInt64  cacheBasePos;
       
   230     
       
   231     if(iFatMount->FatType() == EFat32)
       
   232         {
       
   233         //-- this is FAT32, all directories including Root are files and aligned to the cluster heap boundary
       
   234         //-- set dir. cache base position to the cluster heap boundary
       
   235         const TUint32 offsetMask = (1 << iFatMount->ClusterSizeLog2() )-1;
       
   236         cacheBasePos = (iFatMount->ClusterBasePosition() & offsetMask);
       
   237         }
       
   238     else
       
   239         {
       
   240         //-- this is FAT12/16. Root directory is a separate volume object and has no alignment.
       
   241         //-- set cache base position to its beginning.
       
   242         cacheBasePos = iFatMount->StartOfRootDirInBytes();
       
   243         }
       
   244 
       
   245     ipDirCache->SetCacheBasePos(cacheBasePos);
       
   246     
       
   247 }
       
   248 
       
   249 //-------------------------------------------------------------------------------------
       
   250 
       
   251 /**
       
   252     Read data from the media through LRU data cache cache. 
       
   253 
       
   254     @param  aPos        absolute media position
       
   255     @param  aLength     how many bytes to read
       
   256     @param  aDes        data descriptor
       
   257 
       
   258     @leave on error
       
   259 */
       
   260 void CAtaDisk::ReadCachedL(TInt64 aPos,TInt aLength,TDes8& aDes) const
       
   261     {
       
   262     __PRINT3(_L("CAtaDisk::ReadL() pos:%u:%u, len:%u"), I64HIGH(aPos), I64LOW(aPos), aLength);
       
   263     iUidCache->ReadL(aPos, aLength, aDes);
       
   264     }
       
   265 
       
   266 //-------------------------------------------------------------------------------------
       
   267 
       
   268 /**
       
   269     Write data to the media through LRU data cache
       
   270 
       
   271     @param  aPos        absolute media position
       
   272     @param  aDes        data descriptor
       
   273 
       
   274     @leave on error
       
   275 */
       
   276 void CAtaDisk::WriteCachedL(TInt64 aPos, const TDesC8& aDes)
       
   277     {
       
   278     __PRINT3(_L("CAtaDisk::WriteL() pos:%u:%u, len:%u"), I64HIGH(aPos), I64LOW(aPos), aDes.Size());
       
   279     iUidCache->WriteL(aPos, aDes);
       
   280     }
       
   281 
       
   282 
       
   283 //-------------------------------------------------------------------------------------
       
   284 
       
   285 /**
       
   286     Read data from the media directly without any caches.
       
   287     Mostly used by file IO
       
   288 
       
   289     @param  aPos        absolute media position
       
   290     @param  aLength     how many bytes to read
       
   291     @param  aTrg        Pointer to the data descriptor, i.e. (const TAny*)(&TDes8)
       
   292     @param  aMessage    Refrence to server message from request
       
   293     @param  anOffset    Offset into read data to write
       
   294 
       
   295     @leave on error
       
   296 */
       
   297 void CAtaDisk::ReadL(TInt64 aPos,TInt aLength,const TAny* aTrg,const RMessagePtr2 &aMessage,TInt anOffset) const
       
   298     {
       
   299 
       
   300     __PRINT4(_L("CAtaDisk::ReadL() pos:%u:%u, len:%u, offset:%u"), I64HIGH(aPos), I64LOW(aPos), aLength, anOffset);
       
   301     User::LeaveIfError(iDrive.ReadNonCritical(aPos,aLength,aTrg,aMessage,anOffset));
       
   302     }
       
   303 
       
   304 //-------------------------------------------------------------------------------------
       
   305 
       
   306 /**
       
   307     Write data to the media directly without any cached.
       
   308     Mostly used by file IO
       
   309 
       
   310     This method shall invalidate some data caches to keep them in synch with the media.
       
   311 
       
   312     @param aPos     Media position in bytes
       
   313     @param aLength  Length in bytes of write
       
   314     @param aTrg     Pointer to the data descriptor, i.e. (const TAny*)(&TDes8)
       
   315     @param aMessage Refrence to server message from request, contains data
       
   316     @param anOffset Offset into write data to use in write
       
   317 
       
   318     @leave on error
       
   319 */
       
   320 void CAtaDisk::WriteL(TInt64 aPos,TInt aLength,const TAny* aSrc,const RMessagePtr2 &aMessage,TInt anOffset)
       
   321     {
       
   322     __PRINT4(_L("CAtaDisk::WriteL() pos:%u:%u, len:%u, offset:%u"), I64HIGH(aPos), I64LOW(aPos), aLength, anOffset);
       
   323 
       
   324     //-- write data to the media directly
       
   325     User::LeaveIfError(iDrive.WriteNonCritical(aPos,aLength,aSrc,aMessage,anOffset));
       
   326 
       
   327     //-- we need to invalidate UID cache page that corresponds to aPos (if any). This is UID caching specific. UID is stored in the first few bytes of 
       
   328     //-- the executable module and therefore belongs to one cache page only.
       
   329     //-- If someone writes to the beginning of the exe module file, corresponding UID cache page will be invalidated and re-read from the media later
       
   330     iUidCache->InvalidateCachePage(aPos); 
       
   331 
       
   332     //-- invalidate affected(if any) part of the FAT cache in the case if someone used to write data to FAT area, which usually do not happen 
       
   333     iFatMount->FAT().InvalidateCacheL(aPos,aLength);
       
   334 
       
   335     }
       
   336 
       
   337 //-------------------------------------------------------------------------------------
       
   338 
       
   339 /** Get information for last disk error */
       
   340 TInt CAtaDisk::GetLastErrorInfo(TDes8& aErrorInfo) const
       
   341     {
       
   342     return iDrive.GetLastErrorInfo(aErrorInfo);
       
   343     }
       
   344 
       
   345 
       
   346 //-------------------------------------------------------------------------------------
       
   347 /** Invalidate whole UID cache */
       
   348 void CAtaDisk::InvalidateUidCache()
       
   349 {
       
   350     ASSERT(iUidCache);
       
   351     iUidCache->InvalidateCache();
       
   352 }
       
   353 
       
   354 /** 
       
   355     Invalidate the UID cache page that has aPos cached.
       
   356     This method doesn't pay attention to the length of the block being invalidated because
       
   357     UID lives in the very beginning of the exe module and always fits into a single page
       
   358 */
       
   359 void CAtaDisk::InvalidateUidCachePage(TUint64 aPos)
       
   360 {
       
   361     ASSERT(iUidCache);
       
   362     iUidCache->InvalidateCachePage(aPos);
       
   363 }
       
   364 
       
   365 
       
   366 //################################################################################################################################
       
   367 //##    CRamDisk class implementation
       
   368 //################################################################################################################################
       
   369 
       
   370 
       
   371 /**
       
   372     CRamDisk factory method.
       
   373     
       
   374     @param  aFatMount reference to the owner.
       
   375     @return pointer to the constructed object.
       
   376 */
       
   377 CRamDisk* CRamDisk::NewL(CFatMountCB& aFatMount)
       
   378     {
       
   379     __PRINT1(_L("CRamDisk::NewL() drv:%d"), aFatMount.DriveNumber());
       
   380     CRamDisk* pSelf = new(ELeave)CRamDisk(aFatMount);
       
   381 
       
   382     CleanupStack::PushL(pSelf);
       
   383   
       
   384     pSelf->InitializeL();
       
   385     
       
   386     CleanupStack::Pop();
       
   387 
       
   388     return pSelf;
       
   389     }
       
   390 
       
   391 CRamDisk::CRamDisk(CFatMountCB& aFatMount)
       
   392          :CRawDisk(aFatMount)
       
   393     {
       
   394     }
       
   395 
       
   396 //-------------------------------------------------------------------------------------
       
   397 
       
   398 /**
       
   399     Initialises and re-initialises the object.
       
   400 */
       
   401 void CRamDisk::InitializeL()
       
   402 {
       
   403     CRawDisk::InitializeL();
       
   404 
       
   405     //-- set the RAM disk base
       
   406     TLocalDriveCapsV2 caps;
       
   407     TPckg<TLocalDriveCapsV2> capsPckg(caps);
       
   408     User::LeaveIfError(iFatMount->LocalDrive()->Caps(capsPckg));
       
   409   
       
   410     ASSERT(caps.iMediaAtt & KMediaAttVariableSize);
       
   411     
       
   412     //-- set RAM disk base
       
   413     iRamDiskBase = caps.iBaseAddress; 
       
   414     ASSERT(iRamDiskBase);
       
   415 }
       
   416 
       
   417 
       
   418 
       
   419 /** @return the start address of the Ram Drive in low memory */
       
   420 TUint8* CRamDisk::RamDiskBase() const
       
   421     {
       
   422     return iRamDiskBase;
       
   423     }
       
   424 
       
   425 //-------------------------------------------------------------------------------------
       
   426 //
       
   427 // Read aLength of data from the disk
       
   428 //
       
   429 void CRamDisk::ReadCachedL(TInt64 aPos,TInt aLength,TDes8& aDes) const
       
   430     {
       
   431     
       
   432     __PRINT3(_L("CRamDisk::ReadL Base 0x%x Pos 0x%x, Len %d"),RamDiskBase(),I64LOW(aPos),aLength);
       
   433     __ASSERT_ALWAYS((aPos+aLength<=I64INT(iFatMount->Size())) && (aLength>=0),User::Leave(KErrCorrupt));
       
   434     Mem::Copy((TUint8*)aDes.Ptr(),RamDiskBase()+I64LOW(aPos),aLength);
       
   435     aDes.SetLength(aLength);
       
   436     }
       
   437 
       
   438 //-------------------------------------------------------------------------------------
       
   439 //
       
   440 // Write aLength of data to the disk
       
   441 //
       
   442 void CRamDisk::WriteCachedL(TInt64 aPos,const TDesC8& aDes)
       
   443     {
       
   444 
       
   445     __PRINT3(_L("CRamDisk::WriteL Base 0x%x Pos 0x%x, Len %d"),RamDiskBase(),aPos,aDes.Length());
       
   446     __ASSERT_ALWAYS(aPos+aDes.Length()<=I64INT(iFatMount->Size()),User::Leave(KErrCorrupt));
       
   447     Mem::Copy(RamDiskBase()+I64LOW(aPos),(TUint8*)aDes.Ptr(),aDes.Length());
       
   448     }
       
   449     
       
   450 
       
   451 //-------------------------------------------------------------------------------------
       
   452 //
       
   453 // Read from ramDrive into thread relative descriptor
       
   454 //
       
   455 void CRamDisk::ReadL(TInt64 aPos,TInt aLength,const TAny* /*aTrg*/,const RMessagePtr2 &aMessage,TInt anOffset) const
       
   456     {
       
   457     __PRINT2(_L("CRamDisk::ReadL TAny* Pos 0x%x, Len %d"),aPos,aLength);
       
   458     __ASSERT_ALWAYS((aPos+aLength<=I64INT(iFatMount->Size())) && (aLength>=0),User::Leave(KErrCorrupt));
       
   459     TUint8* pos=RamDiskBase()+I64LOW(aPos);
       
   460     TPtrC8 buf(pos,aLength);
       
   461     aMessage.WriteL(0,buf,anOffset);
       
   462     }
       
   463 
       
   464 //-------------------------------------------------------------------------------------
       
   465 //
       
   466 // Write from thread relative descriptor into ramDrive
       
   467 //
       
   468 void CRamDisk::WriteL(TInt64 aPos,TInt aLength,const TAny* /*aSrc*/,const RMessagePtr2 &aMessage,TInt anOffset)
       
   469     {
       
   470     __PRINT2(_L("CRamDisk::WriteL TAny* Pos 0x%x, Len %d"),aPos,aLength);
       
   471     __ASSERT_ALWAYS(aPos+aLength<=I64INT(iFatMount->Size()),User::Leave(KErrCorrupt));
       
   472     TUint8* pos=RamDiskBase()+I64LOW(aPos);
       
   473     TPtr8 buf(pos,aLength);
       
   474     aMessage.ReadL(0,buf,anOffset);
       
   475     }
       
   476 
       
   477 
       
   478 
       
   479 
       
   480 
       
   481 
       
   482 
       
   483 
       
   484 
       
   485 
       
   486 
       
   487 
       
   488 
       
   489 
       
   490 
       
   491 
       
   492 
       
   493 
       
   494 
       
   495 
       
   496 
       
   497 
       
   498 
       
   499 
       
   500 
       
   501 
       
   502