1 /* |
|
2 * Copyright (c) 2010 Nokia Corporation and/or its subsidiary(-ies). |
|
3 * All rights reserved. |
|
4 * This component and the accompanying materials are made available |
|
5 * under the terms of "Eclipse Public License v1.0" |
|
6 * which accompanies this distribution, and is available |
|
7 * at the URL "http://www.eclipse.org/legal/epl-v10.html". |
|
8 * |
|
9 * Initial Contributors: |
|
10 * Nokia Corporation - initial contribution. |
|
11 * |
|
12 * Contributors: |
|
13 * |
|
14 * Description: |
|
15 * |
|
16 */ |
|
17 |
|
18 |
|
19 |
|
20 #include "e32image.h" |
|
21 #include "e32imageheaders.h" |
|
22 #include "launchertraces.h" |
|
23 |
|
24 |
|
25 const TInt KMaxHeaderSize = sizeof(E32ImageHeaderV) + 65536/8; |
|
26 |
|
27 SCapabilitySet AllCapabilities; |
|
28 SCapabilitySet DisabledCapabilities; |
|
29 |
|
30 // --------------------------------------------------------------------------- |
|
31 |
|
32 E32ImageReader* E32ImageReader::NewLC() |
|
33 { |
|
34 E32ImageReader* self = new(ELeave) E32ImageReader; |
|
35 CleanupStack::PushL(self); |
|
36 self->ConstructL(); |
|
37 return self; |
|
38 } |
|
39 |
|
40 // --------------------------------------------------------------------------- |
|
41 |
|
42 E32ImageReader::E32ImageReader() |
|
43 { |
|
44 } |
|
45 |
|
46 // --------------------------------------------------------------------------- |
|
47 |
|
48 void E32ImageReader::ConstructL() |
|
49 { |
|
50 LOGSTRING("Launcher: E32ImageReader::ConstructL"); |
|
51 |
|
52 iEnv = CEikonEnv::Static(); |
|
53 } |
|
54 |
|
55 // --------------------------------------------------------------------------- |
|
56 |
|
57 CDesCArray* E32ImageReader::ListOfDLLsL(const TDesC& aFullPathToE32Image) |
|
58 { |
|
59 LOGSTRING("Launcher: E32ImageReader::ListOfDLLsL"); |
|
60 |
|
61 // open the file for reading |
|
62 User::LeaveIfError( iFile.Open(iEnv->FsSession(), aFullPathToE32Image, EFileRead) ); |
|
63 CleanupClosePushL(iFile); |
|
64 |
|
65 // get local copies of capability sets |
|
66 TCapabilitySet caps; |
|
67 caps.SetAllSupported(); |
|
68 AllCapabilities=*(SCapabilitySet*)∩︀ |
|
69 caps.SetDisabled(); |
|
70 DisabledCapabilities=*(SCapabilitySet*)∩︀ |
|
71 |
|
72 // read the header of the image |
|
73 User::LeaveIfError( E32ImageHeader::New(iHeader, iFile) ); |
|
74 |
|
75 // set stuff |
|
76 iHeapSizeMin = iHeader->iHeapSizeMin; |
|
77 iHeapSizeMax = iHeader->iHeapSizeMax; |
|
78 iStackSize = iHeader->iStackSize; |
|
79 iPriority = iHeader->ProcessPriority(); |
|
80 iDepCount = iHeader->iDllRefTableCount; |
|
81 iExportDirCount = iHeader->iExportDirCount; |
|
82 iExportDir = iHeader->iExportDirOffset-iHeader->iCodeOffset; |
|
83 iTextSize = iHeader->iTextSize; |
|
84 iCodeSize = iHeader->iCodeSize; |
|
85 iDataSize = iHeader->iDataSize; |
|
86 iBssSize = iHeader->iBssSize; |
|
87 iTotalDataSize = iDataSize+iBssSize; |
|
88 iFileEntryPoint = iHeader->iEntryPoint; |
|
89 iEntryPtVeneer = 0; |
|
90 iExceptionDescriptor = iHeader->ExceptionDescriptor(); |
|
91 if (iHeader->iExportDirOffset) |
|
92 iExportDirLoad=iExportDir; |
|
93 |
|
94 // allocate data for the code area |
|
95 iCodeLoadAddress = (TUint32)User::Alloc(iCodeSize); |
|
96 |
|
97 // load data from the binary |
|
98 User::LeaveIfError( LoadData() ); |
|
99 |
|
100 // create an array for the dll names from the import list |
|
101 CDesCArray* dllArray = new(ELeave) CDesCArrayFlat(100); |
|
102 CleanupStack::PushL(dllArray); |
|
103 |
|
104 // get the dll names from the import section |
|
105 E32ImportSection* importSection = (E32ImportSection *)iImportData; |
|
106 E32ImportBlock* block; |
|
107 if(importSection) |
|
108 block = (E32ImportBlock*)(importSection+1); |
|
109 else |
|
110 block = NULL; |
|
111 iNextImportPos = 0; |
|
112 |
|
113 // loop through all import data blocks |
|
114 for (TInt i=0; i<iDepCount; i++) |
|
115 { |
|
116 // get a pointer to the dll name |
|
117 TPtrC8 dllname = (const TText8*)((TUint32)iImportData + block->iOffsetOfDllName); |
|
118 TBuf8<KMaxKernelName> rootname; |
|
119 if (dllname.Length() > KMaxKernelName) |
|
120 User::Leave( KErrNotSupported ); |
|
121 |
|
122 // parse the filename |
|
123 TFileNameInfo fni; |
|
124 User::LeaveIfError( fni.Set(dllname, TFileNameInfo::EAllowUid) ); |
|
125 fni.GetName(rootname, TFileNameInfo::EIncludeBaseExt); |
|
126 |
|
127 // append the name to the dll name array |
|
128 TFileName dllName16; |
|
129 dllName16.Copy(rootname); |
|
130 dllArray->AppendL(dllName16); |
|
131 |
|
132 // get the next block |
|
133 TUint impfmt = iHeader->ImportFormat(); |
|
134 block = (E32ImportBlock*)block->NextBlock(impfmt); |
|
135 } |
|
136 |
|
137 CleanupStack::Pop(); //dllArray |
|
138 CleanupStack::PopAndDestroy(); //iFile |
|
139 |
|
140 // free memory |
|
141 delete iHeader; |
|
142 iHeader = NULL; |
|
143 delete iImportSection; |
|
144 iImportSection = NULL; |
|
145 delete iCodeRelocSection; |
|
146 iCodeRelocSection = NULL; |
|
147 delete iDataRelocSection; |
|
148 iDataRelocSection = NULL; |
|
149 |
|
150 User::Free((TAny*)iCodeLoadAddress); |
|
151 User::Free(iRestOfFileData); |
|
152 User::Free(iCurrentImportList); |
|
153 if (iExportDirLoadAllocated) |
|
154 User::Free((TAny*)iExportDirLoad); |
|
155 |
|
156 return dllArray; |
|
157 } |
|
158 |
|
159 // --------------------------------------------------------------------------- |
|
160 |
|
161 E32ImageReader::~E32ImageReader() |
|
162 { |
|
163 LOGSTRING("Launcher: E32ImageReader::~E32ImageReader"); |
|
164 } |
|
165 |
|
166 |
|
167 // --------------------------------------------------------------------------- |
|
168 |
|
169 TInt FileRead(RFile& aFile, TUint8* aDest, TInt aSize) |
|
170 { |
|
171 TPtr8 p(aDest,aSize,aSize); |
|
172 return aFile.Read(p,aSize); |
|
173 } |
|
174 |
|
175 // --------------------------------------------------------------------------- |
|
176 |
|
177 TInt E32ImageHeader::New(E32ImageHeader*& aHdr, RFile& aFile) |
|
178 { |
|
179 LOGSTRING("Launcher: E32ImageHeader::New"); |
|
180 |
|
181 E32ImageHeader* h = NULL; |
|
182 TInt hdrsz = 0; |
|
183 TInt filesize; |
|
184 TInt r = aFile.Size(filesize); |
|
185 if (r!=KErrNone) |
|
186 return r; |
|
187 E32ImageHeader bh; |
|
188 r = FileRead(aFile, (TUint8*)&bh, sizeof(E32ImageHeader)); |
|
189 if (r==KErrNone) |
|
190 { |
|
191 hdrsz = bh.TotalSize(); |
|
192 if ( (TUint(hdrsz) > TUint(KMaxHeaderSize)) || (TUint(hdrsz) < TUint(sizeof(bh))) ) |
|
193 return KErrCorrupt; |
|
194 } |
|
195 h = (E32ImageHeader*)User::Alloc(hdrsz); |
|
196 if (!h) |
|
197 return KErrNoMemory; |
|
198 wordmove(h, &bh, sizeof(E32ImageHeader)); |
|
199 if (hdrsz > (TInt)sizeof(E32ImageHeader)) |
|
200 r = FileRead(aFile, (TUint8*)(h + 1), hdrsz - sizeof(E32ImageHeader)); |
|
201 if (r==KErrNone) |
|
202 r = h->IntegrityCheck(filesize); |
|
203 if (r==KErrNone) |
|
204 { |
|
205 if (h->HeaderFormat() >= KImageHdrFmt_V) |
|
206 { |
|
207 // Overide capabilities in image |
|
208 for(TInt i=0; i<SCapabilitySet::ENCapW; i++) |
|
209 { |
|
210 ((E32ImageHeaderV*)h)->iS.iCaps[i] |= DisabledCapabilities[i]; |
|
211 ((E32ImageHeaderV*)h)->iS.iCaps[i] &= AllCapabilities[i]; |
|
212 } |
|
213 } |
|
214 aHdr = h; |
|
215 } |
|
216 else |
|
217 { |
|
218 delete h; |
|
219 aHdr = NULL; |
|
220 } |
|
221 return r; |
|
222 } |
|
223 |
|
224 // --------------------------------------------------------------------------- |
|
225 |
|
226 TInt E32ImageHeader::IntegrityCheck(TInt aFileSize) |
|
227 { |
|
228 LOGSTRING("Launcher: E32ImageHeader::IntegrityCheck"); |
|
229 |
|
230 TInt hdrsz = TotalSize(); |
|
231 TUint hdrfmt = HeaderFormat(); |
|
232 TUidType uids = *(const TUidType*)&iUid1; |
|
233 E32ImageHeaderV* v = NULL; |
|
234 TCheckedUid chkuid(uids); |
|
235 const TUint32* pChkUid = (const TUint32*)&chkuid; |
|
236 |
|
237 if (pChkUid[3] != iUidChecksum) |
|
238 return KErrCorrupt; |
|
239 |
|
240 if (hdrfmt == KImageHdrFmt_V) |
|
241 { |
|
242 TUint32 supplied_crc = iHeaderCrc; |
|
243 iHeaderCrc = KImageCrcInitialiser; |
|
244 TUint32 crc = 0; |
|
245 Mem::Crc32(crc, this, hdrsz); |
|
246 iHeaderCrc = supplied_crc; |
|
247 if (crc != supplied_crc) |
|
248 return KErrCorrupt; |
|
249 v = (E32ImageHeaderV*)this; |
|
250 TUint total_eds = v->iExportDescSize + sizeof(v->iExportDescSize) + sizeof(v->iExportDescType); |
|
251 total_eds = (total_eds + 3) &~ 3; |
|
252 if (total_eds + (TUint)_FOFF(E32ImageHeaderV, iExportDescSize) != (TUint)hdrsz) |
|
253 return KErrCorrupt; |
|
254 if (TUint(v->iExportDescType) > KImageHdr_ExpD_SparseBitmap8) |
|
255 return KErrNotSupported; |
|
256 } |
|
257 else if (hdrfmt >= KImageHdrFmt_V) |
|
258 return KErrNotSupported; |
|
259 |
|
260 TCpu cpu = CpuIdentifier(); |
|
261 TUint abi = ABI(); |
|
262 TUint impfmt = ImportFormat(); |
|
263 TUint compression = CompressionType(); |
|
264 |
|
265 TUint uncompressed_size = compression ? UncompressedFileSize() : (TUint)aFileSize; |
|
266 |
|
267 if (iSignature != 0x434f5045) // 'EPOC' |
|
268 return KErrCorrupt; |
|
269 if (iCodeSize<0) |
|
270 return KErrCorrupt; |
|
271 if (iDataSize<0) |
|
272 return KErrCorrupt; |
|
273 if (iHeapSizeMin<0) |
|
274 return KErrCorrupt; |
|
275 if (iHeapSizeMax<iHeapSizeMin) |
|
276 return KErrCorrupt; |
|
277 if (iStackSize<0) |
|
278 return KErrCorrupt; |
|
279 if (iBssSize<0) |
|
280 return KErrCorrupt; |
|
281 if (iDllRefTableCount<0) |
|
282 return KErrCorrupt; |
|
283 if (iExportDirOffset >= uncompressed_size) |
|
284 return KErrCorrupt; |
|
285 if (TUint(iExportDirCount)>65535) |
|
286 return KErrCorrupt; |
|
287 if (iTextSize<0) |
|
288 return KErrCorrupt; |
|
289 if (iCodeSize<iTextSize) |
|
290 return KErrCorrupt; |
|
291 if (iCodeOffset >= uncompressed_size) |
|
292 return KErrCorrupt; |
|
293 if (iDataOffset >= uncompressed_size) |
|
294 return KErrCorrupt; |
|
295 if (iImportOffset >= uncompressed_size) |
|
296 return KErrCorrupt; |
|
297 if (iCodeRelocOffset >= uncompressed_size) |
|
298 return KErrCorrupt; |
|
299 if (iDataRelocOffset >= uncompressed_size) |
|
300 return KErrCorrupt; |
|
301 if (TUint(iCodeSize+iDataSize) > uncompressed_size) |
|
302 return KErrCorrupt; |
|
303 |
|
304 if (abi>KImageABI_EABI) |
|
305 return KErrNotSupported; |
|
306 if (impfmt>KImageImpFmt_PE2) |
|
307 return KErrNotSupported; |
|
308 if (iUid1 != (TUint32)KExecutableImageUidValue && iUid1 != (TUint32)KDynamicLibraryUidValue) |
|
309 return KErrNotSupported; |
|
310 TUint32 mv = ModuleVersion(); |
|
311 if (mv >= 0x80000000u || (mv & 0x0000ffffu) > 0x8000u) |
|
312 return KErrNotSupported; |
|
313 |
|
314 return KErrNone; |
|
315 } |
|
316 // --------------------------------------------------------------------------- |
|
317 |
|
318 TInt E32ImageReader::LoadData() |
|
319 { |
|
320 LOGSTRING("Launcher: E32ImageReader::LoadData"); |
|
321 |
|
322 TInt remainder; |
|
323 iFile.Size(remainder); |
|
324 |
|
325 remainder -= iHeader->TotalSize(); |
|
326 TUint32 compression = iHeader->CompressionType(); |
|
327 if (compression != KMyFormatNotCompressed) |
|
328 { |
|
329 remainder = iHeader->UncompressedFileSize() - iHeader->iCodeOffset; |
|
330 } |
|
331 |
|
332 remainder -= iHeader->iCodeSize; |
|
333 |
|
334 if (remainder > 0) |
|
335 { |
|
336 iRestOfFileData = (TUint8*)User::Alloc(remainder); |
|
337 if (iRestOfFileData) |
|
338 iRestOfFileSize=remainder; |
|
339 else |
|
340 return KErrNoMemory; |
|
341 } |
|
342 |
|
343 iConversionOffset = iHeader->iCodeOffset + iHeader->iCodeSize; |
|
344 |
|
345 TInt r = LoadFile(compression); |
|
346 if (r !=KErrNone) |
|
347 return r; |
|
348 |
|
349 |
|
350 TUint8* source=NULL; |
|
351 if (iHeader->iImportOffset) |
|
352 { |
|
353 TUint bufferOffset=iHeader->iImportOffset-iConversionOffset; |
|
354 |
|
355 if(bufferOffset>iRestOfFileSize || bufferOffset+sizeof(E32ImportSection)>iRestOfFileSize) |
|
356 return KErrCorrupt; |
|
357 |
|
358 source=iRestOfFileData+bufferOffset; |
|
359 |
|
360 iImportSection = new E32ImportSection; |
|
361 |
|
362 if (iImportSection) |
|
363 Mem::Move((TText8*)iImportSection, source, sizeof(E32ImportSection)); |
|
364 else |
|
365 return KErrNoMemory; |
|
366 } |
|
367 |
|
368 iCodeDelta = iCodeRunAddress-iHeader->iCodeBase; |
|
369 iDataDelta = iDataRunAddress-iHeader->iDataBase; |
|
370 |
|
371 if (r==KErrNone) |
|
372 r = ReadImportData(); |
|
373 |
|
374 return r; |
|
375 } |
|
376 |
|
377 // --------------------------------------------------------------------------- |
|
378 |
|
379 TUint8* E32ImageReader::MemoryMove(TAny* aDestination, const TAny* aSource, TInt aNumberofBytes) |
|
380 { |
|
381 return Mem::Move(aDestination, aSource, aNumberofBytes); |
|
382 } |
|
383 |
|
384 // --------------------------------------------------------------------------- |
|
385 |
|
386 GLDEF_C TInt svRelocateExports(TAny* aPtr) |
|
387 { |
|
388 E32ImageReader* pI=(E32ImageReader*)aPtr; |
|
389 TUint32* destExport=(TUint32*)pI->iExportDirLoad; |
|
390 TInt i=pI->iExportDirCount; |
|
391 TUint32 codeBase=pI->iCodeRunAddress; |
|
392 while (i-->0) |
|
393 *destExport+++=codeBase; |
|
394 return 0; |
|
395 } |
|
396 |
|
397 // --------------------------------------------------------------------------- |
|
398 |
|
399 TInt E32ImageReader::LoadFile(TUint32 aCompression) |
|
400 { |
|
401 LOGSTRING("Launcher: E32ImageReader::LoadFile"); |
|
402 |
|
403 TInt r(KErrNone); |
|
404 |
|
405 if (aCompression == KMyFormatNotCompressed) |
|
406 r=LoadFileNoCompress(); |
|
407 |
|
408 else if (aCompression == KMyUidCompressionDeflate) |
|
409 { |
|
410 TRAP(r, LoadFileInflateL()); |
|
411 } |
|
412 |
|
413 else |
|
414 r = KErrNotSupported; |
|
415 |
|
416 return r; |
|
417 } |
|
418 |
|
419 // --------------------------------------------------------------------------- |
|
420 |
|
421 TInt E32ImageReader::LoadFileNoCompress() |
|
422 { |
|
423 LOGSTRING("Launcher: E32ImageReader::LoadFileNoCompress"); |
|
424 |
|
425 TInt r(KErrNone); |
|
426 |
|
427 if (iHeader->iCodeSize) |
|
428 { |
|
429 r = Read(iHeader->iCodeOffset, (TText8*)iCodeLoadAddress, iCodeSize); |
|
430 } |
|
431 |
|
432 if (r != KErrNone) |
|
433 { |
|
434 return r; |
|
435 } |
|
436 |
|
437 if (iRestOfFileSize) |
|
438 { |
|
439 r = Read(iConversionOffset, (TText8*)iRestOfFileData, iRestOfFileSize); |
|
440 } |
|
441 |
|
442 return r; |
|
443 } |
|
444 |
|
445 // --------------------------------------------------------------------------- |
|
446 |
|
447 void FileCleanup(TAny* aPtr) |
|
448 { |
|
449 TFileInput* f=(TFileInput*)aPtr; |
|
450 f->Cancel(); |
|
451 delete f; |
|
452 } |
|
453 |
|
454 // --------------------------------------------------------------------------- |
|
455 |
|
456 void E32ImageReader::LoadFileInflateL() |
|
457 { |
|
458 LOGSTRING("Launcher: E32ImageReader::LoadFileInflateL"); |
|
459 |
|
460 TInt pos = iHeader->TotalSize(); |
|
461 User::LeaveIfError(iFile.Seek(ESeekStart,pos)); |
|
462 |
|
463 TFileInput* file = new (ELeave) TFileInput(iFile); |
|
464 CleanupStack::PushL(TCleanupItem(&FileCleanup,file)); |
|
465 CInflater* inflater = CInflater::NewLC(*file); |
|
466 |
|
467 if (iHeader->iCodeSize) |
|
468 { |
|
469 TInt count = inflater->ReadL((TUint8*)iCodeLoadAddress, iCodeSize, &MemoryMove); |
|
470 |
|
471 if(count!=iCodeSize) |
|
472 User::Leave(KErrCorrupt); |
|
473 } |
|
474 |
|
475 if (iRestOfFileSize) |
|
476 { |
|
477 TUint32 count = inflater->ReadL(iRestOfFileData, iRestOfFileSize, &Mem::Move); |
|
478 |
|
479 if(count!=iRestOfFileSize) |
|
480 User::Leave(KErrCorrupt); |
|
481 } |
|
482 |
|
483 CleanupStack::PopAndDestroy(2,file); |
|
484 } |
|
485 |
|
486 // --------------------------------------------------------------------------- |
|
487 |
|
488 TInt E32ImageReader::Read(TText8* aDest, TInt aSize) |
|
489 { |
|
490 TPtr8 p(aDest,aSize,aSize); |
|
491 return iFile.Read(p,aSize); |
|
492 } |
|
493 |
|
494 // --------------------------------------------------------------------------- |
|
495 |
|
496 TInt E32ImageReader::Read(TInt aPos, TText8* aDest, TInt aSize) |
|
497 { |
|
498 TPtr8 p(aDest,aSize,aSize); |
|
499 if (aPos<0) |
|
500 return KErrCorrupt; |
|
501 return iFile.Read(aPos,p,aSize); |
|
502 } |
|
503 |
|
504 // --------------------------------------------------------------------------- |
|
505 |
|
506 TInt E32ImageReader::ReadImportData() |
|
507 { |
|
508 LOGSTRING("Launcher: E32ImageReader::ReadImportData"); |
|
509 |
|
510 if (!iHeader->iImportOffset) |
|
511 return KErrNone; |
|
512 |
|
513 TUint32 bufferOffset = iHeader->iImportOffset-iConversionOffset; |
|
514 |
|
515 if(bufferOffset>iRestOfFileSize || bufferOffset+iImportSection->iSize>iRestOfFileSize) |
|
516 return KErrCorrupt; |
|
517 |
|
518 iImportData = (TUint32*)(iRestOfFileData+bufferOffset); |
|
519 |
|
520 E32ImportSection* s = (E32ImportSection*)iImportData; |
|
521 E32ImportBlock* b = (E32ImportBlock*)(s + 1); |
|
522 TUint impfmt = iHeader->ImportFormat(); |
|
523 TInt i; |
|
524 TInt n = 0; |
|
525 |
|
526 for (i=0; i<iDepCount; ++i) |
|
527 { |
|
528 if (b->iNumberOfImports > n) |
|
529 n = b->iNumberOfImports; |
|
530 b = (E32ImportBlock*)b->NextBlock(impfmt); |
|
531 } |
|
532 |
|
533 iCurrentImportList = (TUint32*)User::Alloc(n * sizeof(TUint32)); |
|
534 |
|
535 if (!iCurrentImportList) |
|
536 return KErrNoMemory; |
|
537 |
|
538 return KErrNone; |
|
539 } |
|
540 |
|
541 // --------------------------------------------------------------------------- |
|
542 |
|
543 inline CInflater::CInflater(TBitInput& aInput) |
|
544 :iBits(&aInput),iEncoding(0),iOut(0) |
|
545 {} |
|
546 |
|
547 // --------------------------------------------------------------------------- |
|
548 |
|
549 void CInflater::ConstructL() |
|
550 { |
|
551 iEncoding=new(ELeave) TEncoding; |
|
552 InitL(); |
|
553 iLen=0; |
|
554 iOut=new(ELeave) TUint8[KDeflateMaxDistance]; |
|
555 iAvail=iLimit=iOut; |
|
556 } |
|
557 |
|
558 // --------------------------------------------------------------------------- |
|
559 |
|
560 CInflater* CInflater::NewLC(TBitInput& aInput) |
|
561 { |
|
562 CInflater* self=new(ELeave) CInflater(aInput); |
|
563 CleanupStack::PushL(self); |
|
564 self->ConstructL(); |
|
565 return self; |
|
566 } |
|
567 |
|
568 // --------------------------------------------------------------------------- |
|
569 |
|
570 CInflater::~CInflater() |
|
571 { |
|
572 delete iEncoding; |
|
573 delete [] iOut; |
|
574 } |
|
575 |
|
576 // --------------------------------------------------------------------------- |
|
577 |
|
578 TInt CInflater::ReadL(TUint8* aBuffer,TInt aLength, TMemoryMoveFunction aMemMovefn) |
|
579 { |
|
580 TInt tfr=0; |
|
581 for (;;) |
|
582 { |
|
583 TInt len=Min(aLength,iLimit-iAvail); |
|
584 if (len && aBuffer) |
|
585 { |
|
586 aMemMovefn(aBuffer,iAvail,len); |
|
587 aBuffer+=len; |
|
588 } |
|
589 aLength-=len; |
|
590 iAvail+=len; |
|
591 tfr+=len; |
|
592 if (aLength==0) |
|
593 return tfr; |
|
594 len=InflateL(); |
|
595 if (len==0) |
|
596 return tfr; |
|
597 iAvail=iOut; |
|
598 iLimit=iAvail+len; |
|
599 } |
|
600 } |
|
601 |
|
602 // --------------------------------------------------------------------------- |
|
603 |
|
604 TInt CInflater::SkipL(TInt aLength) |
|
605 { |
|
606 return ReadL(0,aLength,Mem::Move); |
|
607 } |
|
608 |
|
609 // --------------------------------------------------------------------------- |
|
610 |
|
611 void CInflater::InitL() |
|
612 { |
|
613 Huffman::InternalizeL(*iBits,iEncoding->iLitLen,KDeflationCodes); |
|
614 |
|
615 if (!Huffman::IsValid(iEncoding->iLitLen,TEncoding::ELitLens) || |
|
616 !Huffman::IsValid(iEncoding->iDistance,TEncoding::EDistances)) |
|
617 User::Leave(KErrCorrupt); |
|
618 |
|
619 Huffman::Decoding(iEncoding->iLitLen,TEncoding::ELitLens,iEncoding->iLitLen); |
|
620 Huffman::Decoding(iEncoding->iDistance,TEncoding::EDistances,iEncoding->iDistance,KDeflateDistCodeBase); |
|
621 } |
|
622 |
|
623 // --------------------------------------------------------------------------- |
|
624 |
|
625 TInt CInflater::InflateL() |
|
626 { |
|
627 TUint8* out=iOut; |
|
628 TUint8* const end=out+KDeflateMaxDistance; |
|
629 const TUint32* tree=iEncoding->iLitLen; |
|
630 if (iLen<0) // EOF |
|
631 return 0; |
|
632 if (iLen>0) |
|
633 goto useHistory; |
|
634 |
|
635 while (out<end) |
|
636 { |
|
637 // get a huffman code |
|
638 { |
|
639 TInt val=iBits->HuffmanL(tree)-TEncoding::ELiterals; |
|
640 if (val<0) |
|
641 { |
|
642 *out++=TUint8(val); |
|
643 continue; |
|
644 } |
|
645 if (val==TEncoding::EEos-TEncoding::ELiterals) |
|
646 { |
|
647 iLen=-1; |
|
648 break; |
|
649 } |
|
650 |
|
651 TInt code=val&0xff; |
|
652 if (code>=8) |
|
653 { |
|
654 TInt xtra=(code>>2)-1; |
|
655 code-=xtra<<2; |
|
656 code<<=xtra; |
|
657 code|=iBits->ReadL(xtra); |
|
658 } |
|
659 if (val<KDeflateDistCodeBase-TEncoding::ELiterals) |
|
660 { |
|
661 iLen=code+KDeflateMinLength; |
|
662 tree=iEncoding->iDistance; |
|
663 continue; |
|
664 } |
|
665 |
|
666 iRptr=out-(code+1); |
|
667 if (iRptr+KDeflateMaxDistance<end) |
|
668 iRptr+=KDeflateMaxDistance; |
|
669 } |
|
670 useHistory: |
|
671 TInt tfr=Min(end-out,iLen); |
|
672 iLen-=tfr; |
|
673 const TUint8* from=iRptr; |
|
674 do |
|
675 { |
|
676 *out++=*from++; |
|
677 if (from==end) |
|
678 from-=KDeflateMaxDistance; |
|
679 } while (--tfr!=0); |
|
680 iRptr=from; |
|
681 tree=iEncoding->iLitLen; |
|
682 }; |
|
683 |
|
684 return out-iOut; |
|
685 } |
|
686 |
|
687 // --------------------------------------------------------------------------- |
|
688 |
|
689 TFileInput::TFileInput(RFile& aFile) |
|
690 :iFile(aFile),iReadBuf(iBuf1),iPtr(iBuf1,KBufSize) |
|
691 { |
|
692 aFile.Read(iPtr,iStat); |
|
693 } |
|
694 |
|
695 // --------------------------------------------------------------------------- |
|
696 |
|
697 void TFileInput::Cancel() |
|
698 { |
|
699 if (iReadBuf) |
|
700 User::WaitForRequest(iStat); |
|
701 } |
|
702 |
|
703 // --------------------------------------------------------------------------- |
|
704 |
|
705 void TFileInput::UnderflowL() |
|
706 { |
|
707 TUint8* b=iReadBuf; |
|
708 ASSERT(b!=NULL); |
|
709 User::WaitForRequest(iStat); |
|
710 iReadBuf=0; |
|
711 User::LeaveIfError(iStat.Int()); |
|
712 if(iPtr.Length()==0) |
|
713 User::Leave(KErrCorrupt); |
|
714 Set(b,iPtr.Length()*8); |
|
715 |
|
716 b = b==iBuf1 ? iBuf2 : iBuf1; |
|
717 iPtr.Set(b,0,KBufSize); |
|
718 iFile.Read(iPtr,iStat); |
|
719 iReadBuf=b; |
|
720 } |
|
721 |
|
722 // --------------------------------------------------------------------------- |
|
723 |
|
724 TFileNameInfo::TFileNameInfo() |
|
725 { |
|
726 memclr(this, sizeof(TFileNameInfo)); |
|
727 } |
|
728 |
|
729 // --------------------------------------------------------------------------- |
|
730 |
|
731 TInt TFileNameInfo::Set(const TDesC8& aFileName, TUint aFlags) |
|
732 { |
|
733 iUid = 0; |
|
734 iVersion = 0; |
|
735 iPathPos = 0; |
|
736 iName = aFileName.Ptr(); |
|
737 iLen = aFileName.Length(); |
|
738 iExtPos = aFileName.LocateReverse('.'); |
|
739 if (iExtPos<0) |
|
740 iExtPos = iLen; |
|
741 TInt osq = aFileName.LocateReverse('['); |
|
742 TInt csq = aFileName.LocateReverse(']'); |
|
743 if (!(aFlags & EAllowUid) && (osq>=0 || csq>=0)) |
|
744 { |
|
745 return KErrBadName; |
|
746 } |
|
747 if (osq>=iExtPos || csq>=iExtPos) |
|
748 { |
|
749 return KErrBadName; |
|
750 } |
|
751 TInt p = iExtPos; |
|
752 if ((aFlags & EAllowUid) && p>=10 && iName[p-1]==']' && iName[p-10]=='[') |
|
753 { |
|
754 TPtrC8 uidstr(iName + p - 9, 8); |
|
755 TLex8 uidlex(uidstr); |
|
756 TUint32 uid = 0; |
|
757 TInt r = uidlex.Val(uid, EHex); |
|
758 if (r==KErrNone && uidlex.Eos()) |
|
759 iUid = uid, p -= 10; |
|
760 } |
|
761 iUidPos = p; |
|
762 TInt ob = aFileName.LocateReverse('{'); |
|
763 TInt cb = aFileName.LocateReverse('}'); |
|
764 if (ob>=iUidPos || cb>=iUidPos) |
|
765 { |
|
766 return KErrBadName; |
|
767 } |
|
768 if (ob>=0 && cb>=0 && p-1==cb) |
|
769 { |
|
770 TPtrC8 p8(iName, p); |
|
771 TInt d = p8.LocateReverse('.'); |
|
772 TPtrC8 verstr(iName+ob+1, p-ob-2); |
|
773 TLex8 verlex(verstr); |
|
774 if (ob==p-10 && d<ob) |
|
775 { |
|
776 TUint32 ver = 0; |
|
777 TInt r = verlex.Val(ver, EHex); |
|
778 if (r==KErrNone && verlex.Eos()) |
|
779 iVersion = ver, p = ob; |
|
780 } |
|
781 else if (d>ob && p-1>d && (aFlags & EAllowDecimalVersion)) |
|
782 { |
|
783 TUint32 maj = 0; |
|
784 TUint32 min = 0; |
|
785 TInt r = verlex.Val(maj, EDecimal); |
|
786 TUint c = (TUint)verlex.Get(); |
|
787 TInt r2 = verlex.Val(min, EDecimal); |
|
788 if (r==KErrNone && c=='.' && r2==KErrNone && verlex.Eos() && maj<32768 && min<32768) |
|
789 iVersion = (maj << 16) | min, p = ob; |
|
790 } |
|
791 } |
|
792 iVerPos = p; |
|
793 if (iLen>=2 && iName[1]==':') |
|
794 { |
|
795 TUint c = iName[0]; |
|
796 if (c!='?' || !(aFlags & EAllowPlaceholder)) |
|
797 { |
|
798 c |= 0x20; |
|
799 if (c<'a' || c>'z') |
|
800 { |
|
801 return KErrBadName; |
|
802 } |
|
803 } |
|
804 iPathPos = 2; |
|
805 } |
|
806 TPtrC8 pathp(iName+iPathPos, iVerPos-iPathPos); |
|
807 if (pathp.Locate('[')>=0 || pathp.Locate(']')>=0 || pathp.Locate('{')>=0 || pathp.Locate('}')>=0 || pathp.Locate(':')>=0) |
|
808 { |
|
809 return KErrBadName; |
|
810 } |
|
811 iBasePos = pathp.LocateReverse('\\') + 1 + iPathPos; |
|
812 |
|
813 return KErrNone; |
|
814 } |
|
815 |
|
816 // --------------------------------------------------------------------------- |
|
817 |
|
818 void TFileNameInfo::GetName(TDes8& aName, TUint aFlags) const |
|
819 { |
|
820 if (aFlags & EIncludeDrive) |
|
821 aName.Append(Drive()); |
|
822 if (aFlags & EIncludePath) |
|
823 { |
|
824 if (PathLen() && iName[iPathPos]!='\\') |
|
825 aName.Append('\\'); |
|
826 aName.Append(Path()); |
|
827 } |
|
828 if (aFlags & EIncludeBase) |
|
829 aName.Append(Base()); |
|
830 if ((aFlags & EForceVer) || ((aFlags & EIncludeVer) && VerLen()) ) |
|
831 { |
|
832 aName.Append('{'); |
|
833 aName.AppendNumFixedWidth(iVersion, EHex, 8); |
|
834 aName.Append('}'); |
|
835 } |
|
836 if ((aFlags & EForceUid) || ((aFlags & EIncludeUid) && UidLen()) ) |
|
837 { |
|
838 aName.Append('['); |
|
839 aName.AppendNumFixedWidth(iUid, EHex, 8); |
|
840 aName.Append(']'); |
|
841 } |
|
842 if (aFlags & EIncludeExt) |
|
843 aName.Append(Ext()); |
|
844 } |
|
845 |
|
846 // --------------------------------------------------------------------------- |
|