~ubuntu-installer/wubi/trunk

« back to all changes in this revision

Viewing changes to src/7z/CPP/7zip/Archive/7z/7zHandler.cpp

  • Committer: Agostino Russo
  • Date: 2008-12-04 00:37:30 UTC
  • Revision ID: agostino.russo@gmail.com-20081204003730-3o051yp78d6ujckl
* Bumped version to 9.04
* Added required binaries (will be compiled at a later stage)
* Added uninstallation page
* Added BitTorrent source
* Added documentation and licenses
* Connected download managers
* Fixed download status updates
* Added more information to the README
* Made the tasklist thread daemonic so that it does not prevent the
  main application from quitting

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// 7zHandler.cpp
 
2
 
 
3
#include "StdAfx.h"
 
4
 
 
5
#include "7zHandler.h"
 
6
#include "7zProperties.h"
 
7
 
 
8
#include "../../../Common/IntToString.h"
 
9
#include "../../../Common/ComTry.h"
 
10
#include "../../../Windows/Defs.h"
 
11
 
 
12
#include "../Common/ItemNameUtils.h"
 
13
#ifdef _7Z_VOL
 
14
#include "../Common/MultiStream.h"
 
15
#endif
 
16
 
 
17
#ifdef __7Z_SET_PROPERTIES
 
18
#ifdef EXTRACT_ONLY
 
19
#include "../Common/ParseProperties.h"
 
20
#endif
 
21
#endif
 
22
 
 
23
#ifdef COMPRESS_MT
 
24
#include "../../../Windows/System.h"
 
25
#endif
 
26
 
 
27
using namespace NWindows;
 
28
 
 
29
extern UString ConvertMethodIdToString(UInt64 id);
 
30
 
 
31
namespace NArchive {
 
32
namespace N7z {
 
33
 
 
34
CHandler::CHandler()
 
35
{
 
36
  _crcSize = 4;
 
37
 
 
38
  #ifdef EXTRACT_ONLY
 
39
  #ifdef COMPRESS_MT
 
40
  _numThreads = NWindows::NSystem::GetNumberOfProcessors();
 
41
  #endif
 
42
  #else
 
43
  Init();
 
44
  #endif
 
45
}
 
46
 
 
47
STDMETHODIMP CHandler::GetNumberOfItems(UInt32 *numItems)
 
48
{
 
49
  *numItems = 
 
50
  #ifdef _7Z_VOL
 
51
  _refs.Size();
 
52
  #else
 
53
  *numItems = _database.Files.Size();
 
54
  #endif
 
55
  return S_OK;
 
56
}
 
57
 
 
58
#ifdef _SFX
 
59
 
 
60
IMP_IInArchive_ArcProps_NO
 
61
 
 
62
STDMETHODIMP CHandler::GetNumberOfProperties(UInt32 * /* numProperties */)
 
63
{
 
64
  return E_NOTIMPL;
 
65
}
 
66
 
 
67
STDMETHODIMP CHandler::GetPropertyInfo(UInt32 /* index */,     
 
68
      BSTR * /* name */, PROPID * /* propID */, VARTYPE * /* varType */)
 
69
{
 
70
  return E_NOTIMPL;
 
71
}
 
72
 
 
73
 
 
74
#else
 
75
 
 
76
STATPROPSTG kArcProps[] = 
 
77
{
 
78
  { NULL, kpidMethod, VT_BSTR},
 
79
  { NULL, kpidSolid, VT_BOOL},
 
80
  { NULL, kpidNumBlocks, VT_UI4}
 
81
};
 
82
 
 
83
STDMETHODIMP CHandler::GetArchiveProperty(PROPID propID, PROPVARIANT *value)
 
84
{
 
85
  COM_TRY_BEGIN
 
86
  NWindows::NCOM::CPropVariant prop;
 
87
  switch(propID)
 
88
  {
 
89
    case kpidMethod:
 
90
    {
 
91
      UString resString;
 
92
      CRecordVector<UInt64> ids;
 
93
      int i;
 
94
      for (i = 0; i < _database.Folders.Size(); i++)
 
95
      {
 
96
        const CFolder &f = _database.Folders[i];
 
97
        for (int j = f.Coders.Size() - 1; j >= 0; j--)
 
98
          ids.AddToUniqueSorted(f.Coders[j].MethodID);
 
99
      }
 
100
 
 
101
      for (i = 0; i < ids.Size(); i++)
 
102
      {
 
103
        UInt64 id = ids[i];
 
104
        UString methodName;
 
105
        /* bool methodIsKnown = */ FindMethod(EXTERNAL_CODECS_VARS id, methodName);
 
106
        if (methodName.IsEmpty())
 
107
          methodName = ConvertMethodIdToString(id);
 
108
        if (!resString.IsEmpty())
 
109
          resString += L' ';
 
110
        resString += methodName;
 
111
      }
 
112
      prop = resString; 
 
113
      break;
 
114
    }
 
115
    case kpidSolid: prop = _database.IsSolid(); break;
 
116
    case kpidNumBlocks: prop = (UInt32)_database.Folders.Size(); break;
 
117
  }
 
118
  prop.Detach(value);
 
119
  return S_OK;
 
120
  COM_TRY_END
 
121
}
 
122
 
 
123
IMP_IInArchive_ArcProps
 
124
 
 
125
#endif
 
126
 
 
127
static void MySetFileTime(bool timeDefined, FILETIME unixTime, NWindows::NCOM::CPropVariant &prop)
 
128
{
 
129
  if (timeDefined)
 
130
    prop = unixTime;
 
131
}
 
132
 
 
133
#ifndef _SFX
 
134
 
 
135
static UString ConvertUInt32ToString(UInt32 value)
 
136
{
 
137
  wchar_t buffer[32];
 
138
  ConvertUInt64ToString(value, buffer);
 
139
  return buffer;
 
140
}
 
141
 
 
142
static UString GetStringForSizeValue(UInt32 value)
 
143
{
 
144
  for (int i = 31; i >= 0; i--)
 
145
    if ((UInt32(1) << i) == value)
 
146
      return ConvertUInt32ToString(i);
 
147
  UString result;
 
148
  if (value % (1 << 20) == 0)
 
149
  {
 
150
    result += ConvertUInt32ToString(value >> 20);
 
151
    result += L"m";
 
152
  }
 
153
  else if (value % (1 << 10) == 0)
 
154
  {
 
155
    result += ConvertUInt32ToString(value >> 10);
 
156
    result += L"k";
 
157
  }
 
158
  else
 
159
  {
 
160
    result += ConvertUInt32ToString(value);
 
161
    result += L"b";
 
162
  }
 
163
  return result;
 
164
}
 
165
 
 
166
static const UInt64 k_Copy = 0x0;
 
167
static const UInt64 k_LZMA  = 0x030101;
 
168
static const UInt64 k_PPMD  = 0x030401;
 
169
 
 
170
static wchar_t GetHex(Byte value)
 
171
{
 
172
  return (wchar_t)((value < 10) ? (L'0' + value) : (L'A' + (value - 10)));
 
173
}
 
174
static inline UString GetHex2(Byte value)
 
175
{
 
176
  UString result;
 
177
  result += GetHex((Byte)(value >> 4));
 
178
  result += GetHex((Byte)(value & 0xF));
 
179
  return result;
 
180
}
 
181
 
 
182
#endif
 
183
 
 
184
static const UInt64 k_AES  = 0x06F10701;
 
185
 
 
186
#ifndef _SFX
 
187
static inline UInt32 GetUInt32FromMemLE(const Byte *p)
 
188
{
 
189
  return p[0] | (((UInt32)p[1]) << 8) | (((UInt32)p[2]) << 16) | (((UInt32)p[3]) << 24);
 
190
}
 
191
#endif
 
192
 
 
193
bool CHandler::IsEncrypted(UInt32 index2) const
 
194
{
 
195
  CNum folderIndex = _database.FileIndexToFolderIndexMap[index2];
 
196
  if (folderIndex != kNumNoIndex)
 
197
  {
 
198
    const CFolder &folderInfo = _database.Folders[folderIndex];
 
199
    for (int i = folderInfo.Coders.Size() - 1; i >= 0; i--)
 
200
      if (folderInfo.Coders[i].MethodID == k_AES)
 
201
        return true;
 
202
  }
 
203
  return false;
 
204
}
 
205
 
 
206
STDMETHODIMP CHandler::GetProperty(UInt32 index, PROPID propID,  PROPVARIANT *value)
 
207
{
 
208
  COM_TRY_BEGIN
 
209
  NWindows::NCOM::CPropVariant prop;
 
210
  
 
211
  /*
 
212
  const CRef2 &ref2 = _refs[index];
 
213
  if (ref2.Refs.IsEmpty())
 
214
    return E_FAIL;
 
215
  const CRef &ref = ref2.Refs.Front();
 
216
  */
 
217
  
 
218
  #ifdef _7Z_VOL
 
219
  const CRef &ref = _refs[index];
 
220
  const CVolume &volume = _volumes[ref.VolumeIndex];
 
221
  const CArchiveDatabaseEx &_database = volume.Database;
 
222
  UInt32 index2 = ref.ItemIndex;
 
223
  const CFileItem &item = _database.Files[index2];
 
224
  #else
 
225
  const CFileItem &item = _database.Files[index];
 
226
  UInt32 index2 = index;
 
227
  #endif
 
228
 
 
229
  switch(propID)
 
230
  {
 
231
    case kpidPath:
 
232
    {
 
233
      if (!item.Name.IsEmpty())
 
234
        prop = NItemName::GetOSName(item.Name);
 
235
      break;
 
236
    }
 
237
    case kpidIsFolder:
 
238
      prop = item.IsDirectory;
 
239
      break;
 
240
    case kpidSize:
 
241
    {
 
242
      prop = item.UnPackSize;
 
243
      // prop = ref2.UnPackSize;
 
244
      break;
 
245
    }
 
246
    case kpidPosition:
 
247
    {
 
248
      /*
 
249
      if (ref2.Refs.Size() > 1)
 
250
        prop = ref2.StartPos;
 
251
      else
 
252
      */
 
253
        if (item.IsStartPosDefined)
 
254
          prop = item.StartPos;
 
255
      break;
 
256
    }
 
257
    case kpidPackedSize:
 
258
    {
 
259
      // prop = ref2.PackSize;
 
260
      {
 
261
        CNum folderIndex = _database.FileIndexToFolderIndexMap[index2];
 
262
        if (folderIndex != kNumNoIndex)
 
263
        {
 
264
          if (_database.FolderStartFileIndex[folderIndex] == (CNum)index2)
 
265
            prop = _database.GetFolderFullPackSize(folderIndex);
 
266
          /*
 
267
          else
 
268
            prop = (UInt64)0;
 
269
          */
 
270
        }
 
271
        else
 
272
          prop = (UInt64)0;
 
273
      }
 
274
      break;
 
275
    }
 
276
    case kpidLastAccessTime:
 
277
      MySetFileTime(item.IsLastAccessTimeDefined, item.LastAccessTime, prop);
 
278
      break;
 
279
    case kpidCreationTime:
 
280
      MySetFileTime(item.IsCreationTimeDefined, item.CreationTime, prop);
 
281
      break;
 
282
    case kpidLastWriteTime:
 
283
      MySetFileTime(item.IsLastWriteTimeDefined, item.LastWriteTime, prop);
 
284
      break;
 
285
    case kpidAttributes:
 
286
      if (item.AreAttributesDefined)
 
287
        prop = item.Attributes;
 
288
      break;
 
289
    case kpidCRC:
 
290
      if (item.IsFileCRCDefined)
 
291
        prop = item.FileCRC;
 
292
      break;
 
293
    case kpidEncrypted:
 
294
    {
 
295
      prop = IsEncrypted(index2);
 
296
      break;
 
297
    }
 
298
    #ifndef _SFX
 
299
    case kpidMethod:
 
300
      {
 
301
        CNum folderIndex = _database.FileIndexToFolderIndexMap[index2];
 
302
        if (folderIndex != kNumNoIndex)
 
303
        {
 
304
          const CFolder &folderInfo = _database.Folders[folderIndex];
 
305
          UString methodsString;
 
306
          for (int i = folderInfo.Coders.Size() - 1; i >= 0; i--)
 
307
          {
 
308
            const CCoderInfo &coderInfo = folderInfo.Coders[i];
 
309
            if (!methodsString.IsEmpty())
 
310
              methodsString += L' ';
 
311
 
 
312
            {
 
313
              UString methodName;
 
314
              bool methodIsKnown = FindMethod(
 
315
                  EXTERNAL_CODECS_VARS 
 
316
                  coderInfo.MethodID, methodName);
 
317
 
 
318
              if (methodIsKnown)
 
319
              {
 
320
                methodsString += methodName;
 
321
                if (coderInfo.MethodID == k_LZMA)
 
322
                {
 
323
                  if (coderInfo.Properties.GetCapacity() >= 5)
 
324
                  {
 
325
                    methodsString += L":";
 
326
                    UInt32 dicSize = GetUInt32FromMemLE(
 
327
                      ((const Byte *)coderInfo.Properties + 1));
 
328
                    methodsString += GetStringForSizeValue(dicSize);
 
329
                  }
 
330
                }
 
331
                else if (coderInfo.MethodID == k_PPMD)
 
332
                {
 
333
                  if (coderInfo.Properties.GetCapacity() >= 5)
 
334
                  {
 
335
                    Byte order = *(const Byte *)coderInfo.Properties;
 
336
                    methodsString += L":o";
 
337
                    methodsString += ConvertUInt32ToString(order);
 
338
                    methodsString += L":mem";
 
339
                    UInt32 dicSize = GetUInt32FromMemLE(
 
340
                      ((const Byte *)coderInfo.Properties + 1));
 
341
                    methodsString += GetStringForSizeValue(dicSize);
 
342
                  }
 
343
                }
 
344
                else if (coderInfo.MethodID == k_AES)
 
345
                {
 
346
                  if (coderInfo.Properties.GetCapacity() >= 1)
 
347
                  {
 
348
                    methodsString += L":";
 
349
                    const Byte *data = (const Byte *)coderInfo.Properties;
 
350
                    Byte firstByte = *data++;
 
351
                    UInt32 numCyclesPower = firstByte & 0x3F;
 
352
                    methodsString += ConvertUInt32ToString(numCyclesPower);
 
353
                    /*
 
354
                    if ((firstByte & 0xC0) != 0)
 
355
                    {
 
356
                      methodsString += L":";
 
357
                      return S_OK;
 
358
                      UInt32 saltSize = (firstByte >> 7) & 1;
 
359
                      UInt32 ivSize = (firstByte >> 6) & 1;
 
360
                      if (coderInfo.Properties.GetCapacity() >= 2)
 
361
                      {
 
362
                        Byte secondByte = *data++;
 
363
                        saltSize += (secondByte >> 4);
 
364
                        ivSize += (secondByte & 0x0F);
 
365
                      }
 
366
                    }
 
367
                    */
 
368
                  }
 
369
                }
 
370
                else
 
371
                {
 
372
                  if (coderInfo.Properties.GetCapacity() > 0)
 
373
                  {
 
374
                    methodsString += L":[";
 
375
                    for (size_t bi = 0; bi < coderInfo.Properties.GetCapacity(); bi++)
 
376
                    {
 
377
                      if (bi > 5 && bi + 1 < coderInfo.Properties.GetCapacity())
 
378
                      {
 
379
                        methodsString += L"..";
 
380
                        break;
 
381
                      }
 
382
                      else
 
383
                        methodsString += GetHex2(coderInfo.Properties[bi]);
 
384
                    }
 
385
                    methodsString += L"]";
 
386
                  }
 
387
                }
 
388
              }
 
389
              else
 
390
              {
 
391
                methodsString += ConvertMethodIdToString(coderInfo.MethodID);
 
392
              }
 
393
            }
 
394
          }
 
395
          prop = methodsString;
 
396
        }
 
397
      }
 
398
      break;
 
399
    case kpidBlock:
 
400
      {
 
401
        CNum folderIndex = _database.FileIndexToFolderIndexMap[index2];
 
402
        if (folderIndex != kNumNoIndex)
 
403
          prop = (UInt32)folderIndex;
 
404
      }
 
405
      break;
 
406
    case kpidPackedSize0:
 
407
    case kpidPackedSize1:
 
408
    case kpidPackedSize2:
 
409
    case kpidPackedSize3:
 
410
    case kpidPackedSize4:
 
411
      {
 
412
        CNum folderIndex = _database.FileIndexToFolderIndexMap[index2];
 
413
        if (folderIndex != kNumNoIndex)
 
414
        {
 
415
          const CFolder &folderInfo = _database.Folders[folderIndex];
 
416
          if (_database.FolderStartFileIndex[folderIndex] == (CNum)index2 &&
 
417
              folderInfo.PackStreams.Size() > (int)(propID - kpidPackedSize0))
 
418
          {
 
419
            prop = _database.GetFolderPackStreamSize(folderIndex, propID - kpidPackedSize0);
 
420
          }
 
421
          else
 
422
            prop = (UInt64)0;
 
423
        }
 
424
        else
 
425
          prop = (UInt64)0;
 
426
      }
 
427
      break;
 
428
    #endif
 
429
    case kpidIsAnti:
 
430
      prop = item.IsAnti;
 
431
      break;
 
432
  }
 
433
  prop.Detach(value);
 
434
  return S_OK;
 
435
  COM_TRY_END
 
436
}
 
437
 
 
438
#ifdef _7Z_VOL
 
439
 
 
440
static const wchar_t *kExt = L"7z";
 
441
static const wchar_t *kAfterPart = L".7z";
 
442
 
 
443
class CVolumeName
 
444
{
 
445
  bool _first;
 
446
  UString _unchangedPart;
 
447
  UString _changedPart;    
 
448
  UString _afterPart;    
 
449
public:
 
450
  bool InitName(const UString &name)
 
451
  {
 
452
    _first = true;
 
453
    int dotPos = name.ReverseFind('.');
 
454
    UString basePart = name;
 
455
    if (dotPos >= 0)
 
456
    {
 
457
      UString ext = name.Mid(dotPos + 1);
 
458
      if (ext.CompareNoCase(kExt)==0 || 
 
459
        ext.CompareNoCase(L"EXE") == 0)
 
460
      {
 
461
        _afterPart = kAfterPart;
 
462
        basePart = name.Left(dotPos);
 
463
      }
 
464
    }
 
465
 
 
466
    int numLetters = 1;
 
467
    bool splitStyle = false;
 
468
    if (basePart.Right(numLetters) == L"1")
 
469
    {
 
470
      while (numLetters < basePart.Length())
 
471
      {
 
472
        if (basePart[basePart.Length() - numLetters - 1] != '0')
 
473
          break;
 
474
        numLetters++;
 
475
      }
 
476
    }
 
477
    else 
 
478
      return false;
 
479
    _unchangedPart = basePart.Left(basePart.Length() - numLetters);
 
480
    _changedPart = basePart.Right(numLetters);
 
481
    return true;
 
482
  }
 
483
 
 
484
  UString GetNextName()
 
485
  {
 
486
    UString newName; 
 
487
    // if (_newStyle || !_first)
 
488
    {
 
489
      int i;
 
490
      int numLetters = _changedPart.Length();
 
491
      for (i = numLetters - 1; i >= 0; i--)
 
492
      {
 
493
        wchar_t c = _changedPart[i];
 
494
        if (c == L'9')
 
495
        {
 
496
          c = L'0';
 
497
          newName = c + newName;
 
498
          if (i == 0)
 
499
            newName = UString(L'1') + newName;
 
500
          continue;
 
501
        }
 
502
        c++;
 
503
        newName = UString(c) + newName;
 
504
        i--;
 
505
        for (; i >= 0; i--)
 
506
          newName = _changedPart[i] + newName;
 
507
        break;
 
508
      }
 
509
      _changedPart = newName;
 
510
    }
 
511
    _first = false;
 
512
    return _unchangedPart + _changedPart + _afterPart;
 
513
  }
 
514
};
 
515
 
 
516
#endif
 
517
 
 
518
STDMETHODIMP CHandler::Open(IInStream *stream,
 
519
    const UInt64 *maxCheckStartPosition, 
 
520
    IArchiveOpenCallback *openArchiveCallback)
 
521
{
 
522
  COM_TRY_BEGIN
 
523
  Close();
 
524
  #ifndef _SFX
 
525
  _fileInfoPopIDs.Clear();
 
526
  #endif
 
527
  try
 
528
  {
 
529
    CMyComPtr<IArchiveOpenCallback> openArchiveCallbackTemp = openArchiveCallback;
 
530
    #ifdef _7Z_VOL
 
531
    CVolumeName seqName;
 
532
 
 
533
    CMyComPtr<IArchiveOpenVolumeCallback> openVolumeCallback;
 
534
    #endif
 
535
 
 
536
    #ifndef _NO_CRYPTO
 
537
    CMyComPtr<ICryptoGetTextPassword> getTextPassword;
 
538
    if (openArchiveCallback)
 
539
    {
 
540
      openArchiveCallbackTemp.QueryInterface(
 
541
          IID_ICryptoGetTextPassword, &getTextPassword);
 
542
    }
 
543
    #endif
 
544
    #ifdef _7Z_VOL
 
545
    if (openArchiveCallback)
 
546
    {
 
547
      openArchiveCallbackTemp.QueryInterface(IID_IArchiveOpenVolumeCallback, &openVolumeCallback);
 
548
    }
 
549
    for (;;)
 
550
    {
 
551
      CMyComPtr<IInStream> inStream;
 
552
      if (!_volumes.IsEmpty())
 
553
      {
 
554
        if (!openVolumeCallback)
 
555
          break;
 
556
        if(_volumes.Size() == 1)
 
557
        {
 
558
          UString baseName;
 
559
          {
 
560
            NCOM::CPropVariant prop;
 
561
            RINOK(openVolumeCallback->GetProperty(kpidName, &prop));
 
562
            if (prop.vt != VT_BSTR)
 
563
              break;
 
564
            baseName = prop.bstrVal;
 
565
          }
 
566
          seqName.InitName(baseName);
 
567
        }
 
568
 
 
569
        UString fullName = seqName.GetNextName();
 
570
        HRESULT result = openVolumeCallback->GetStream(fullName, &inStream);
 
571
        if (result == S_FALSE)
 
572
          break;
 
573
        if (result != S_OK)
 
574
          return result;
 
575
        if (!stream)
 
576
          break;
 
577
      }
 
578
      else
 
579
        inStream = stream;
 
580
 
 
581
      CInArchive archive;
 
582
      RINOK(archive.Open(inStream, maxCheckStartPosition));
 
583
 
 
584
      _volumes.Add(CVolume());
 
585
      CVolume &volume = _volumes.Back();
 
586
      CArchiveDatabaseEx &database = volume.Database;
 
587
      volume.Stream = inStream;
 
588
      volume.StartRef2Index = _refs.Size();
 
589
 
 
590
      HRESULT result = archive.ReadDatabase(database
 
591
          #ifndef _NO_CRYPTO
 
592
          , getTextPassword
 
593
          #endif
 
594
          );
 
595
      if (result != S_OK)
 
596
      {
 
597
        _volumes.Clear();
 
598
        return result;
 
599
      }
 
600
      database.Fill();
 
601
      for(int i = 0; i < database.Files.Size(); i++)
 
602
      {
 
603
        CRef refNew;
 
604
        refNew.VolumeIndex = _volumes.Size() - 1;
 
605
        refNew.ItemIndex = i;
 
606
        _refs.Add(refNew);
 
607
        /*
 
608
        const CFileItem &file = database.Files[i];
 
609
        int j;
 
610
        */
 
611
        /*
 
612
        for (j = _refs.Size() - 1; j >= 0; j--)
 
613
        {
 
614
          CRef2 &ref2 = _refs[j];
 
615
          const CRef &ref = ref2.Refs.Back();
 
616
          const CVolume &volume2 = _volumes[ref.VolumeIndex];
 
617
          const CArchiveDatabaseEx &database2 = volume2.Database;
 
618
          const CFileItem &file2 = database2.Files[ref.ItemIndex];
 
619
          if (file2.Name.CompareNoCase(file.Name) == 0)
 
620
          {
 
621
            if (!file.IsStartPosDefined)
 
622
              continue;
 
623
            if (file.StartPos != ref2.StartPos + ref2.UnPackSize)
 
624
              continue;
 
625
            ref2.Refs.Add(refNew);
 
626
            break;
 
627
          }
 
628
        }
 
629
        */
 
630
        /*
 
631
        j = -1;
 
632
        if (j < 0)
 
633
        {
 
634
          CRef2 ref2New;
 
635
          ref2New.Refs.Add(refNew);
 
636
          j = _refs.Add(ref2New);
 
637
        }
 
638
        CRef2 &ref2 = _refs[j];
 
639
        ref2.UnPackSize += file.UnPackSize;
 
640
        ref2.PackSize += database.GetFilePackSize(i);
 
641
        if (ref2.Refs.Size() == 1 && file.IsStartPosDefined)
 
642
          ref2.StartPos = file.StartPos;
 
643
        */
 
644
      }
 
645
      if (database.Files.Size() != 1)
 
646
        break;
 
647
      const CFileItem &file = database.Files.Front();
 
648
      if (!file.IsStartPosDefined)
 
649
        break;
 
650
    }
 
651
    #else
 
652
    CInArchive archive;
 
653
    RINOK(archive.Open(stream, maxCheckStartPosition));
 
654
    HRESULT result = archive.ReadDatabase(
 
655
      EXTERNAL_CODECS_VARS
 
656
      _database
 
657
      #ifndef _NO_CRYPTO
 
658
      , getTextPassword
 
659
      #endif
 
660
      );
 
661
    RINOK(result);
 
662
    _database.Fill();
 
663
    _inStream = stream;
 
664
    #endif
 
665
  }
 
666
  catch(...)
 
667
  {
 
668
    Close();
 
669
    return S_FALSE;
 
670
  }
 
671
  // _inStream = stream;
 
672
  #ifndef _SFX
 
673
  FillPopIDs();
 
674
  #endif
 
675
  return S_OK;
 
676
  COM_TRY_END
 
677
}
 
678
 
 
679
STDMETHODIMP CHandler::Close()
 
680
{
 
681
  COM_TRY_BEGIN
 
682
  #ifdef _7Z_VOL
 
683
  _volumes.Clear();
 
684
  _refs.Clear();
 
685
  #else
 
686
  _inStream.Release();
 
687
  _database.Clear();
 
688
  #endif
 
689
  return S_OK;
 
690
  COM_TRY_END
 
691
}
 
692
 
 
693
#ifdef _7Z_VOL
 
694
STDMETHODIMP CHandler::GetStream(UInt32 index, ISequentialInStream **stream)
 
695
{
 
696
  if (index != 0)
 
697
    return E_INVALIDARG;
 
698
  *stream = 0;
 
699
  CMultiStream *streamSpec = new CMultiStream;
 
700
  CMyComPtr<ISequentialInStream> streamTemp = streamSpec;
 
701
  
 
702
  UInt64 pos = 0;
 
703
  const UString *fileName;
 
704
  for (int i = 0; i < _refs.Size(); i++)
 
705
  {
 
706
    const CRef &ref = _refs[i];
 
707
    const CVolume &volume = _volumes[ref.VolumeIndex];
 
708
    const CArchiveDatabaseEx &database = volume.Database;
 
709
    const CFileItem &file = database.Files[ref.ItemIndex];
 
710
    if (i == 0)
 
711
      fileName = &file.Name;
 
712
    else
 
713
      if (fileName->Compare(file.Name) != 0)
 
714
        return S_FALSE;
 
715
    if (!file.IsStartPosDefined)
 
716
      return S_FALSE;
 
717
    if (file.StartPos != pos)
 
718
      return S_FALSE;
 
719
    CNum folderIndex = database.FileIndexToFolderIndexMap[ref.ItemIndex];
 
720
    if (folderIndex == kNumNoIndex)
 
721
    {
 
722
      if (file.UnPackSize != 0)
 
723
        return E_FAIL;
 
724
      continue;
 
725
    }
 
726
    if (database.NumUnPackStreamsVector[folderIndex] != 1)
 
727
      return S_FALSE;
 
728
    const CFolder &folder = database.Folders[folderIndex];
 
729
    if (folder.Coders.Size() != 1)
 
730
      return S_FALSE;
 
731
    const CCoderInfo &coder = folder.Coders.Front();
 
732
    if (coder.NumInStreams != 1 || coder.NumOutStreams != 1)
 
733
      return S_FALSE;
 
734
    if (coder.MethodID != k_Copy)
 
735
      return S_FALSE;
 
736
 
 
737
    pos += file.UnPackSize;
 
738
    CMultiStream::CSubStreamInfo subStreamInfo;
 
739
    subStreamInfo.Stream = volume.Stream;
 
740
    subStreamInfo.Pos = database.GetFolderStreamPos(folderIndex, 0);
 
741
    subStreamInfo.Size = file.UnPackSize;
 
742
    streamSpec->Streams.Add(subStreamInfo);
 
743
  }
 
744
  streamSpec->Init();
 
745
  *stream = streamTemp.Detach();
 
746
  return S_OK;
 
747
}
 
748
#endif
 
749
 
 
750
 
 
751
#ifdef __7Z_SET_PROPERTIES
 
752
#ifdef EXTRACT_ONLY
 
753
 
 
754
STDMETHODIMP CHandler::SetProperties(const wchar_t **names, const PROPVARIANT *values, Int32 numProperties)
 
755
{
 
756
  COM_TRY_BEGIN
 
757
  #ifdef COMPRESS_MT
 
758
  const UInt32 numProcessors = NSystem::GetNumberOfProcessors();
 
759
  _numThreads = numProcessors;
 
760
  #endif
 
761
 
 
762
  for (int i = 0; i < numProperties; i++)
 
763
  {
 
764
    UString name = names[i];
 
765
    name.MakeUpper();
 
766
    if (name.IsEmpty())
 
767
      return E_INVALIDARG;
 
768
    const PROPVARIANT &value = values[i];
 
769
    UInt32 number;
 
770
    int index = ParseStringToUInt32(name, number);
 
771
    if (index == 0)
 
772
    {
 
773
      if(name.Left(2).CompareNoCase(L"MT") == 0)
 
774
      {
 
775
        #ifdef COMPRESS_MT
 
776
        RINOK(ParseMtProp(name.Mid(2), value, numProcessors, _numThreads));
 
777
        #endif
 
778
        continue;
 
779
      }
 
780
      else
 
781
        return E_INVALIDARG;
 
782
    }
 
783
  }
 
784
  return S_OK;
 
785
  COM_TRY_END
 
786
}  
 
787
 
 
788
#endif
 
789
#endif
 
790
 
 
791
IMPL_ISetCompressCodecsInfo
 
792
 
 
793
}}