Example #1
0
void CCurve::AddArcOrLines(bool check_for_arc, std::list<CVertex> &new_vertices, std::list<const CVertex*>& might_be_an_arc, CArc &arc, bool &arc_found, bool &arc_added)
{
	if(check_for_arc && CheckForArc(new_vertices.back(), might_be_an_arc, arc))
	{
		arc_found = true;
	}
	else
	{
		if(arc_found)
		{
			if(arc.AlmostALine())
			{
				new_vertices.push_back(CVertex(arc.m_e, arc.m_user_data));
			}
			else
			{
				new_vertices.push_back(CVertex(arc.m_dir ? 1:-1, arc.m_e, arc.m_c, arc.m_user_data));
			}

			arc_added = true;
			arc_found = false;
			const CVertex* back_vt = might_be_an_arc.back();
			might_be_an_arc.clear();
			if(check_for_arc)might_be_an_arc.push_back(back_vt);
		}
		else
		{
			const CVertex* back_vt = might_be_an_arc.back();
			if(check_for_arc)might_be_an_arc.pop_back();
			for(std::list<const CVertex*>::iterator It = might_be_an_arc.begin(); It != might_be_an_arc.end(); It++)
			{
				const CVertex* v = *It;
				if(It != might_be_an_arc.begin() || (new_vertices.size() == 0) || (new_vertices.back().m_p != v->m_p))
				{
					new_vertices.push_back(*v);
				}
			}
			might_be_an_arc.clear();
			if(check_for_arc)might_be_an_arc.push_back(back_vt);
		}
	}
}
Example #2
0
HRESULT CProxyArc::Load(const CArc &arc, IProgress *progress)
{
  // DWORD tickCount = GetTickCount(); for (int ttt = 0; ttt < 1; ttt++) {

  Files.Free();
  Dirs.Clear();

  Dirs.AddNew();
  IInArchive *archive = arc.Archive;

  UInt32 numItems;
  RINOK(archive->GetNumberOfItems(&numItems));
  
  if (progress)
    RINOK(progress->SetTotal(numItems));
  
  Files.Alloc(numItems);

  UString path;
  UString name;
  NCOM::CPropVariant prop;
  
  for (UInt32 i = 0; i < numItems; i++)
  {
    if (progress && (i & 0xFFFF) == 0)
    {
      UInt64 currentItemIndex = i;
      RINOK(progress->SetCompleted(&currentItemIndex));
    }
    
    const wchar_t *s = NULL;
    unsigned len = 0;
    bool isPtrName = false;

    #ifdef MY_CPU_LE
    if (arc.GetRawProps)
    {
      const void *p;
      UInt32 size;
      UInt32 propType;
      if (arc.GetRawProps->GetRawProp(i, kpidPath, &p, &size, &propType) == S_OK
          && propType == NPropDataType::kUtf16z
          && size > 2)
      {
        // is (size <= 2), it's empty name, and we call default arc.GetItemPath();
        len = size / 2 - 1;
        s = (const wchar_t *)p;
        isPtrName = true;
      }
    }
    if (!s)
    #endif
    {
      prop.Clear();
      RINOK(arc.Archive->GetProperty(i, kpidPath, &prop));
      if (prop.vt == VT_BSTR)
      {
        s = prop.bstrVal;
        len = ::SysStringLen(prop.bstrVal);
      }
      else if (prop.vt != VT_EMPTY)
        return E_FAIL;
      if (len == 0)
      {
        RINOK(arc.GetDefaultItemPath(i, path));
        len = path.Len();
        s = path;
      }
      
      /*
      RINOK(arc.GetItemPath(i, path));
      len = path.Len();
      s = path;
      */
    }

    unsigned curItem = 0;

    /*
    if (arc.Ask_Deleted)
    {
      bool isDeleted = false;
      RINOK(Archive_IsItem_Deleted(archive, i, isDeleted));
      if (isDeleted)
        curItem = AddDirSubItem(curItem, (UInt32)(Int32)-1, false, L"[DELETED]");
    }
    */

    unsigned namePos = 0;
    for (unsigned j = 0; j < len; j++)
    {
      wchar_t c = s[j];
      if (c == WCHAR_PATH_SEPARATOR || c == L'/')
      {
        name.SetFrom(s + namePos, j - namePos);
        curItem = AddDir(curItem, -1, name);
        namePos = j + 1;
      }
    }

    /*
    that code must be implemeted to hide alt streams in list.
    if (arc.Ask_AltStreams)
    {
      bool isAltStream;
      RINOK(Archive_IsItem_AltStream(archive, i, isAltStream));
      if (isAltStream)
      {

      }
    }
    */

    bool isDir;
    RINOK(Archive_IsItem_Dir(archive, i, isDir));

    CProxyFile &f = Files[i];

    f.NameLen = len - namePos;
    s += namePos;

    if (isPtrName)
      f.Name = s;
    else
    {
      f.Name = new wchar_t[f.NameLen + 1];
      f.NeedDeleteName = true;
      MyStringCopy((wchar_t *)f.Name, s);
    }

    if (isDir)
    {
      name = s;
      AddDir(curItem, (int)i, name);
    }
    else
      Dirs[curItem].SubFiles.Add(i);
  }
  
  CalculateSizes(0, archive);

  // } char s[128]; sprintf(s, "Load archive: %7d ms", GetTickCount() - tickCount); OutputDebugStringA(s);

  return S_OK;
}
Example #3
0
HRESULT CFieldPrinter::PrintItemInfo(const CArc &arc, UInt32 index, bool techMode)
{
  /*
  if (techMode)
  {
    g_StdOut << "Index = ";
    g_StdOut << (UInt64)index;
    g_StdOut << endl;
  }
  */
  for (int i = 0; i < _fields.Size(); i++)
  {
    const CFieldInfo &fieldInfo = _fields[i];
    if (!techMode)
      PrintSpaces(fieldInfo.PrefixSpacesWidth);

    NCOM::CPropVariant prop;
    if (fieldInfo.PropID == kpidPath)
    {
      UString s;
      RINOK(arc.GetItemPath(index, s));
      prop = s;
    }
    else
    {
      RINOK(arc.Archive->GetProperty(index, fieldInfo.PropID, &prop));
    }
    if (techMode)
    {
      g_StdOut << fieldInfo.Name << " = ";
    }
    int width = (fieldInfo.PropID == kpidPath) ? 0: fieldInfo.Width;
    if (fieldInfo.PropID == kpidAttrib && (prop.vt == VT_EMPTY || prop.vt == VT_UI4))
    {
      UInt32 attrib = (prop.vt == VT_EMPTY) ? 0 : prop.ulVal;
      bool isFolder;
      RINOK(IsArchiveItemFolder(arc.Archive, index, isFolder));
      char s[8];
      GetAttribString(attrib, isFolder, s);
      g_StdOut << s;
    }
    else if (prop.vt == VT_EMPTY)
    {
      if (!techMode)
        PrintSpaces(width);
    }
    else if (fieldInfo.PropID == kpidMTime)
    {
      PrintTime(prop);
    }
    else if (prop.vt == VT_BSTR)
    {
      if (techMode)
        g_StdOut << prop.bstrVal;
      else
        PrintString(fieldInfo.TextAdjustment, width, prop.bstrVal);
    }
    else
    {
      UString s = ConvertPropertyToString(prop, fieldInfo.PropID);
      s.Replace(wchar_t(0xA), L' ');
      s.Replace(wchar_t(0xD), L' ');

      if (techMode)
        g_StdOut << s;
      else
        PrintString(fieldInfo.TextAdjustment, width, s);
    }
    if (techMode)
      g_StdOut << endl;
  }
  return S_OK;
}
Example #4
0
HRESULT CArchiveLink::Open(
    CCodecs *codecs,
    const CIntVector &formatIndices,
    bool stdInMode,
    IInStream *stream,
    const UString &filePath,
    IArchiveOpenCallback *callback)
{
  Release();
  if (formatIndices.Size() >= 32)
    return E_NOTIMPL;
  
  HRESULT resSpec;

  for (;;)
  {
    resSpec = S_OK;
    int formatIndex = -1;
    if (formatIndices.Size() >= 1)
    {
      if (Arcs.Size() >= formatIndices.Size())
        break;
      formatIndex = formatIndices[formatIndices.Size() - Arcs.Size() - 1];
    }
    else if (Arcs.Size() >= 32)
      break;

    if (Arcs.IsEmpty())
    {
      CArc arc;
      arc.Path = filePath;
      arc.SubfileIndex = (UInt32)(Int32)-1;
      RINOK(arc.OpenStreamOrFile(codecs, formatIndex, stdInMode, stream, callback));
      Arcs.Add(arc);
      continue;
    }
    
    const CArc &arc = Arcs.Back();
    
    resSpec = (formatIndices.Size() == 0 ? S_OK : E_NOTIMPL);
    
    UInt32 mainSubfile;
    {
      NCOM::CPropVariant prop;
      RINOK(arc.Archive->GetArchiveProperty(kpidMainSubfile, &prop));
      if (prop.vt == VT_UI4)
        mainSubfile = prop.ulVal;
      else
        break;
      UInt32 numItems;
      RINOK(arc.Archive->GetNumberOfItems(&numItems));
      if (mainSubfile >= numItems)
        break;
    }

  
    CMyComPtr<IInArchiveGetStream> getStream;
    if (arc.Archive->QueryInterface(IID_IInArchiveGetStream, (void **)&getStream) != S_OK || !getStream)
      break;
    
    CMyComPtr<ISequentialInStream> subSeqStream;
    if (getStream->GetStream(mainSubfile, &subSeqStream) != S_OK || !subSeqStream)
      break;
    
    CMyComPtr<IInStream> subStream;
    if (subSeqStream.QueryInterface(IID_IInStream, &subStream) != S_OK || !subStream)
      break;
    
    CArc arc2;
    RINOK(arc.GetItemPath(mainSubfile, arc2.Path));
    
    CMyComPtr<IArchiveOpenSetSubArchiveName> setSubArchiveName;
    callback->QueryInterface(IID_IArchiveOpenSetSubArchiveName, (void **)&setSubArchiveName);
    if (setSubArchiveName)
      setSubArchiveName->SetSubArchiveName(arc2.Path);
    
    arc2.SubfileIndex = mainSubfile;
    HRESULT result = arc2.OpenStream(codecs, formatIndex, subStream, NULL, callback);
    resSpec = (formatIndices.Size() == 0 ? S_OK : S_FALSE);
    if (result == S_FALSE)
      break;
    RINOK(result);
    RINOK(arc.GetItemMTime(mainSubfile, arc2.MTime, arc2.MTimeDefined));
    Arcs.Add(arc2);
  }
  IsOpen = !Arcs.IsEmpty();
  return S_OK;
}
Example #5
0
bool CCurve::CheckForArc(const CVertex& prev_vt, std::list<const CVertex*>& might_be_an_arc, CArc &arc_returned)
{
	// this examines the vertices in might_be_an_arc
	// if they do fit an arc, set arc to be the arc that they fit and return true
	// returns true, if arc added
	if(might_be_an_arc.size() < 2)return false;

	// find middle point
	std::size_t num = might_be_an_arc.size();
	std::size_t i = 0;
	const CVertex* mid_vt = NULL;
	std::size_t mid_i = (num-1)/2;
	for(std::list<const CVertex*>::iterator It = might_be_an_arc.begin(); It != might_be_an_arc.end(); It++, i++)
	{
		if(i == mid_i)
		{
			mid_vt = *It;
			break;
		}
	}

	// create a circle to test
	Point p0(prev_vt.m_p);
	Point p1(mid_vt->m_p);
	Point p2(might_be_an_arc.back()->m_p);
	Circle c(p0, p1, p2);

	const CVertex* current_vt = &prev_vt;
	double accuracy = CArea::m_accuracy * 1.4 / CArea::m_units;
	for(std::list<const CVertex*>::iterator It = might_be_an_arc.begin(); It != might_be_an_arc.end(); It++)
	{
		const CVertex* vt = *It;

		if(!c.LineIsOn(current_vt->m_p, vt->m_p, accuracy))
			return false;
		current_vt = vt;
	}

	CArc arc;
	arc.m_c = c.m_c;
	arc.m_s = prev_vt.m_p;
	arc.m_e = might_be_an_arc.back()->m_p;
	arc.SetDirWithPoint(might_be_an_arc.front()->m_p);
	arc.m_user_data = might_be_an_arc.back()->m_user_data;

	double angs = atan2(arc.m_s.y - arc.m_c.y, arc.m_s.x - arc.m_c.x);
	double ange = atan2(arc.m_e.y - arc.m_c.y, arc.m_e.x - arc.m_c.x);
	if(arc.m_dir)
	{
		// make sure ange > angs
		if(ange < angs)ange += 6.2831853071795864;
	}
	else
	{
		// make sure angs > ange
		if(angs < ange)angs += 6.2831853071795864;
	}

	if(arc.IncludedAngle() >= 3.15)return false; // We don't want full arcs, so limit to about 180 degrees

	for(std::list<const CVertex*>::iterator It = might_be_an_arc.begin(); It != might_be_an_arc.end(); It++)
	{
		const CVertex* vt = *It;
		double angp = atan2(vt->m_p.y - arc.m_c.y, vt->m_p.x - arc.m_c.x);
		if(arc.m_dir)
		{
			// make sure angp > angs
			if(angp < angs)angp += 6.2831853071795864;
			if(angp > ange)return false;
		}
		else
		{
			// make sure angp > ange
			if(angp < ange)angp += 6.2831853071795864;
			if(angp > angs)return false;
		}
	}

	arc_returned = arc;
	return true;
}
Example #6
0
CElem* CXMLVecLS::LoadElem(CXmlNode &node)
{
	CString str;
	int nType = GetType(node.GetName());

	CPointF pt;
	CRectF rc; 

	CElem *elem = NULL;
	switch (nType)
	{
	case CElem::Line:
		{		
			CLine *pElem = new CLine();
			
			TEST_FREE_RETURNNULL(!LoadNonFillVecElem(pElem,node),pElem);
 
			pt.x = node.GetFloatAttrib(_T("StartPointX"));
			pt.y = node.GetFloatAttrib(_T("StartPointY"));
			pElem->SetStartPoint(pt);

			pt.x = node.GetFloatAttrib(_T("EndPointX"));
			pt.y = node.GetFloatAttrib(_T("EndPointY")); 
			pElem->SetEndPoint(pt);
			elem = pElem;
		}
		break;
	case CElem::Bezier:
		{		
			CBezier *pElem = new CBezier();
			
			TEST_FREE_RETURNNULL(!LoadNonFillVecElem(pElem,node),pElem);

			CXmlNode n;
			CPointF pt;
			CFPoints pts;
			for (int i=0,cnt=node.ChildCount; i<cnt; ++i)
			{
				n = node.Child[i];
				if (n.GetName() == _T("Point"))
				{
					pt.x = n.GetFloatAttrib(_T("X"));
					pt.y = n.GetFloatAttrib(_T("Y"));
					pts.Add(pt);
				}
			}
			pElem->SetPoints(pts);
			elem = pElem;
		}
		break;
	case CElem::FreeLine:
		{		
			CFreeLine *pElem = new CFreeLine();
			
			TEST_FREE_RETURNNULL(!LoadNonFillVecElem(pElem,node),pElem);

			CXmlNode n;
			CPointF pt;
			CFPoints pts;
			for (int i=0,cnt=node.ChildCount; i<cnt; ++i)
			{
				n = node.Child[i];
				if (n.GetName() == _T("Point"))
				{
					pt.x = n.GetFloatAttrib(_T("X"));
					pt.y = n.GetFloatAttrib(_T("Y"));
					pts.Add(pt);
				}
			}
			pElem->SetPoints(pts);
			elem = pElem;
		}
		break;
	case CElem::Arc:
		{
			CArc *pElem = new CArc();
			
			TEST_FREE_RETURNNULL(!LoadNonFillVecElem(pElem,node),pElem);

			rc.left = node.GetFloatAttrib(_T("RectLeft"));
			rc.top = node.GetFloatAttrib(_T("RectTop"));
			rc.right = node.GetFloatAttrib(_T("RectRight"));			
			rc.bottom = node.GetFloatAttrib(_T("RectBottom"));
			pElem->SetBoundsRect(rc);

			pElem->SetStartAngel(node.GetFloatAttrib(_T("StartAngel")));
			pElem->SetEndAngel(node.GetFloatAttrib(_T("EndAngel")));

			elem = pElem;
		}
		break;
	case CElem::Chord:
		{
			CChord *pElem = new CChord();
			
			TEST_FREE_RETURNNULL(!LoadFilledVecElem(pElem,node),pElem);

			rc.left = node.GetFloatAttrib(_T("RectLeft"));
			rc.top = node.GetFloatAttrib(_T("RectTop"));
			rc.right = node.GetFloatAttrib(_T("RectRight"));			
			rc.bottom = node.GetFloatAttrib(_T("RectBottom"));
			pElem->SetBoundsRect(rc);

			pElem->SetStartAngel(node.GetFloatAttrib(_T("StartAngel")));
			pElem->SetEndAngel(node.GetFloatAttrib(_T("EndAngel")));
			elem = pElem; 
		}
		break;
	case CElem::Pie:
		{
			CPie *pElem = new CPie();
			
			TEST_FREE_RETURNNULL(!LoadFilledVecElem(pElem,node),pElem);

			rc.left = node.GetFloatAttrib(_T("RectLeft"));
			rc.top = node.GetFloatAttrib(_T("RectTop"));
			rc.right = node.GetFloatAttrib(_T("RectRight"));			
			rc.bottom = node.GetFloatAttrib(_T("RectBottom"));
			pElem->SetBoundsRect(rc);

			pElem->SetStartAngel(node.GetFloatAttrib(_T("StartAngel")));
			pElem->SetEndAngel(node.GetFloatAttrib(_T("EndAngel")));
			elem = pElem;  
		}
		break;

	case CElem::Poly:
		{
			CPoly *pElem = new CPoly();
			
			TEST_FREE_RETURNNULL(!LoadFilledVecElem(pElem,node),pElem);

			CXmlNode n;
			CPointF pt;
			CFPoints pts;
			for (int i=0,cnt=node.ChildCount; i<cnt; ++i)
			{
				n = node.Child[i];
				if (n.GetName() == _T("Point"))
				{
					pt.x = n.GetFloatAttrib(_T("X"));
					pt.y = n.GetFloatAttrib(_T("Y"));
					pts.Add(pt);
				}
			}
			pElem->SetPoints(pts);
			elem = pElem;
		}
		break;
	case CElem::Region:
		{
			CRegion *pElem = new CRegion();
			
			TEST_FREE_RETURNNULL(!LoadFilledVecElem(pElem,node),pElem);

			CXmlNode n;
			CPointF pt;
			CFPoints pts;
			for (int i=0,cnt=node.ChildCount; i<cnt; ++i)
			{
				n = node.Child[i];
				if (n.GetName() == _T("Point"))
				{
					pt.x = n.GetFloatAttrib(_T("X"));
					pt.y = n.GetFloatAttrib(_T("Y"));
					pts.Add(pt);
				}
			}
			pElem->SetPoints(pts);
			elem = pElem;
		}
		break;
	case CElem::Rectangle:
		{			
			CRectangle *pElem = new CRectangle();
			
			TEST_FREE_RETURNNULL(!LoadFilledVecElem(pElem,node),pElem);

			pElem->SetText(node.GetStringAttrib(_T("Text")));
			rc.left = node.GetFloatAttrib(_T("RectLeft"));
			rc.top = node.GetFloatAttrib(_T("RectTop"));
			rc.right = node.GetFloatAttrib(_T("RectRight"));			
			rc.bottom = node.GetFloatAttrib(_T("RectBottom"));
			pElem->SetBoundsRect(rc);
			elem = pElem;
		}
		break;
	case CElem::RoundRect:
		{
			CRoundRect *pElem = new CRoundRect();
			
			TEST_FREE_RETURNNULL(!LoadFilledVecElem(pElem,node),pElem);

			rc.left = node.GetFloatAttrib(_T("RectLeft"));
			rc.top = node.GetFloatAttrib(_T("RectTop"));
			rc.right = node.GetFloatAttrib(_T("RectRight"));			
			rc.bottom = node.GetFloatAttrib(_T("RectBottom"));
			pElem->SetBoundsRect(rc);

			pElem->SetXEllipse(node.GetFloatAttrib(_T("XEllipse")));
			pElem->SetYEllipse(node.GetFloatAttrib(_T("YEllipse")));

			elem = pElem;
		}
		break;
	case CElem::Ellipse:
		{
			CEllipse *pElem = new CEllipse();
			
			TEST_FREE_RETURNNULL(!LoadFilledVecElem(pElem,node),pElem);

			rc.left = node.GetFloatAttrib(_T("RectLeft"));
			rc.top = node.GetFloatAttrib(_T("RectTop"));
			rc.right = node.GetFloatAttrib(_T("RectRight"));			
			rc.bottom = node.GetFloatAttrib(_T("RectBottom"));
			pElem->SetBoundsRect(rc);

			elem = pElem;;
		}
		break;
	default: 
		ASSERT(FALSE);
		return NULL;
	} 
	if (elem != NULL)
	{
		elem->SetCustomData(node.GetBigUIntAttrib(_T("CustomData")));
		elem->SetDesc(node.GetStringAttrib(_T("Desc")));
		//elem->SetText(node.GetStringAttrib(_T("Text")));
		//elem->SetTextColor(node.GetUIntAttrib(_T("TextColor")));
	}

	return elem;
}
Example #7
0
HRESULT CProxyArchive::Load(const CArc &arc, IProgress *progress)
{
  RootFolder.Clear();
  IInArchive *archive = arc.Archive;
  {
    ThereIsPathProp = false;
    UInt32 numProps;
    archive->GetNumberOfProperties(&numProps);
    for (UInt32 i = 0; i < numProps; i++)
    {
      CMyComBSTR name;
      PROPID propID;
      VARTYPE varType;
      RINOK(archive->GetPropertyInfo(i, &name, &propID, &varType));
      if (propID == kpidPath)
      {
        ThereIsPathProp = true;
        break;
      }
    }
  }

  UInt32 numItems;
  RINOK(archive->GetNumberOfItems(&numItems));
  if (progress != NULL)
  {
    UInt64 totalItems = numItems;
    RINOK(progress->SetTotal(totalItems));
  }
  UString fileName;
  for (UInt32 i = 0; i < numItems; i++)
  {
    if (progress != NULL && (i & 0xFFFFF) == 0)
    {
      UInt64 currentItemIndex = i;
      RINOK(progress->SetCompleted(&currentItemIndex));
    }
    UString filePath;
    RINOK(arc.GetItemPath(i, filePath));
    CProxyFolder *curItem = &RootFolder;
    int len = filePath.Length();
    fileName.Empty();
    for (int j = 0; j < len; j++)
    {
      wchar_t c = filePath[j];
      if (c == WCHAR_PATH_SEPARATOR || c == L'/')
      {
        curItem = curItem->AddDirSubItem((UInt32)(Int32)-1, false, fileName);
        fileName.Empty();
      }
      else
        fileName += c;
    }

    bool isFolder;
    RINOK(IsArchiveItemFolder(archive, i, isFolder));
    if (isFolder)
      curItem->AddDirSubItem(i, true, fileName);
    else
      curItem->AddFileSubItem(i, fileName);
  }
  RootFolder.CalculateSizes(archive);
  return S_OK;
}
Example #8
0
static HRESULT DecompressArchive(
    const CArc &arc,
    UInt64 packSize,
    const NWildcard::CCensorNode &wildcardCensor,
    const CExtractOptions &options,
    IExtractCallbackUI *callback,
    CArchiveExtractCallback *extractCallbackSpec,
    UString &errorMessage,
    UInt64 &stdInProcessed)
{
  stdInProcessed = 0;
  IInArchive *archive = arc.Archive;
  CRecordVector<UInt32> realIndices;
  if (!options.StdInMode)
  {
    UInt32 numItems;
    RINOK(archive->GetNumberOfItems(&numItems));

    for (UInt32 i = 0; i < numItems; i++)
    {
      UString filePath;
      RINOK(arc.GetItemPath(i, filePath));
      bool isFolder;
      RINOK(IsArchiveItemFolder(archive, i, isFolder));
      if (!wildcardCensor.CheckPath(filePath, !isFolder))
        continue;
      realIndices.Add(i);
    }
    if (realIndices.Size() == 0)
    {
      callback->ThereAreNoFiles();
      return S_OK;
    }
  }

  UStringVector removePathParts;

  UString outDir = options.OutputDir;
  outDir.Replace(L"*", GetCorrectFsPath(arc.DefaultName));
  #ifdef _WIN32
  // GetCorrectFullFsPath doesn't like "..".
  // outDir.TrimRight();
  // outDir = GetCorrectFullFsPath(outDir);
  #endif

  if (!outDir.IsEmpty())
    if (!NFile::NDirectory::CreateComplexDirectory(outDir))
    {
      HRESULT res = ::GetLastError();
      if (res == S_OK)
        res = E_FAIL;
      errorMessage = ((UString)L"Can not create output directory ") + outDir;
      return res;
    }

  extractCallbackSpec->Init(
      options.StdInMode ? &wildcardCensor : NULL,
      &arc,
      callback,
      options.StdOutMode, options.TestMode, options.CalcCrc,
      outDir,
      removePathParts,
      packSize);

  #if !defined(_7ZIP_ST) && !defined(_SFX)
  RINOK(SetProperties(archive, options.Properties));
  #endif

  HRESULT result;
  Int32 testMode = (options.TestMode && !options.CalcCrc) ? 1: 0;
  if (options.StdInMode)
  {
    result = archive->Extract(NULL, (UInt32)(Int32)-1, testMode, extractCallbackSpec);
    NCOM::CPropVariant prop;
    if (archive->GetArchiveProperty(kpidPhySize, &prop) == S_OK)
      if (prop.vt == VT_UI8 || prop.vt == VT_UI4)
        stdInProcessed = ConvertPropVariantToUInt64(prop);
  }
  else
    result = archive->Extract(&realIndices.Front(), realIndices.Size(), testMode, extractCallbackSpec);

  return callback->ExtractResult(result);
}