Beispiel #1
3
		/*!
		 * \brief
		 * Decompresses a single file entry from a 7zip archive, into memory.
		 * 
		 * \param archive_stream
		 * The stream to read the compressed data from.
		 * 
		 * \param archive_desc
		 * The archives description struct.
		 * 
		 * \param look_stream
		 * The stream associated with the archive stream.
		 * 
		 * \param file_index
		 * Index of the file to extract.
		 * 
		 * \param uncompressed_data
		 * The pointer reference to set when allocating memory for the uncompressed data.
		 * 
		 * \param uncompressed_data_size
		 * Reference to set the uncompressed datas size to.
		 * 
		 * \returns
		 * Returns SZ_OK if decompression was successfully, otherwise returns a non-zero value.
		 * 
		 * Decompresses a single file entry from a 7zip archive, into memory.
		 */
		static SRes Decompress(CFileInStream& archive_stream,
			CSzArEx& archive_desc,
			CLookToRead& look_stream,
			uint32 file_index,
			byte*& uncompressed_data,
			size_t& uncompressed_data_size)
		{
			ISzAlloc alloc_imp;
			SRes result = SZ_OK;

			// set functions 7zip will use to allocated and free memory
			alloc_imp.Alloc = AllocFunc;
			alloc_imp.Free = FreeFunc;

			UInt32 block_index = 0xFFFFFFFF;
			size_t offset = 0;
			size_t out_size_processed = 0;

			// decompress the requested file, saving the uncompressed data into memory
			result = SzArEx_Extract(&archive_desc, &look_stream.s, file_index,
				&block_index, &uncompressed_data, &uncompressed_data_size,
				&offset, &out_size_processed,
				&alloc_imp, &alloc_imp);

			if (result != SZ_OK)
			{
				// the decompression failed, so delete the allocated data
				IAlloc_Free(&alloc_imp, uncompressed_data);
				uncompressed_data = NULL;

				uncompressed_data_size = 0;
			}

			return result;
		}
Beispiel #2
0
void SzFolder_Free(CSzFolder *p, ISzAlloc *alloc)
{
   uint32_t i;
   if (p->Coders)
      for (i = 0; i < p->NumCoders; i++)
         SzCoderInfo_Free(&p->Coders[i], alloc);
   IAlloc_Free(alloc, p->Coders);
   IAlloc_Free(alloc, p->BindPairs);
   IAlloc_Free(alloc, p->PackStreams);
   IAlloc_Free(alloc, p->UnpackSizes);
   SzFolder_Init(p);
}
Beispiel #3
0
void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc)
{
   IAlloc_Free(alloc, p->FolderStartPackStreamIndex);
   IAlloc_Free(alloc, p->PackStreamStartPositions);
   IAlloc_Free(alloc, p->FolderStartFileIndex);
   IAlloc_Free(alloc, p->FileIndexToFolderIndexMap);

   IAlloc_Free(alloc, p->FileNameOffsets);
   Buf_Free(&p->FileNames, alloc);

   SzAr_Free(&p->db, alloc);
   SzArEx_Init(p);
}
Beispiel #4
0
void SzAr_Free(CSzAr *p, ISzAlloc *alloc)
{
   uint32_t i;
   if (p->Folders)
      for (i = 0; i < p->NumFolders; i++)
         SzFolder_Free(&p->Folders[i], alloc);

   IAlloc_Free(alloc, p->PackSizes);
   IAlloc_Free(alloc, p->PackCRCsDefined);
   IAlloc_Free(alloc, p->PackCRCs);
   IAlloc_Free(alloc, p->Folders);
   IAlloc_Free(alloc, p->Files);
   SzAr_Init(p);
}
Beispiel #5
0
 ~Qt7zPackagePrivate()
 {
     if (m_outBuffer) {
         IAlloc_Free(&m_allocImp, m_outBuffer);
         m_outBuffer = 0;
     }
 }
Beispiel #6
0
static void _7z_close(ar_archive *ar)
{
    ar_archive_7z *_7z = (ar_archive_7z *)ar;
    free(_7z->entry_name);
    SzArEx_Free(&_7z->data, &gSzAlloc);
    IAlloc_Free(&gSzAlloc, _7z->uncomp.buffer);
}
Beispiel #7
0
	~C7zArchive()
	{
		if (OutBuffer != NULL)
		{
			IAlloc_Free(&g_Alloc, OutBuffer);
		}
		SzArEx_Free(&DB, &g_Alloc);
	}
Beispiel #8
0
static void CMtThread_Destruct(CMtThread *p)
{
  CMtThread_CloseEvents(p);

  if (Thread_WasCreated(&p->thread.thread))
  {
    LoopThread_StopAndWait(&p->thread);
    LoopThread_Close(&p->thread);
  }

  if (p->mtCoder->alloc)
    IAlloc_Free(p->mtCoder->alloc, p->outBuf);
  p->outBuf = 0;

  if (p->mtCoder->alloc)
    IAlloc_Free(p->mtCoder->alloc, p->inBuf);
  p->inBuf = 0;
}
Beispiel #9
0
CArchive7Zip::~CArchive7Zip()
{
	if (outBuffer) {
		IAlloc_Free(&allocImp, outBuffer);
	}
	if (isOpen) {
		File_Close(&archiveStream.file);
	}
	SzArEx_Free(&db, &allocImp);
}
Beispiel #10
0
static SRes SzReadAndDecodePackedStreams(
      ILookInStream *inStream,
      CSzData *sd,
      CBuf *outBuffer,
      uint64_t baseOffset,
      ISzAlloc *allocTemp)
{
   CSzAr p;
   uint64_t *unpackSizes = 0;
   uint8_t *digestsDefined = 0;
   uint32_t *digests = 0;
   SRes res;
   SzAr_Init(&p);
   res = SzReadAndDecodePackedStreams2(inStream, sd, outBuffer, baseOffset,
         &p, &unpackSizes, &digestsDefined, &digests,
         allocTemp);
   SzAr_Free(&p, allocTemp);
   IAlloc_Free(allocTemp, unpackSizes);
   IAlloc_Free(allocTemp, digestsDefined);
   IAlloc_Free(allocTemp, digests);
   return res;
}
Beispiel #11
0
static SRes SzReadAndDecodePackedStreams(
    ISeekInStream *inStream,
    CSzData *sd,
    ISeqOutStream *outStream,
    UInt64 baseOffset,
    ISzAlloc *allocTemp)
{
  CSzAr p;
  UInt64 *unpackSizes = 0;
  Byte *digestsDefined = 0;
  UInt32 *digests = 0;
  SRes res;
  SzAr_Init(&p);
  res = SzReadAndDecodePackedStreams2(inStream, sd, outStream, baseOffset,
    &p, &unpackSizes, &digestsDefined, &digests,
    allocTemp);
  SzAr_Free(&p, allocTemp);
  IAlloc_Free(allocTemp, unpackSizes);
  IAlloc_Free(allocTemp, digestsDefined);
  IAlloc_Free(allocTemp, digests);
  return res;
}
Beispiel #12
0
void Qt7zPackagePrivate::reset()
{
    m_packagePath.clear();
    m_isOpen = false;
    m_fileNameList.clear();
    m_fileInfoList.clear();

    m_blockIndex = 0xFFFFFFFF;
    if (m_outBuffer) {
        IAlloc_Free(&m_allocImp, m_outBuffer);
        m_outBufferSize = 0;
    }
}
Beispiel #13
0
void
SzArEx_DictCache_free(SzArEx_DictCache *dictCache)
{
  if (dictCache->mapFile) {
    // unmap memory
    SzArEx_DictCache_munmap(dictCache);
    // close file handle (it will be set to NULL in init method)
    // FIXME: can we close the FILE* and just hold on to the mmap pointer? I think
    // that will keep the fd open until the mapping is closed.
    fclose(dictCache->mapFile);
  } else if (dictCache->outBuffer != 0) {
    // free memory that was allocated on the heap
    IAlloc_Free(dictCache->allocMain, dictCache->outBuffer);
  }
  SzArEx_DictCache_init(dictCache, dictCache->allocMain);
}
Beispiel #14
0
static void sevenzip_stream_free(void *data)
{
   struct sevenzip_context_t *sevenzip_context = (struct sevenzip_context_t*)data;

   if (!sevenzip_context)
      return;

   if (sevenzip_context->output)
   {
      IAlloc_Free(&sevenzip_context->allocImp, sevenzip_context->output);
      sevenzip_context->output = NULL;
      sevenzip_context->handle->data = NULL;
   }

   SzArEx_Free(&sevenzip_context->db, &sevenzip_context->allocImp);
   File_Close(&sevenzip_context->archiveStream.file);
}
Beispiel #15
0
static void SzAr_Free(CSzAr *p, ISzAlloc *alloc)
{
  IAlloc_Free(alloc, p->PackPositions);
  SzBitUi32s_Free(&p->FolderCRCs, alloc);
 
  IAlloc_Free(alloc, p->FoCodersOffsets);
  IAlloc_Free(alloc, p->FoStartPackStreamIndex);
  IAlloc_Free(alloc, p->FoToCoderUnpackSizes);
  IAlloc_Free(alloc, p->FoToMainUnpackSizeIndex);
  IAlloc_Free(alloc, p->CoderUnpackSizes);
  
  IAlloc_Free(alloc, p->CodersData);

  SzAr_Init(p);
}
Beispiel #16
0
static void free__7z_file(_7z_file *_7z)
{
	if (_7z != NULL)
	{
		if (_7z->archiveStream.file._7z_osdfile != NULL)
			osd_close(_7z->archiveStream.file._7z_osdfile);
		if (_7z->filename != NULL)
			free((void *)_7z->filename);


		if (_7z->outBuffer) IAlloc_Free(&_7z->allocImp, _7z->outBuffer);
		if (_7z->inited) SzArEx_Free(&_7z->db, &_7z->allocImp);


		free(_7z);
	}
}
Beispiel #17
0
CBuf* SZFilePack::openFile(const char* fileName)
{
	char szFileName[MAX_PATH+1] = "";
	strncpy(szFileName, fileName, MAX_PATH);
	NormalFileName(szFileName);
	_strlwr(szFileName);

	FileIndexMap::iterator itFind = mIndexMap.find(szFileName);
	if (itFind == mIndexMap.end())
		return NULL;

	//if you need cache, use these 3 variables.
	//if you use external function, you can make these variable as static.
	UInt32 blockIndex = 0xFFFFFFFF; // it can have any value before first call (if outBuffer = 0)
	Byte *outBuffer = 0; // it must be 0 before first call for each new archive.
	size_t outBufferSize = 0;  // it can have any value before first call (if outBuffer = 0)
	size_t offset = 0;
	size_t outSizeProcessed = 0;
	SRes res;

	size_t index = itFind->second;
	res = SzArEx_Extract(&mDb, &mLookStream.s, index,
		&blockIndex, &outBuffer, &outBufferSize,
		&offset, &outSizeProcessed,
		&mAllocImp, &mAllocTempImp);
	if (res != SZ_OK)
		return NULL;

	closeFile();
	mFileBuffer = new CBuf;
	mFileBuffer->data = new byte[outSizeProcessed];
	memcpy(mFileBuffer->data, outBuffer+offset, outSizeProcessed);
	mFileBuffer->size = outSizeProcessed;

	IAlloc_Free(&mAllocImp, outBuffer);

	return mFileBuffer;
}
Beispiel #18
0
void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc)
{
  IAlloc_Free(alloc, p->UnpackPositions);
  IAlloc_Free(alloc, p->IsDirs);

  IAlloc_Free(alloc, p->FolderToFile);
  IAlloc_Free(alloc, p->FileToFolder);

  IAlloc_Free(alloc, p->FileNameOffsets);
  IAlloc_Free(alloc, p->FileNames);

  SzBitUi32s_Free(&p->CRCs, alloc);
  SzBitUi32s_Free(&p->Attribs, alloc);
  // SzBitUi32s_Free(&p->Parents, alloc);
  SzBitUi64s_Free(&p->MTime, alloc);
  SzBitUi64s_Free(&p->CTime, alloc);
  
  SzAr_Free(&p->db, alloc);
  SzArEx_Init(p);
}
Beispiel #19
0
void SzArEx_Free(CSzArEx *p, ISzAlloc *alloc)
{
  // IAlloc_Free(alloc, p->FolderStartPackStreamIndex);
  // IAlloc_Free(alloc, p->PackStreamStartPositions);
  IAlloc_Free(alloc, p->FolderStartFileIndex);
  IAlloc_Free(alloc, p->FileIndexToFolderIndexMap);

  IAlloc_Free(alloc, p->FileNameOffsets);
  IAlloc_Free(alloc, p->FileNames);

  SzBitUi64s_Free(&p->CTime, alloc);
  SzBitUi64s_Free(&p->MTime, alloc);
  SzBitUi32s_Free(&p->CRCs, alloc);
  // SzBitUi32s_Free(&p->Parents, alloc);
  SzBitUi32s_Free(&p->Attribs, alloc);
  IAlloc_Free(alloc, p->IsDirs);
  // IAlloc_Free(alloc, p->IsEmptyFiles);
  IAlloc_Free(alloc, p->UnpackPositions);
  // IAlloc_Free(alloc, p->Files);

  SzAr_Free(&p->db, alloc);
  SzArEx_Init(p);
}
Beispiel #20
0
static SRes SzReadHeader(
      CSzArEx *p,
      CSzData *sd,
      ISzAlloc *allocMain,
      ISzAlloc *allocTemp)
{
   uint64_t *unpackSizes = 0;
   uint8_t *digestsDefined = 0;
   uint32_t *digests = 0;
   uint8_t *emptyStreamVector = 0;
   uint8_t *emptyFileVector = 0;
   uint8_t *lwtVector = 0;
   SRes res = SzReadHeader2(p, sd,
         &unpackSizes, &digestsDefined, &digests,
         &emptyStreamVector, &emptyFileVector, &lwtVector,
         allocMain, allocTemp);
   IAlloc_Free(allocTemp, unpackSizes);
   IAlloc_Free(allocTemp, digestsDefined);
   IAlloc_Free(allocTemp, digests);
   IAlloc_Free(allocTemp, emptyStreamVector);
   IAlloc_Free(allocTemp, emptyFileVector);
   IAlloc_Free(allocTemp, lwtVector);
   return res;
}
Beispiel #21
0
int MY_CDECL main(int numargs, char *args[])
{
  CFileInStream archiveStream;
  CLookToRead lookStream;
  CSzArEx db;
  SRes res;
  ISzAlloc allocImp;
  ISzAlloc allocTempImp;
  UInt16 *temp = NULL;
  size_t tempSize = 0;
  // UInt32 parents[NUM_PARENTS_MAX];

  printf("\n7z ANSI-C Decoder " MY_VERSION_COPYRIGHT_DATE "\n\n");

  if (numargs == 1)
  {
    printf(
      "Usage: 7zDec <command> <archive_name>\n\n"
      "<Commands>\n"
      "  e: Extract files from archive (without using directory names)\n"
      "  l: List contents of archive\n"
      "  t: Test integrity of archive\n"
      "  x: eXtract files with full paths\n");
    return 0;
  }
  
  if (numargs < 3)
  {
    PrintError("incorrect command");
    return 1;
  }

  #if defined(_WIN32) && !defined(USE_WINDOWS_FILE) && !defined(UNDER_CE)
  g_FileCodePage = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
  #endif

  allocImp.Alloc = SzAlloc;
  allocImp.Free = SzFree;

  allocTempImp.Alloc = SzAllocTemp;
  allocTempImp.Free = SzFreeTemp;

  #ifdef UNDER_CE
  if (InFile_OpenW(&archiveStream.file, L"\test.7z"))
  #else
  if (InFile_Open(&archiveStream.file, args[2]))
  #endif
  {
    PrintError("can not open input file");
    return 1;
  }

  FileInStream_CreateVTable(&archiveStream);
  LookToRead_CreateVTable(&lookStream, False);
  
  lookStream.realStream = &archiveStream.s;
  LookToRead_Init(&lookStream);

  CrcGenerateTable();

  SzArEx_Init(&db);
  
  res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp);
  
  if (res == SZ_OK)
  {
    char *command = args[1];
    int listCommand = 0, testCommand = 0, fullPaths = 0;
    
    if (strcmp(command, "l") == 0) listCommand = 1;
    else if (strcmp(command, "t") == 0) testCommand = 1;
    else if (strcmp(command, "e") == 0) { }
    else if (strcmp(command, "x") == 0) { fullPaths = 1; }
    else
    {
      PrintError("incorrect command");
      res = SZ_ERROR_FAIL;
    }

    if (res == SZ_OK)
    {
      UInt32 i;

      /*
      if you need cache, use these 3 variables.
      if you use external function, you can make these variable as static.
      */
      UInt32 blockIndex = 0xFFFFFFFF; /* it can have any value before first call (if outBuffer = 0) */
      Byte *outBuffer = 0; /* it must be 0 before first call for each new archive. */
      size_t outBufferSize = 0;  /* it can have any value before first call (if outBuffer = 0) */

      for (i = 0; i < db.NumFiles; i++)
      {
        size_t offset = 0;
        size_t outSizeProcessed = 0;
        // const CSzFileItem *f = db.Files + i;
        size_t len;
        unsigned isDir = SzArEx_IsDir(&db, i);
        if (listCommand == 0 && isDir && !fullPaths)
          continue;
        len = SzArEx_GetFileNameUtf16(&db, i, NULL);
        // len = SzArEx_GetFullNameLen(&db, i);

        if (len > tempSize)
        {
          SzFree(NULL, temp);
          tempSize = len;
          temp = (UInt16 *)SzAlloc(NULL, tempSize * sizeof(temp[0]));
          if (!temp)
          {
            res = SZ_ERROR_MEM;
            break;
          }
        }

        SzArEx_GetFileNameUtf16(&db, i, temp);
        /*
        if (SzArEx_GetFullNameUtf16_Back(&db, i, temp + len) != temp)
        {
          res = SZ_ERROR_FAIL;
          break;
        }
        */

        if (listCommand)
        {
          char attr[8], s[32], t[32];
          UInt64 fileSize;

          GetAttribString(SzBitWithVals_Check(&db.Attribs, i) ? db.Attribs.Vals[i] : 0, isDir, attr);

          fileSize = SzArEx_GetFileSize(&db, i);
          UInt64ToStr(fileSize, s);
          
          if (SzBitWithVals_Check(&db.MTime, i))
            ConvertFileTimeToString(&db.MTime.Vals[i], t);
          else
          {
            size_t j;
            for (j = 0; j < 19; j++)
              t[j] = ' ';
            t[j] = '\0';
          }
          
          printf("%s %s %10s  ", t, attr, s);
          res = PrintString(temp);
          if (res != SZ_OK)
            break;
          if (isDir)
            printf("/");
          printf("\n");
          continue;
        }

        fputs(testCommand ?
            "Testing    ":
            "Extracting ",
            stdout);
        res = PrintString(temp);
        if (res != SZ_OK)
          break;
        
        if (isDir)
          printf("/");
        else
        {
          res = SzArEx_Extract(&db, &lookStream.s, i,
              &blockIndex, &outBuffer, &outBufferSize,
              &offset, &outSizeProcessed,
              &allocImp, &allocTempImp);
          if (res != SZ_OK)
            break;
        }
        
        if (!testCommand)
        {
          CSzFile outFile;
          size_t processedSize;
          size_t j;
          UInt16 *name = (UInt16 *)temp;
          const UInt16 *destPath = (const UInt16 *)name;
 
          for (j = 0; name[j] != 0; j++)
            if (name[j] == '/')
            {
              if (fullPaths)
              {
                name[j] = 0;
                MyCreateDir(name);
                name[j] = CHAR_PATH_SEPARATOR;
              }
              else
                destPath = name + j + 1;
            }
    
          if (isDir)
          {
            MyCreateDir(destPath);
            printf("\n");
            continue;
          }
          else if (OutFile_OpenUtf16(&outFile, destPath))
          {
            PrintError("can not open output file");
            res = SZ_ERROR_FAIL;
            break;
          }

          processedSize = outSizeProcessed;
          
          if (File_Write(&outFile, outBuffer + offset, &processedSize) != 0 || processedSize != outSizeProcessed)
          {
            PrintError("can not write output file");
            res = SZ_ERROR_FAIL;
            break;
          }
          
          if (File_Close(&outFile))
          {
            PrintError("can not close output file");
            res = SZ_ERROR_FAIL;
            break;
          }
          
          #ifdef USE_WINDOWS_FILE
          if (SzBitWithVals_Check(&db.Attribs, i))
            SetFileAttributesW(destPath, db.Attribs.Vals[i]);
          #endif
        }
        printf("\n");
      }
      IAlloc_Free(&allocImp, outBuffer);
    }
  }

  SzArEx_Free(&db, &allocImp);
  SzFree(NULL, temp);

  File_Close(&archiveStream.file);
  
  if (res == SZ_OK)
  {
    printf("\nEverything is Ok\n");
    return 0;
  }
  
  if (res == SZ_ERROR_UNSUPPORTED)
    PrintError("decoder doesn't support this archive");
  else if (res == SZ_ERROR_MEM)
    PrintError("can not allocate memory");
  else if (res == SZ_ERROR_CRC)
    PrintError("CRC error");
  else
    printf("\nERROR #%d\n", res);
  
  return 1;
}
Beispiel #22
0
static SRes SzReadHeader2(
      CSzArEx *p,   /* allocMain */
      CSzData *sd,
      uint64_t **unpackSizes,  /* allocTemp */
      uint8_t **digestsDefined,    /* allocTemp */
      uint32_t **digests,         /* allocTemp */
      uint8_t **emptyStreamVector, /* allocTemp */
      uint8_t **emptyFileVector,   /* allocTemp */
      uint8_t **lwtVector,         /* allocTemp */
      ISzAlloc *allocMain,
      ISzAlloc *allocTemp)
{
   uint64_t type;
   uint32_t numUnpackStreams = 0;
   uint32_t numFiles = 0;
   CSzFileItem *files = 0;
   uint32_t numEmptyStreams = 0;
   uint32_t i;

   RINOK(SzReadID(sd, &type));

   if (type == k7zIdArchiveProperties)
   {
      RINOK(SzReadArchiveProperties(sd));
      RINOK(SzReadID(sd, &type));
   }


   if (type == k7zIdMainStreamsInfo)
   {
      RINOK(SzReadStreamsInfo(sd,
               &p->dataPos,
               &p->db,
               &numUnpackStreams,
               unpackSizes,
               digestsDefined,
               digests, allocMain, allocTemp));
      p->dataPos += p->startPosAfterHeader;
      RINOK(SzReadID(sd, &type));
   }

   if (type == k7zIdEnd)
      return SZ_OK;
   if (type != k7zIdFilesInfo)
      return SZ_ERROR_ARCHIVE;

   RINOK(SzReadNumber32(sd, &numFiles));
   p->db.NumFiles = numFiles;

   MY_ALLOC(CSzFileItem, files, (size_t)numFiles, allocMain);

   p->db.Files = files;
   for (i = 0; i < numFiles; i++)
      SzFile_Init(files + i);

   for (;;)
   {
      uint64_t size;
      RINOK(SzReadID(sd, &type));
      if (type == k7zIdEnd)
         break;
      RINOK(SzReadNumber(sd, &size));
      if (size > sd->Size)
         return SZ_ERROR_ARCHIVE;
      if ((uint64_t)(int)type != type)
      {
         RINOK(SzSkeepDataSize(sd, size));
      }
      else
         switch((int)type)
         {
            case k7zIdName:
               {
                  size_t namesSize;
                  RINOK(SzReadSwitch(sd));
                  namesSize = (size_t)size - 1;
                  if ((namesSize & 1) != 0)
                     return SZ_ERROR_ARCHIVE;
                  if (!Buf_Create(&p->FileNames, namesSize, allocMain))
                     return SZ_ERROR_MEM;
                  MY_ALLOC(size_t, p->FileNameOffsets, numFiles + 1, allocMain);
                  memcpy(p->FileNames.data, sd->Data, namesSize);
                  RINOK(SzReadFileNames(sd->Data, namesSize >> 1, numFiles, p->FileNameOffsets))
                     RINOK(SzSkeepDataSize(sd, namesSize));
                  break;
               }
            case k7zIdEmptyStream:
               {
                  RINOK(SzReadBoolVector(sd, numFiles, emptyStreamVector, allocTemp));
                  numEmptyStreams = 0;
                  for (i = 0; i < numFiles; i++)
                     if ((*emptyStreamVector)[i])
                        numEmptyStreams++;
                  break;
               }
            case k7zIdEmptyFile:
               {
                  RINOK(SzReadBoolVector(sd, numEmptyStreams, emptyFileVector, allocTemp));
                  break;
               }
            case k7zIdWinAttributes:
               {
                  RINOK(SzReadBoolVector2(sd, numFiles, lwtVector, allocTemp));
                  RINOK(SzReadSwitch(sd));
                  for (i = 0; i < numFiles; i++)
                  {
                     CSzFileItem *f = &files[i];
                     uint8_t defined = (*lwtVector)[i];
                     f->AttribDefined = defined;
                     f->Attrib = 0;
                     if (defined)
                     {
                        RINOK(SzReaduint32_t(sd, &f->Attrib));
                     }
                  }
                  IAlloc_Free(allocTemp, *lwtVector);
                  *lwtVector = NULL;
                  break;
               }
            case k7zIdMTime:
               {
                  RINOK(SzReadBoolVector2(sd, numFiles, lwtVector, allocTemp));
                  RINOK(SzReadSwitch(sd));
                  for (i = 0; i < numFiles; i++)
                  {
                     CSzFileItem *f = &files[i];
                     uint8_t defined = (*lwtVector)[i];
                     f->MTimeDefined = defined;
                     f->MTime.Low = f->MTime.High = 0;
                     if (defined)
                     {
                        RINOK(SzReaduint32_t(sd, &f->MTime.Low));
                        RINOK(SzReaduint32_t(sd, &f->MTime.High));
                     }
                  }
                  IAlloc_Free(allocTemp, *lwtVector);
                  *lwtVector = NULL;
                  break;
               }
            default:
               {
                  RINOK(SzSkeepDataSize(sd, size));
               }
         }
   }

   {
      uint32_t emptyFileIndex = 0;
      uint32_t sizeIndex = 0;
      for (i = 0; i < numFiles; i++)
      {
         CSzFileItem *file = files + i;
         file->IsAnti = 0;
         if (*emptyStreamVector == 0)
            file->HasStream = 1;
         else
            file->HasStream = (uint8_t)((*emptyStreamVector)[i] ? 0 : 1);
         if (file->HasStream)
         {
            file->IsDir = 0;
            file->Size = (*unpackSizes)[sizeIndex];
            file->Crc = (*digests)[sizeIndex];
            file->CrcDefined = (uint8_t)(*digestsDefined)[sizeIndex];
            sizeIndex++;
         }
         else
         {
            if (*emptyFileVector == 0)
               file->IsDir = 1;
            else
               file->IsDir = (uint8_t)((*emptyFileVector)[emptyFileIndex] ? 0 : 1);
            emptyFileIndex++;
            file->Size = 0;
            file->Crc = 0;
            file->CrcDefined = 0;
         }
      }
   }
   return SzArEx_Fill(p, allocMain);
}
Beispiel #23
0
static SRes SzReadSubStreamsInfo(
      CSzData *sd,
      uint32_t numFolders,
      CSzFolder *folders,
      uint32_t *numUnpackStreams,
      uint64_t **unpackSizes,
      uint8_t **digestsDefined,
      uint32_t **digests,
      ISzAlloc *allocTemp)
{
   uint64_t type = 0;
   uint32_t i;
   uint32_t si = 0;
   uint32_t numDigests = 0;

   for (i = 0; i < numFolders; i++)
      folders[i].NumUnpackStreams = 1;
   *numUnpackStreams = numFolders;

   for (;;)
   {
      RINOK(SzReadID(sd, &type));
      if (type == k7zIdNumUnpackStream)
      {
         *numUnpackStreams = 0;
         for (i = 0; i < numFolders; i++)
         {
            uint32_t numStreams;
            RINOK(SzReadNumber32(sd, &numStreams));
            folders[i].NumUnpackStreams = numStreams;
            *numUnpackStreams += numStreams;
         }
         continue;
      }
      if (type == k7zIdCRC || type == k7zIdSize)
         break;
      if (type == k7zIdEnd)
         break;
      RINOK(SzSkeepData(sd));
   }

   if (*numUnpackStreams == 0)
   {
      *unpackSizes = 0;
      *digestsDefined = 0;
      *digests = 0;
   }
   else
   {
      *unpackSizes = (uint64_t *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(uint64_t));
      RINOM(*unpackSizes);
      *digestsDefined = (uint8_t *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(uint8_t));
      RINOM(*digestsDefined);
      *digests = (uint32_t *)IAlloc_Alloc(allocTemp, (size_t)*numUnpackStreams * sizeof(uint32_t));
      RINOM(*digests);
   }

   for (i = 0; i < numFolders; i++)
   {
      /*
         v3.13 incorrectly worked with empty folders
         v4.07: we check that folder is empty
         */
      uint64_t sum = 0;
      uint32_t j;
      uint32_t numSubstreams = folders[i].NumUnpackStreams;
      if (numSubstreams == 0)
         continue;
      if (type == k7zIdSize)
         for (j = 1; j < numSubstreams; j++)
         {
            uint64_t size;
            RINOK(SzReadNumber(sd, &size));
            (*unpackSizes)[si++] = size;
            sum += size;
         }
      (*unpackSizes)[si++] = SzFolder_GetUnpackSize(folders + i) - sum;
   }
   if (type == k7zIdSize)
   {
      RINOK(SzReadID(sd, &type));
   }

   for (i = 0; i < *numUnpackStreams; i++)
   {
      (*digestsDefined)[i] = 0;
      (*digests)[i] = 0;
   }


   for (i = 0; i < numFolders; i++)
   {
      uint32_t numSubstreams = folders[i].NumUnpackStreams;
      if (numSubstreams != 1 || !folders[i].UnpackCRCDefined)
         numDigests += numSubstreams;
   }


   si = 0;
   for (;;)
   {
      if (type == k7zIdCRC)
      {
         int digestIndex = 0;
         uint8_t *digestsDefined2 = 0;
         uint32_t *digests2 = 0;
         SRes res = SzReadHashDigests(sd, numDigests, &digestsDefined2, &digests2, allocTemp);
         if (res == SZ_OK)
         {
            for (i = 0; i < numFolders; i++)
            {
               CSzFolder *folder = folders + i;
               uint32_t numSubstreams = folder->NumUnpackStreams;
               if (numSubstreams == 1 && folder->UnpackCRCDefined)
               {
                  (*digestsDefined)[si] = 1;
                  (*digests)[si] = folder->UnpackCRC;
                  si++;
               }
               else
               {
                  uint32_t j;
                  for (j = 0; j < numSubstreams; j++, digestIndex++)
                  {
                     (*digestsDefined)[si] = digestsDefined2[digestIndex];
                     (*digests)[si] = digests2[digestIndex];
                     si++;
                  }
               }
            }
         }
         IAlloc_Free(allocTemp, digestsDefined2);
         IAlloc_Free(allocTemp, digests2);
         RINOK(res);
      }
      else if (type == k7zIdEnd)
         return SZ_OK;
      else
      {
         RINOK(SzSkeepData(sd));
      }
      RINOK(SzReadID(sd, &type));
   }
}
Beispiel #24
0
static SRes SzReadUnpackInfo(
      CSzData *sd,
      uint32_t *numFolders,
      CSzFolder **folders,  /* for alloc */
      ISzAlloc *alloc,
      ISzAlloc *allocTemp)
{
   uint32_t i;
   RINOK(SzWaitAttribute(sd, k7zIdFolder));
   RINOK(SzReadNumber32(sd, numFolders));
   {
      RINOK(SzReadSwitch(sd));

      MY_ALLOC(CSzFolder, *folders, (size_t)*numFolders, alloc);

      for (i = 0; i < *numFolders; i++)
         SzFolder_Init((*folders) + i);

      for (i = 0; i < *numFolders; i++)
      {
         RINOK(SzGetNextFolderItem(sd, (*folders) + i, alloc));
      }
   }

   RINOK(SzWaitAttribute(sd, k7zIdCodersUnpackSize));

   for (i = 0; i < *numFolders; i++)
   {
      uint32_t j;
      CSzFolder *folder = (*folders) + i;
      uint32_t numOutStreams = SzFolder_GetNumOutStreams(folder);

      MY_ALLOC(uint64_t, folder->UnpackSizes, (size_t)numOutStreams, alloc);

      for (j = 0; j < numOutStreams; j++)
      {
         RINOK(SzReadNumber(sd, folder->UnpackSizes + j));
      }
   }

   for (;;)
   {
      uint64_t type;
      RINOK(SzReadID(sd, &type));
      if (type == k7zIdEnd)
         return SZ_OK;
      if (type == k7zIdCRC)
      {
         SRes res;
         uint8_t *crcsDefined = 0;
         uint32_t *crcs = 0;
         res = SzReadHashDigests(sd, *numFolders, &crcsDefined, &crcs, allocTemp);
         if (res == SZ_OK)
         {
            for (i = 0; i < *numFolders; i++)
            {
               CSzFolder *folder = (*folders) + i;
               folder->UnpackCRCDefined = crcsDefined[i];
               folder->UnpackCRC = crcs[i];
            }
         }
         IAlloc_Free(allocTemp, crcs);
         IAlloc_Free(allocTemp, crcsDefined);
         RINOK(res);
         continue;
      }
      RINOK(SzSkeepData(sd));
   }
}
Beispiel #25
0
int cli_7unz (cli_ctx *ctx, size_t offset) {
    CFileInStream archiveStream;
    CLookToRead lookStream;
    CSzArEx db;
    SRes res;
    UInt16 utf16buf[UTFBUFSZ], *utf16name = utf16buf;
    int namelen = UTFBUFSZ, found = CL_CLEAN;
    Int64 begin_of_archive = offset;
    UInt32 viruses_found = 0;

    /* Replacement for 
       FileInStream_CreateVTable(&archiveStream); */
    archiveStream.s.Read = FileInStream_fmap_Read;
    archiveStream.s.Seek = FileInStream_fmap_Seek;
    archiveStream.s.curpos = 0;
    archiveStream.file.fmap = *ctx->fmap;

    LookToRead_CreateVTable(&lookStream, False);
  
    if(archiveStream.s.Seek(&archiveStream.s, &begin_of_archive, SZ_SEEK_SET) != 0)
	return CL_CLEAN;

    lookStream.realStream = &archiveStream.s;
    LookToRead_Init(&lookStream);

    SzArEx_Init(&db);
    res = SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp);
    if(res == SZ_OK) {
	UInt32 i, blockIndex = 0xFFFFFFFF;
	Byte *outBuffer = 0;
	size_t outBufferSize = 0;
	unsigned int encrypted = 0;

	for (i = 0; i < db.db.NumFiles; i++) {
	    size_t offset = 0;
	    size_t outSizeProcessed = 0;
	    const CSzFileItem *f = db.db.Files + i;
	    char *name;
	    size_t j;
	    int newnamelen, fd;

	    if((found = cli_checklimits("7unz", ctx, 0, 0, 0)))
		break;

	    if (f->IsDir)
		continue;

	    if(cli_checklimits("7unz", ctx, f->Size, 0, 0))
		continue;

	    if (!db.FileNameOffsets)
		newnamelen = 0; /* no filename */
	    else {
		newnamelen = SzArEx_GetFileNameUtf16(&db, i, NULL);
		if (newnamelen > namelen) {
		    if(namelen > UTFBUFSZ)
			free(utf16name);
		    utf16name = cli_malloc(newnamelen*2);
		    if(!utf16name) {
			found = CL_EMEM;
			break;
		    }
		    namelen = newnamelen;
		}
		SzArEx_GetFileNameUtf16(&db, i, utf16name);
	    }

	    name = (char *)utf16name;
	    for(j=0; j<(size_t)newnamelen; j++) /* FIXME */
		name[j] = utf16name[j];
	    name[j] = 0;
	    cli_dbgmsg("cli_7unz: extracting %s\n", name);

	    res = SzArEx_Extract(&db, &lookStream.s, i, &blockIndex, &outBuffer, &outBufferSize, &offset, &outSizeProcessed, &allocImp, &allocTempImp);
	    if(res == SZ_ERROR_ENCRYPTED) {
		encrypted = 1;
		if(DETECT_ENCRYPTED) {
		    cli_dbgmsg("cli_7unz: Encrypted files found in archive.\n");
		    cli_append_virus(ctx, "Heuristics.Encrypted.7Zip");
		    viruses_found++;
		    if(!SCAN_ALL) {
			found = CL_VIRUS;
			break;
		    }
		}
	    }
	    if(cli_matchmeta(ctx, name, 0, f->Size, encrypted, i, f->CrcDefined ? f->Crc : 0, NULL)) {
		found = CL_VIRUS;
		viruses_found++;
		if (!SCAN_ALL)
		    break;
	    }
	    if (res != SZ_OK)
		cli_dbgmsg("cli_unz: extraction failed with %d\n", res);
	    else {
		if((found = cli_gentempfd(ctx->engine->tmpdir, &name, &fd)))
		    break;
		    
		cli_dbgmsg("cli_7unz: Saving to %s\n", name);
		if((size_t)cli_writen(fd, outBuffer + offset, outSizeProcessed) != outSizeProcessed)
		    found = CL_EWRITE;
		else
		    if ((found = cli_magic_scandesc(fd, ctx)) == CL_VIRUS)
			viruses_found++;
		close(fd);
		if(!ctx->engine->keeptmp && cli_unlink(name))
		    found = CL_EUNLINK;

		free(name);
		if(found != CL_CLEAN)
		    if (!(SCAN_ALL && found == CL_VIRUS))
			break;
	    }
	}
	IAlloc_Free(&allocImp, outBuffer);
    }
    SzArEx_Free(&db, &allocImp);
    if(namelen > UTFBUFSZ)
	free(utf16name);

    if (res == SZ_OK)
	cli_dbgmsg("cli_7unz: completed successfully\n");
    else if (res == SZ_ERROR_UNSUPPORTED)
	cli_dbgmsg("cli_7unz: unsupported\n");
    else if (res == SZ_ERROR_MEM)
	cli_dbgmsg("cli_7unz: oom\n");
    else if (res == SZ_ERROR_CRC)
	cli_dbgmsg("cli_7unz: crc mismatch\n");
    else
	cli_dbgmsg("cli_7unz: error %d\n", res);

    if (SCAN_ALL && viruses_found)
	return CL_VIRUS;
    return found;
}
Beispiel #26
0
SRes SzArEx_Extract(
      const CSzArEx *p,
      ILookInStream *inStream,
      uint32_t fileIndex,
      uint32_t *blockIndex,
      uint8_t **outBuffer,
      size_t *outBufferSize,
      size_t *offset,
      size_t *outSizeProcessed,
      ISzAlloc *allocMain,
      ISzAlloc *allocTemp)
{
   uint32_t folderIndex = p->FileIndexToFolderIndexMap[fileIndex];
   SRes res = SZ_OK;
   *offset = 0;
   *outSizeProcessed = 0;
   if (folderIndex == (uint32_t)-1)
   {
      IAlloc_Free(allocMain, *outBuffer);
      *blockIndex = folderIndex;
      *outBuffer = 0;
      *outBufferSize = 0;
      return SZ_OK;
   }

   if (*outBuffer == 0 || *blockIndex != folderIndex)
   {
      CSzFolder *folder = p->db.Folders + folderIndex;
      uint64_t unpackSizeSpec = SzFolder_GetUnpackSize(folder);
      size_t unpackSize = (size_t)unpackSizeSpec;
      uint64_t startOffset = SzArEx_GetFolderStreamPos(p, folderIndex, 0);

      if (unpackSize != unpackSizeSpec)
         return SZ_ERROR_MEM;
      *blockIndex = folderIndex;
      IAlloc_Free(allocMain, *outBuffer);
      *outBuffer = 0;

      RINOK(LookInStream_SeekTo(inStream, startOffset));

      if (res == SZ_OK)
      {
         *outBufferSize = unpackSize;
         if (unpackSize != 0)
         {
            *outBuffer = (uint8_t *)IAlloc_Alloc(allocMain, unpackSize);
            if (*outBuffer == 0)
               res = SZ_ERROR_MEM;
         }
         if (res == SZ_OK)
         {
            res = SzFolder_Decode(folder,
                  p->db.PackSizes + p->FolderStartPackStreamIndex[folderIndex],
                  inStream, startOffset,
                  *outBuffer, unpackSize, allocTemp);
            if (res == SZ_OK)
            {
               if (folder->UnpackCRCDefined)
               {
                  if (CrcCalc(*outBuffer, unpackSize) != folder->UnpackCRC)
                     res = SZ_ERROR_CRC;
               }
            }
         }
      }
   }
   if (res == SZ_OK)
   {
      uint32_t i;
      CSzFileItem *fileItem = p->db.Files + fileIndex;
      *offset = 0;
      for (i = p->FolderStartFileIndex[folderIndex]; i < fileIndex; i++)
         *offset += (uint32_t)p->db.Files[i].Size;
      *outSizeProcessed = (size_t)fileItem->Size;
      if (*offset + *outSizeProcessed > *outBufferSize)
         return SZ_ERROR_FAIL;
      if (fileItem->CrcDefined && CrcCalc(*outBuffer + *offset, *outSizeProcessed) != fileItem->Crc)
         res = SZ_ERROR_CRC;
   }
   return res;
}
Beispiel #27
0
void SzBitUi64s_Free(CSzBitUi64s *p, ISzAlloc *alloc)
{
  IAlloc_Free(alloc, p->Defs); p->Defs = NULL;
  IAlloc_Free(alloc, p->Vals); p->Vals = NULL;
}
Beispiel #28
0
SRes SzAr_Extract(
    const CSzArEx *p,
    ISzInStream *inStream, 
    UInt32 fileIndex,
    UInt32 *blockIndex,
    Byte **outBuffer, 
    size_t *outBufferSize,
    size_t *offset, 
    size_t *outSizeProcessed, 
    ISzAlloc *allocMain,
    ISzAlloc *allocTemp)
{
  UInt32 folderIndex = p->FileIndexToFolderIndexMap[fileIndex];
  SRes res = SZ_OK;
  *offset = 0;
  *outSizeProcessed = 0;
  if (folderIndex == (UInt32)-1)
  {
    IAlloc_Free(allocMain, *outBuffer);
    *blockIndex = folderIndex;
    *outBuffer = 0;
    *outBufferSize = 0;
    return SZ_OK;
  }

  if (*outBuffer == 0 || *blockIndex != folderIndex)
  {
    CSzFolder *folder = p->db.Folders + folderIndex;
    CFileSize unPackSizeSpec = SzFolder_GetUnPackSize(folder);
    size_t unPackSize = (size_t)unPackSizeSpec;
    CFileSize startOffset = SzArEx_GetFolderStreamPos(p, folderIndex, 0);

    if (unPackSize != unPackSizeSpec)
      return SZ_ERROR_MEM;
    *blockIndex = folderIndex;
    IAlloc_Free(allocMain, *outBuffer);
    *outBuffer = 0;
    
    RINOK(inStream->Seek(inStream, startOffset, SZ_SEEK_SET));
    
    if (res == SZ_OK)
    {
      *outBufferSize = unPackSize;
      if (unPackSize != 0)
      {
        *outBuffer = (Byte *)IAlloc_Alloc(allocMain, unPackSize);
        if (*outBuffer == 0)
          res = SZ_ERROR_MEM;
      }
      if (res == SZ_OK)
      {
        res = SzDecode(p->db.PackSizes + 
          p->FolderStartPackStreamIndex[folderIndex], folder, 
          inStream, startOffset, 
          *outBuffer, unPackSize, allocTemp);
        if (res == SZ_OK)
        {
          if (folder->UnPackCRCDefined)
          {
            if (CrcCalc(*outBuffer, unPackSize) != folder->UnPackCRC)
              res = SZ_ERROR_CRC;
          }
        }
      }
    }
  }
  if (res == SZ_OK)
  {
    UInt32 i; 
    CSzFileItem *fileItem = p->db.Files + fileIndex;
    *offset = 0;
    for(i = p->FolderStartFileIndex[folderIndex]; i < fileIndex; i++)
      *offset += (UInt32)p->db.Files[i].Size;
    *outSizeProcessed = (size_t)fileItem->Size;
    if (*offset + *outSizeProcessed > *outBufferSize)
      return SZ_ERROR_FAIL;
    {
      if (fileItem->IsFileCRCDefined)
      {
        if (CrcCalc(*outBuffer + *offset, *outSizeProcessed) != fileItem->FileCRC)
          res = SZ_ERROR_CRC;
      }
    }
  }
  return res;
}
Beispiel #29
0
/* Extract the relative path (needle) from a 7z archive 
 * (path) and allocate a buf for it to write it in.
 * If optional_outfile is set, extract to that instead 
 * and don't allocate buffer.
 */
static int content_7zip_file_read(
      const char *path,
      const char *needle, void **buf,
      const char *optional_outfile)
{
   CFileInStream archiveStream;
   CLookToRead lookStream;
   CSzArEx db;
   ISzAlloc allocImp;
   ISzAlloc allocTempImp;
   uint8_t *output      = 0;
   long outsize         = -1;

   /*These are the allocation routines.
    * Currently using the non-standard 7zip choices. */
   allocImp.Alloc       = SzAlloc;
   allocImp.Free        = SzFree;
   allocTempImp.Alloc   = SzAllocTemp;
   allocTempImp.Free    = SzFreeTemp;

   if (InFile_Open(&archiveStream.file, path))
   {
      RARCH_ERR("Could not open %s as 7z archive\n.", path);
      return -1;
   }

   FileInStream_CreateVTable(&archiveStream);
   LookToRead_CreateVTable(&lookStream, False);
   lookStream.realStream = &archiveStream.s;
   LookToRead_Init(&lookStream);
   CrcGenerateTable();
   SzArEx_Init(&db);

   if (SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp) == SZ_OK)
   {
      uint32_t i;
      bool file_found      = false;
      uint16_t *temp       = NULL;
      size_t temp_size     = 0;
      uint32_t block_index = 0xFFFFFFFF;
      SRes res             = SZ_OK;

      for (i = 0; i < db.db.NumFiles; i++)
      {
         size_t len;
         char infile[PATH_MAX_LENGTH];
         size_t offset           = 0;
         size_t outSizeProcessed = 0;
         const CSzFileItem    *f = db.db.Files + i;

         /* We skip over everything which is not a directory. 
          * FIXME: Why continue then if f->IsDir is true?*/
         if (f->IsDir)
            continue;

         len = SzArEx_GetFileNameUtf16(&db, i, NULL);

         if (len > temp_size)
         {
            free(temp);
            temp_size = len;
            temp = (uint16_t *)malloc(temp_size * sizeof(temp[0]));

            if (temp == 0)
            {
               res = SZ_ERROR_MEM;
               break;
            }
         }

         SzArEx_GetFileNameUtf16(&db, i, temp);
         res = utf16_to_char_string(temp, infile, sizeof(infile)) 
            ? SZ_OK : SZ_ERROR_FAIL;

         if (string_is_equal(infile, needle))
         {
            size_t output_size   = 0;

            RARCH_LOG_OUTPUT("Opened archive %s. Now trying to extract %s\n",
                  path, needle);

            /* C LZMA SDK does not support chunked extraction - see here:
             * sourceforge.net/p/sevenzip/discussion/45798/thread/6fb59aaf/
             * */
            file_found = true;
            res = SzArEx_Extract(&db, &lookStream.s, i, &block_index,
                  &output, &output_size, &offset, &outSizeProcessed,
                  &allocImp, &allocTempImp);

            if (res != SZ_OK)
               break; /* This goes to the error section. */

            outsize = outSizeProcessed;
            
            if (optional_outfile != NULL)
            {
               const void *ptr = (const void*)(output + offset);

               if (!retro_write_file(optional_outfile, ptr, outsize))
               {
                  RARCH_ERR("Could not open outfilepath %s.\n",
                        optional_outfile);
                  res        = SZ_OK;
                  file_found = true;
                  outsize    = -1;
               }
            }
            else
            {
               /*We could either use the 7Zip allocated buffer,
                * or create our own and use it.
                * We would however need to realloc anyways, because RetroArch
                * expects a \0 at the end, therefore we allocate new,
                * copy and free the old one. */
               *buf = malloc(outsize + 1);
               ((char*)(*buf))[outsize] = '\0';
               memcpy(*buf,output + offset,outsize);
            }
            break;
         }
      }

      free(temp);
      IAlloc_Free(&allocImp, output);

      if (!(file_found && res == SZ_OK))
      {
         /* Error handling */
         if (!file_found)
            RARCH_ERR("File %s not found in %s\n", needle, path);

         RARCH_ERR("Failed to open compressed file inside 7zip archive.\n");

         outsize    = -1;
      }
   }

   SzArEx_Free(&db, &allocImp);
   File_Close(&archiveStream.file);

   return outsize;
}
Beispiel #30
0
void ExtractPayload(const void* payload, size_t payloadSize, const WCHAR* prefix)
{
	CMemInStream memStream;
	MemInStream_Init(&memStream, payload, payloadSize);

	CrcGenerateTable();

	ISzAlloc alloc = { SzAlloc, SzFree };
	CSzArEx db;
	SzArEx_Init(&db);
	SRes res = SzArEx_Open(&db, &memStream.s, &alloc, &alloc);
	if (res != SZ_OK)
	{
		SzArEx_Free(&db, &alloc);
		return;
	}

	WCHAR buffer[MAX_PATH];
	UInt32 blockIndex = 0xFFFFFFFF;
	Byte* outBuffer = 0;
	size_t outBufferSize = 0;

	for (UInt32 i = 0; i < db.db.NumFiles; i++)
	{
		size_t offset = 0;
		size_t outSizeProcessed = 0;
		const CSzFileItem* f = db.db.Files + i;

		SzArEx_GetFileNameUtf16(&db, i, (UInt16*)buffer);
		WCHAR* destPath = buffer;
		if (wcsncmp(destPath, prefix, 3) == 0 ||
			wcsncmp(destPath, L"ALL", 3) == 0)
		{
			// Skip the prefix (X64/X32/ALL) and the path separater.
			destPath += 4;
		}
		else
		{
			// This file isn't for this arch.
			continue;
		}

		if (!f->IsDir)
		{
			res = SzArEx_Extract(
				&db, &memStream.s, i, &blockIndex, &outBuffer, &outBufferSize, &offset,
				&outSizeProcessed, &alloc, &alloc);
			if (res != SZ_OK)
			{
				break;
			}
		}

		for (size_t j = 0; destPath[j] != L'\0'; ++j)
		{
			if (destPath[j] == L'/')
			{
				destPath[j] = L'\0';
				CreateDirectory(destPath, NULL);
				destPath[j] = CHAR_PATH_SEPARATOR;
			}
		}

		if (f->IsDir)
		{
			CreateDirectory(destPath, NULL);
			continue;
		}

		CSzFile outFile;
		if (OutFile_OpenW(&outFile, destPath))
		{
			res = SZ_ERROR_FAIL;
			break;
		}
		size_t processedSize = outSizeProcessed;
		if (File_Write(&outFile, outBuffer + offset, &processedSize) != 0 ||
			processedSize != outSizeProcessed)
		{
			res = SZ_ERROR_FAIL;
			break;
		}
		if (File_Close(&outFile))
		{
			res = SZ_ERROR_FAIL;
			break;
		}

		if (f->AttribDefined) SetFileAttributesW(destPath, f->Attrib);
	}

	IAlloc_Free(&alloc, outBuffer);
	SzArEx_Free(&db, &alloc);

	if (res == SZ_OK)
	{
		// Success.
	}
}