Exemplo n.º 1
0
void VssClient::GatherWriterMetadataToScreen()
{
    FunctionTracer ft(DBG_INFO);

    ft.WriteLine(L"(Gathering writer metadata...)");

    // Gathers writer metadata
    // WARNING: this call can be performed only once per IVssBackupComponents instance!
    CComPtr<IVssAsync>  pAsync;
    CHECK_COM(m_pVssObject->GatherWriterMetadata(&pAsync));

    // Waits for the async operation to finish and checks the result
    WaitAndCheckForAsyncOperation(pAsync);

    // Get the list of writers in the metadata  
    unsigned cWriters = 0;
    CHECK_COM(m_pVssObject->GetWriterMetadataCount(&cWriters));

    // Enumerate writers
    for (unsigned iWriter = 0; iWriter < cWriters; iWriter++)
    {
        CComBSTR bstrXML;
        // Get the metadata for this particular writer
        VSS_ID idInstance = GUID_NULL;
        CComPtr<IVssExamineWriterMetadata> pMetadata;
        CHECK_COM(m_pVssObject->GetWriterMetadata(iWriter, &idInstance, &pMetadata));

        CHECK_COM(pMetadata->SaveAsXML(&bstrXML));
        wprintf(L"\n--[Writer %u]--\n%s\n", iWriter, (LPCWSTR)(bstrXML));
    }

    wprintf(L"--[end of data]--\n");
}
Exemplo n.º 2
0
// Initialize the list of writers and components for restore
void VssClient::InitializeWriterComponentsForRestore()
{
    FunctionTracer ft(DBG_INFO);

    ft.WriteLine(L"Initializing writer components for restore ...");

    // Get the list of writers in the metadata  
    unsigned cWriters = 0;
    CHECK_COM(m_pVssObject->GetWriterComponentsCount(&cWriters));

    // Enumerate writers
    for (unsigned iWriter = 0; iWriter < cWriters; iWriter++)
    {
        // Get the selected components for this particular writer
        CComPtr<IVssWriterComponentsExt> pWriterComponents;
        CHECK_COM(m_pVssObject->GetWriterComponents(iWriter, &pWriterComponents));
        
        // Get writer identity. 
        // Ignore this writer if the real writer is not present in the system
        VSS_ID idInstance = GUID_NULL;
        VSS_ID idWriter = GUID_NULL;
        CHECK_COM(pWriterComponents->GetWriterInfo(
            &idInstance, 
            &idWriter
            ));

        wstring id = Guid2WString(idWriter);
        wstring instanceId = Guid2WString(idInstance);

        // Try to discover the name based on an existing writer (identical ID and instance ID).
        // Otherwise, ignore it!
        bool bFound = false;
        for (unsigned i = 0; i < m_writerList.size(); i++)
        {
            // Do Not check for instance ID ... 
            if (id != m_writerList[i].id)
                continue; 

            // Copy the information from the existing writer in the system
            VssWriter   writer = m_writerList[i];

            ft.WriteLine(L"- Writer %s is present in the Backup Components document and on the system. Considering for restore ...",
                writer.name.c_str());

            // Adding components
            writer.InitializeComponentsForRestore(pWriterComponents);

            // Add this writer object to the writer components list 
            m_writerComponentsForRestore.push_back(writer);

            // We found the writer!
            bFound = true;
        }

        if (!bFound)
        {
            ft.WriteLine(L"- Writer with ID %s is not present in the system! Ignoring ...", id.c_str());
        }
    }
}
Exemplo n.º 3
0
// Initialize from a IVssWriterComponentsExt
void VssWriter::InitializeComponentsForRestore(IVssWriterComponentsExt * pWriterComponents)
{
    FunctionTracer ft(DBG_INFO);

    // Erase the current list of components for this writer
    components.clear();

    // Enumerate the components from the BC document
    unsigned cComponents = 0;
    CHECK_COM(pWriterComponents->GetComponentCount(&cComponents));

    // Enumerate components
    for(unsigned iComponent = 0; iComponent < cComponents; iComponent++)
    {
        // Get component
        CComPtr<IVssComponent> pComponent;
        CHECK_COM(pWriterComponents->GetComponent(iComponent, &pComponent));

        // Add this component to the list of components
        VssComponent component;
        component.Initialize(name, pComponent);

        ft.WriteLine(L"- Found component available for restore: \"%s\"", component.fullPath.c_str());

        components.push_back(component);
    }
}
Exemplo n.º 4
0
void VssClient::DoResync(DWORD dwResyncFlags)
{
    FunctionTracer ft(DBG_INFO);

    CComPtr<IVssBackupComponentsEx3> pVssObjectEx3;

    CHECK_COM(m_pVssObject->QueryInterface(__uuidof(IVssBackupComponentsEx3), (void**)&pVssObjectEx3));

    // Iterate resync pairs and add them to the recovery set
    for ( map<VSS_ID,wstring,ltguid>::iterator pair = m_resyncPairs.begin();
          pair != m_resyncPairs.end();
          ++pair )
    {
        if ( pair->second.size() )
        {
            CHECK_COM(pVssObjectEx3->AddSnapshotToRecoverySet( pair->first, 0, (PWCHAR)pair->second.c_str() ));
        }
        else
        {
            CHECK_COM(pVssObjectEx3->AddSnapshotToRecoverySet( pair->first, 0 ));
        }
    }

    // Perform resync
    CComPtr<IVssAsync>  pAsync;

    CHECK_COM(pVssObjectEx3->RecoverSet(dwResyncFlags, &pAsync));

    WaitAndCheckForAsyncOperation(pAsync);

    ft.WriteLine(L"Resync done.");

}
Exemplo n.º 5
0
// Initialize a file descriptor from a 
void VssDependency::Initialize(
        IVssWMDependency * pDependency
        )
{
    FunctionTracer ft(DBG_INFO);

    VSS_ID guidWriterId;
    CHECK_COM(pDependency->GetWriterId(&guidWriterId));

    CComBSTR bstrLogicalPath;
    CHECK_COM(pDependency->GetLogicalPath(&bstrLogicalPath));

    CComBSTR bstrComponentName;
    CHECK_COM(pDependency->GetComponentName(&bstrComponentName));

    // Initialize local data members
    writerId = Guid2WString(guidWriterId);
    logicalPath = BSTR2WString(bstrLogicalPath);
    componentName = BSTR2WString(bstrComponentName);

    // Compute the full path
    fullPath = AppendBackslash(logicalPath) + componentName;
    if (fullPath[0] != L'\\')
        fullPath = wstring(L"\\") + fullPath;
}
Exemplo n.º 6
0
void VssClient::BreakSnapshotSetEx(VSS_ID snapshotSetID, DWORD dwBreakExFlags)
{
    FunctionTracer ft(DBG_INFO);

    ft.WriteLine(L"- Calling BreakSnapshotSetEx on " WSTR_GUID_FMT L" ...", GUID_PRINTF_ARG(snapshotSetID));

    if (!(dwBreakExFlags & VSS_BREAKEX_FLAG_MASK_LUNS)                &&
        !(dwBreakExFlags & VSS_BREAKEX_FLAG_MAKE_READ_WRITE)          &&
        !(dwBreakExFlags & VSS_BREAKEX_FLAG_REVERT_IDENTITY_ALL)    &&
        !(dwBreakExFlags & VSS_BREAKEX_FLAG_REVERT_IDENTITY_NONE))
        ft.WriteLine(L"- No BreakSnapshotSetEx flags, can use -mask, -rw, -forcerevert, or -norevert");


    CComPtr<IVssBackupComponentsEx2> pVssObjectEx;
    CHECK_COM(m_pVssObject->QueryInterface(__uuidof(IVssBackupComponentsEx2), (void**)&pVssObjectEx));

    CComPtr<IVssAsync>  pAsync;

    CHECK_COM(pVssObjectEx->BreakSnapshotSetEx(snapshotSetID, dwBreakExFlags, &pAsync));

    // Waits for the async operation to finish and checks the result
    WaitAndCheckForAsyncOperation(pAsync);

    ft.WriteLine(L"BreakEx done.");

}
Exemplo n.º 7
0
wstring create_guid() {
  GUID guid;
  CHECK_COM(CoCreateGuid(&guid));
  wchar_t guid_str[50];
  CHECK(StringFromGUID2(guid, guid_str, ARRAYSIZE(guid_str)));
  return guid_str;
}
Exemplo n.º 8
0
wstring Archive::get_temp_file_name() const {
  GUID guid;
  CHECK_COM(CoCreateGuid(&guid));
  wchar_t guid_str[50];
  CHECK(StringFromGUID2(guid, guid_str, ARRAYSIZE(guid_str)));
  return add_trailing_slash(arc_dir()) + guid_str + L".tmp";
}
Exemplo n.º 9
0
// Return the list of snapshot volume devices in this snapshot set
vector<wstring> VssClient::GetSnapshotDevices(VSS_ID snapshotSetID)
{
    FunctionTracer ft(DBG_INFO);

    vector<wstring> volumes;
        
    // Get list all snapshots. 
    CComPtr<IVssEnumObject> pIEnumSnapshots;
    CHECK_COM( m_pVssObject->Query( GUID_NULL, VSS_OBJECT_NONE, VSS_OBJECT_SNAPSHOT, &pIEnumSnapshots ) );

    // Enumerate all snapshots. 
    VSS_OBJECT_PROP Prop;
    VSS_SNAPSHOT_PROP& Snap = Prop.Obj.Snap;
    while(true)
    {
        // Get the next element
        ULONG ulFetched = 0;
        CHECK_COM(pIEnumSnapshots->Next( 1, &Prop, &ulFetched ));

        // We reached the end of list
        if (ulFetched == 0)
            break;

        // Automatically call VssFreeSnapshotProperties on this structure at the end of scope
        CAutoSnapPointer snapAutoCleanup(&Snap);

        // Ignore snapshots not part of this set
        if (Snap.m_SnapshotSetId == snapshotSetID)
        {
            // Get the snapshot device object name which is a volume guid name for persistent snapshot
            // and a device name for non persistent snapshot.
            // The volume guid name and the device name we obtained here might change after breaksnapshot
            // depending on if the disk signature is reverted, but those cached names should still work
            // as symbolic links, in which case they can not persist after reboot.
            wstring snapshotDeviceObjectName = Snap.m_pwszSnapshotDeviceObject;

            // Add it to the array
            ft.WriteLine(L"- Will convert %s to read-write ...", snapshotDeviceObjectName.c_str());
            volumes.push_back(snapshotDeviceObjectName);
        }
    }

    // Return the list of snapshot volumes
    return volumes;
}
Exemplo n.º 10
0
// Lists the status for all writers
void VssClient::ListWriterStatus()
{
    FunctionTracer ft(DBG_INFO);

    ft.WriteLine(L"Listing writer status ..."); 
    
    // Gets the number of writers in the gathered status info
    // (WARNING: GatherWriterStatus must be called before)
    unsigned cWriters = 0;
    CHECK_COM(m_pVssObject->GetWriterStatusCount(&cWriters));
    ft.WriteLine(L"- Number of writers that responded: %u", cWriters);  

    // Enumerate each writer
    for(unsigned iWriter = 0; iWriter < cWriters; iWriter++)
    {
        VSS_ID idInstance = GUID_NULL;
        VSS_ID idWriter= GUID_NULL;
        VSS_WRITER_STATE eWriterStatus = VSS_WS_UNKNOWN;
        CComBSTR bstrWriterName;
        HRESULT hrWriterFailure = S_OK;

        // Get writer status
        CHECK_COM(m_pVssObject->GetWriterStatus(iWriter,
                             &idInstance,
                             &idWriter,
                             &bstrWriterName,
                             &eWriterStatus,
                             &hrWriterFailure));

        // Print writer status
        ft.WriteLine(L"\n"
            L"* WRITER \"%s\"\n"
            L"   - Status: %d (%s)\n" 
            L"   - Writer Failure code: 0x%08lx (%s)\n" 
            L"   - Writer ID: " WSTR_GUID_FMT L"\n"
            L"   - Instance ID: " WSTR_GUID_FMT L"\n",
            (PWCHAR)bstrWriterName,
            eWriterStatus, GetStringFromWriterStatus(eWriterStatus).c_str(), 
            hrWriterFailure, FunctionTracer::HResult2String(hrWriterFailure).c_str(),
            GUID_PRINTF_ARG(idWriter),
            GUID_PRINTF_ARG(idInstance)
            );
    }
}
Exemplo n.º 11
0
// Initialize a file descriptor from a 
void VssFileDescriptor::Initialize(
        IVssWMFiledesc * pFileDesc, 
        VSS_DESCRIPTOR_TYPE typeParam
        )
{
    FunctionTracer ft(DBG_INFO);

    // Set the type
    type = typeParam;

    CComBSTR bstrPath;
    CHECK_COM(pFileDesc->GetPath(&bstrPath));

    CComBSTR bstrFilespec;
    CHECK_COM(pFileDesc->GetFilespec (&bstrFilespec));

    bool bRecursive = false;
    CHECK_COM(pFileDesc->GetRecursive(&bRecursive));

    CComBSTR bstrAlternate;
    CHECK_COM(pFileDesc->GetAlternateLocation(&bstrAlternate));

    // Initialize local data members
    path = BSTR2WString(bstrPath);
    filespec = BSTR2WString(bstrFilespec);
    expandedPath = bRecursive;
    path = BSTR2WString(bstrPath);

    // Get the expanded path
    expandedPath.resize(MAX_PATH, L'\0');
    _ASSERTE(bstrPath && bstrPath[0]);
    CHECK_WIN32(ExpandEnvironmentStringsW(bstrPath, (PWCHAR)expandedPath.c_str(), (DWORD)expandedPath.length()));
    expandedPath = AppendBackslash(expandedPath);

    // Get the affected volume 
    if (!GetUniqueVolumeNameForPathNoThrow(expandedPath, affectedVolume))
    {
        affectedVolume = expandedPath;
    }

}
Exemplo n.º 12
0
// Gather writers status
void VssClient::GatherWriterStatus()
{
    FunctionTracer ft(DBG_INFO);

    // Gathers writer status
    // WARNING: GatherWriterMetadata must be called before
    CComPtr<IVssAsync>  pAsync;
    CHECK_COM(m_pVssObject->GatherWriterStatus(&pAsync));

    // Waits for the async operation to finish and checks the result
    WaitAndCheckForAsyncOperation(pAsync);
}
Exemplo n.º 13
0
void                                    
CFrameTable::SetFrameId(CComPtr<IHTMLDocument2> document, TFrameId frameId, bool bImportant)
{
	// retrieve document's window object
	CComPtr<IHTMLWindow2> window;
	CHECK_COM(document->get_parentWindow(&window), _T("Cannot retrieve parent window"));
	if (!window) 
	{
		TRACE_E(_T("Cannot retrieve parent window for document"));
		ATLASSERT(0);
		return;
	}

	// cast window object to IDispatchEx
	CComQIPtr<IDispatchEx> windowDispEx = window;
	if (!windowDispEx)
	{
		TRACE_E(_T("Cannot retrieve IDispatchEx on parent window of document"));
		ATLASSERT(0);
		return;
	}

	// add FrameId property to window object
	DISPID dispid;
	DISPPARAMS dispparams;
	HRESULT hr = windowDispEx->GetDispID(CComBSTR(JAVASCRIPT_FRAMEID_VARIABLE), fdexNameEnsure|fdexNameCaseSensitive, &dispid);
	if (!bImportant && hr==E_ACCESSDENIED) return;
	CHECK_COM(hr, FS(_T("GetDispID for window.%s has failed"), JAVASCRIPT_FRAMEID_VARIABLE));
	DISPID putid = DISPATCH_PROPERTYPUT;
	CComVariant var(frameId);
	dispparams.rgvarg = &var;
	dispparams.rgdispidNamedArgs = &putid;
	dispparams.cArgs = 1;
	dispparams.cNamedArgs = 1;
	VARIANT temp;
	CHECK_COM(windowDispEx->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYPUT, &dispparams, &temp, NULL, NULL), _T("Failed to add property to window object")); 

	ATLASSERT(GetFrameId(document)==frameId);
	DT(TRACE_I(FS(_T("CFrameTable::SetFrameId(doc=%08X, id=%d) OK"), document, frameId)));
}
Exemplo n.º 14
0
void VssClient::InitializeWriterMetadata()
{
    FunctionTracer ft(DBG_INFO);

    // Get the list of writers in the metadata  
    unsigned cWriters = 0;
    CHECK_COM(m_pVssObject->GetWriterMetadataCount (&cWriters));

    // Enumerate writers
    for (unsigned iWriter = 0; iWriter < cWriters; iWriter++)
    {
        // Get the metadata for this particular writer
        VSS_ID idInstance = GUID_NULL;
        CComPtr<IVssExamineWriterMetadata> pMetadata;
        CHECK_COM(m_pVssObject->GetWriterMetadata(iWriter, &idInstance, &pMetadata));

        VssWriter   writer;
        writer.Initialize(pMetadata);

        // Add this writer to the list 
        m_writerList.push_back(writer);
    }
}
Exemplo n.º 15
0
// Query the properties of the given shadow copy
void VssClient::GetSnapshotProperties(VSS_ID snapshotID)
{
    FunctionTracer ft(DBG_INFO);

    // Get the shadow copy properties
    VSS_SNAPSHOT_PROP Snap;
    CHECK_COM(m_pVssObject->GetSnapshotProperties(snapshotID, &Snap));

    // Automatically call VssFreeSnapshotProperties on this structure at the end of scope
    CAutoSnapPointer snapAutoCleanup(&Snap);

    // Print the properties of this shadow copy 
    PrintSnapshotProperties(Snap);
}
Exemplo n.º 16
0
// Post-restore 
void VssClient::PostRestore()
{
    FunctionTracer ft(DBG_INFO);

    ft.WriteLine(L"\nSending the PostRestore event ... \n");

    // Gathers writer status
    // WARNING: GatherWriterMetadata must be called before
    CComPtr<IVssAsync>  pAsync;
    CHECK_COM(m_pVssObject->PostRestore(&pAsync));

    // Waits for the async operation to finish and checks the result
    WaitAndCheckForAsyncOperation(pAsync);
}
Exemplo n.º 17
0
//
// Break the given shadow copy set to read or read-write
//
// Setting the parameter pVolumeNames makes this function return immediately after VSS breaks the
// shadow copy set. This is useful in the fast recover scenario: if the LUN after break is in an
// offline mode, the requster must wait for the LUN online in order to call VDS to make it read-write.
void VssClient::BreakSnapshotSet(VSS_ID snapshotSetID, bool makeReadWrite, vector<wstring> *pVolumeNames)
{
    FunctionTracer ft(DBG_INFO);

    if (makeReadWrite)
    {
        // If we want read-write treatment, compute a list of volumes in the shadow copy set
        vector<wstring> snapshotDeviceList;
        snapshotDeviceList = GetSnapshotDevices(snapshotSetID);

        ft.WriteLine(L"- Calling BreakSnapshotSet on " WSTR_GUID_FMT L" ...", GUID_PRINTF_ARG(snapshotSetID));

        // Break the shadow copy set
        CHECK_COM(m_pVssObject->BreakSnapshotSet(snapshotSetID));

        // If we want to delay read-write treatment, fill out the volume name list and return
        if (pVolumeNames)
        {
            *pVolumeNames = snapshotDeviceList;
            return;
        }

        ft.WriteLine(L"- Making shadow copy devices from " WSTR_GUID_FMT L" read-write...", GUID_PRINTF_ARG(snapshotSetID));

        // Make the snapshot devices read-write
        MakeVolumesReadWrite(snapshotDeviceList);
    }
    else
    {
        ft.WriteLine(L"- Calling BreakSnapshotSet on " WSTR_GUID_FMT L" ...", GUID_PRINTF_ARG(snapshotSetID));

        // Just break the snapshot set
        CHECK_COM(m_pVssObject->BreakSnapshotSet(snapshotSetID));

        ft.WriteLine(L"Break done.");
    }
}
Exemplo n.º 18
0
// Initialize the COM infrastructure and the internal pointers
void VssClient::Initialize(DWORD dwContext, wstring xmlDoc, bool bDuringRestore)
{
    FunctionTracer ft(DBG_INFO);

    // Initialize COM 
    CHECK_COM( CoInitialize(NULL) );
    m_bCoInitializeCalled = true;

    // Initialize COM security
    CHECK_COM( 
        CoInitializeSecurity(
            NULL,                           //  Allow *all* VSS writers to communicate back!
            -1,                             //  Default COM authentication service
            NULL,                           //  Default COM authorization service
            NULL,                           //  reserved parameter
            RPC_C_AUTHN_LEVEL_PKT_PRIVACY,  //  Strongest COM authentication level
            RPC_C_IMP_LEVEL_IDENTIFY,       //  Minimal impersonation abilities 
            NULL,                           //  Default COM authentication settings
            EOAC_NONE,                      //  No special options
            NULL                            //  Reserved parameter
            ) );

    // Create the internal backup components object
    CHECK_COM( CreateVssBackupComponents(&m_pVssObject) );
    
    // We are during restore now?
    m_bDuringRestore = bDuringRestore;

    // Call either Initialize for backup or for restore
    if (m_bDuringRestore)
    {
        CHECK_COM(m_pVssObject->InitializeForRestore(CComBSTR(xmlDoc.c_str())))
    }
    else
    {
        // Initialize for backup
        if (xmlDoc.length() == 0)
Exemplo n.º 19
0
TFrameId                             
CFrameTable::GetFrameId(CComPtr<IHTMLDocument2> document, bool bImportant)
{
	// get frame id from window.<JAVASCRIPT_FRAMEID_VARIABLE>

	// retrieve document's window object
	CComPtr<IHTMLWindow2> window;
	CHECK_COM(document->get_parentWindow(&window), _T("Cannot retrieve parent window"));
	if (!window) 
	{
		TRACE_E(_T("Cannot retrieve parent window for document"));
		ATLASSERT(0);
		return NULL_FRAME;
	}

	// cast window object to IDispatchEx
	CComQIPtr<IDispatchEx> windowDispEx = window;
	if (!windowDispEx)
	{
		TRACE_E(_T("Cannot retrieve IDispatchEx on parent window of document"));
		ATLASSERT(0);
		return NULL_FRAME;
	}

	// read FrameId property to window object
	DISPID dispid;
	DISPPARAMS dispparams = { NULL, NULL, 0, 0 };
	HRESULT hr = windowDispEx->GetDispID(CComBSTR(JAVASCRIPT_FRAMEID_VARIABLE), fdexNameCaseSensitive, &dispid);
	if (hr==DISP_E_UNKNOWNNAME) return NULL_FRAME;
	if (!bImportant && hr==E_ACCESSDENIED) return NULL_FRAME;
	CHECK_COM(hr, FS(_T("GetDispID for window.%s has failed"), JAVASCRIPT_FRAMEID_VARIABLE));
	CComVariant res;
	CHECK_COM(windowDispEx->Invoke(dispid, IID_NULL, LOCALE_USER_DEFAULT, DISPATCH_PROPERTYGET, &dispparams, &res, NULL, NULL), _T("Failed to read property from window object")); 
	ATLASSERT(res.vt==VT_UI4);
	return res.ulVal;
}
Exemplo n.º 20
0
// Initialize from a IVssComponent
void VssComponent::Initialize(wstring writerNameParam, IVssComponent * pComponent)
{
    FunctionTracer ft(DBG_INFO);

    writerName = writerNameParam;

    // Get component type
    CHECK_COM(pComponent->GetComponentType(&type));

    // Get component name
    CComBSTR bstrComponentName;
    CHECK_COM(pComponent->GetComponentName(&bstrComponentName));
    name = BSTR2WString(bstrComponentName);

    // Get component logical path
    CComBSTR bstrLogicalPath;
    CHECK_COM(pComponent->GetLogicalPath(&bstrLogicalPath));
    logicalPath = BSTR2WString(bstrLogicalPath);

    // Compute the full path
    fullPath = AppendBackslash(logicalPath) + name;
    if (fullPath[0] != L'\\')
        fullPath = wstring(L"\\") + fullPath;
}
Exemplo n.º 21
0
// Gather writers metadata
void VssClient::GatherWriterMetadata()
{
    FunctionTracer ft(DBG_INFO);

    ft.WriteLine(L"(Gathering writer metadata...)");

    // Gathers writer metadata
    // WARNING: this call can be performed only once per IVssBackupComponents instance!
    CComPtr<IVssAsync>  pAsync;
    CHECK_COM(m_pVssObject->GatherWriterMetadata(&pAsync));

    // Waits for the async operation to finish and checks the result
    WaitAndCheckForAsyncOperation(pAsync);

    ft.WriteLine(L"Initialize writer metadata ...");

    // Initialize the internal metadata data structures
    InitializeWriterMetadata();
}
Exemplo n.º 22
0
// Returns an array of enumerated VDS objects
vector< CComPtr<IUnknown> > VssClient::EnumerateVdsObjects(IEnumVdsObject * pEnumeration)
{
    FunctionTracer ft(DBG_INFO);

    vector< CComPtr<IUnknown> > objectList;
    
    while(true)
    {
        CComPtr<IUnknown> pUnknown;
        ULONG ulFetched = 0;
        CHECK_COM(pEnumeration->Next(1, &pUnknown, &ulFetched));

        // End of enumeration
        if (ulFetched == 0)
            break;

        // Add the object to the array
        objectList.push_back(pUnknown);
    }

    return objectList;
}
Exemplo n.º 23
0
HRESULT
CFrame::Create(CComPtr<IHTMLDocument2> document)
{
	// cache document
	m_Document = document;
	CComBSTR url;
	CHECK_COM(document->get_URL(&url), FS(_T("Cannot retrieve location URL from %08X"), document));
	m_URL = url;

	CComBSTR mime;
	document->get_mimeType(&mime);
	DT(TRACE_I(FS(_T("MIME=%s, URL=%s"), CString(mime), m_URL)));
	m_MIME = mime;

	//////////////////////////////////////////////////////////////////////////
	// look for child frames

	// attach scripting engine (if applicable)
	// ---------------------------------------
	// here we need to test what kind of document we have here
	// we need to apply scrpting engine only to HTML documents
	// applying scripting engine to PDF, DOC, ... documents may cause problems and even throw exceptions
	// see: http://groups.google.cz/group/microsoft.public.inetsdk.programming.html_objmodel/browse_thread/thread/a72010c809ced9d1/00f299ba42346dff?lnk=st&q=ihtmldocument2+pdf&rnum=3#00f299ba42346dff
	// probably we need to use http://home.nyc.rr.com/itandetnik/PassthruAPP.zip to implement this test correctly
	// TODO: use PasstrhuAPP to detect document type and attach script engine only onto HTML documents

	if (IsScriptableDocument())
	{
		m_Attached = m_ScriptEngine->Attach(document, m_URL);
	}

	// update my links
	// different approach: do not update when created frame, child documents may be not prepared
	// we will fire links update when loading of all relevant documents is finished
	// UpdateLinks();

	return S_OK;
}
Exemplo n.º 24
0
void                                           
CFrame::UpdateLinks()
{
	// start from scratch
	m_ChildFrames.clear();

	// detect all child frames
	CComQIPtr<IOleContainer> spContainer = m_Document;
	if (!!spContainer)
	{
		// get an enumerator for the frames
		IEnumUnknown* pEnumerator;
		HRESULT hr = spContainer->EnumObjects(OLECONTF_EMBEDDINGS, &pEnumerator);

		if (SUCCEEDED(hr))
		{
			IUnknown* pUnknown;
			ULONG uFetched;

			// enumerate all the frames
			for (UINT i = 0; S_OK == pEnumerator->Next(1, &pUnknown, &uFetched); i++)
			{
				CComQIPtr<IWebBrowser2> spChildBrowser = pUnknown;
				pUnknown->Release();
				if (!!spChildBrowser)
				{
					// well done, store child frame
					CComPtr<IDispatch> spChildDispDoc;
					CHECK_COM(spChildBrowser->get_Document(&spChildDispDoc), FS(_T("Cannot retrieve document object from %08X"), spChildBrowser));
					CComQIPtr<IHTMLDocument2> spChildDoc = spChildDispDoc;

					// sometimes IE can return NULL spChildDispDoc 
					// 
					// (observed on pages with file download blocking)
					// test for valid doc
					if (!!spChildDoc)
					{
						CComBSTR url2;
						CHECK_COM(spChildDoc->get_URL(&url2), FS(_T("Cannot retrieve location URL from %08X"), spChildDoc));
						CString URL2 = url2;

						// it wouldn't be so easy to simply add child document into childs
						// but IE (maybe) does some reallocation of this document, so we need to do lookup via frameId

						TFrameId id = m_FrameTable.GetFrameId(spChildDoc, false);

						// wait for document to load, 
						// there is RISK OF CALLS to other functions !!!
						//if (id==NULL_FRAME) id = m_FrameTable.GetFrameId(spChildDoc, true); // blocking call
						if (id==NULL_FRAME)
						{
							// TODO: tohle se muze nekdy stat, kdyz se frame jeste nestihne naloadovat pri F5, napriklad gmail.com to dela
							TRACE_W(FS(_T("Child doc not found for %s !!"), URL2));
						}
						else
						{
							m_ChildFrames.push_back(id);
						}
					}
				}
			}
		}
		pEnumerator->Release();
	}
}
Exemplo n.º 25
0
// Initialize from a IVssWMComponent
void VssComponent::Initialize(wstring writerNameParam, IVssWMComponent * pComponent)
{
    FunctionTracer ft(DBG_INFO);

    writerName = writerNameParam;

    // Get the component info
    PVSSCOMPONENTINFO pInfo = NULL;
    CHECK_COM(pComponent->GetComponentInfo (&pInfo));

    // Initialize local members
    name = BSTR2WString(pInfo->bstrComponentName);
    logicalPath = BSTR2WString(pInfo->bstrLogicalPath);
    caption = BSTR2WString(pInfo->bstrCaption);
    type = pInfo->type;
    isSelectable = pInfo->bSelectable;
    notifyOnBackupComplete = pInfo->bNotifyOnBackupComplete;

    // Compute the full path
    fullPath = AppendBackslash(logicalPath) + name;
    if (fullPath[0] != L'\\')
        fullPath = wstring(L"\\") + fullPath;

    // Get file list descriptors
    for(unsigned i = 0; i < pInfo->cFileCount; i++)
    {
        CComPtr<IVssWMFiledesc> pFileDesc;
        CHECK_COM(pComponent->GetFile (i, &pFileDesc));

        VssFileDescriptor desc;
        desc.Initialize(pFileDesc, VSS_FDT_FILELIST);
        descriptors.push_back(desc);
    }
    
    // Get database descriptors
    for(unsigned i = 0; i < pInfo->cDatabases; i++)
    {
        CComPtr<IVssWMFiledesc> pFileDesc;
        CHECK_COM(pComponent->GetDatabaseFile (i, &pFileDesc));

        VssFileDescriptor desc;
        desc.Initialize(pFileDesc, VSS_FDT_DATABASE);
        descriptors.push_back(desc);
    }
    
    // Get log descriptors
    for(unsigned i = 0; i < pInfo->cLogFiles; i++)
    {
        CComPtr<IVssWMFiledesc> pFileDesc;
        CHECK_COM(pComponent->GetDatabaseLogFile (i, &pFileDesc));

        VssFileDescriptor desc;
        desc.Initialize(pFileDesc, VSS_FDT_DATABASE_LOG);
        descriptors.push_back(desc);
    }
    

#ifdef VSS_SERVER
    // Get dependencies
    for(unsigned i = 0; i < pInfo->cDependencies; i++)
    {
        CComPtr<IVssWMDependency> pDependency;
        CHECK_COM(pComponent->GetDependency(i, &pDependency));

        VssDependency dependency;
        dependency.Initialize(pDependency);
        dependencies.push_back(dependency);
    }
#endif


    pComponent->FreeComponentInfo (pInfo);

    // Compute the affected paths and volumes
    for(unsigned i = 0; i < descriptors.size(); i++)
    {
        if (!FindStringInList(descriptors[i].expandedPath, affectedPaths))
            affectedPaths.push_back(descriptors[i].expandedPath);

        if (!FindStringInList(descriptors[i].affectedVolume, affectedVolumes))
            affectedVolumes.push_back(descriptors[i].affectedVolume);
    }


    sort( affectedPaths.begin( ), affectedPaths.end( ) );
}
Exemplo n.º 26
0
void VssClient::RevertToSnapshot(VSS_ID snapshotID)
{
    FunctionTracer ft(DBG_INFO);

    // Get the shadow copy properties
    VSS_SNAPSHOT_PROP Snap;
    CHECK_COM(m_pVssObject->GetSnapshotProperties(snapshotID, &Snap));
    
    // Automatically call VssFreeSnapshotProperties on this structure at the end of scope
    CAutoSnapPointer snapAutoCleanup(&Snap);

    ft.WriteLine(L"- Reverting to shadow copy " WSTR_GUID_FMT L" on %s from provider " WSTR_GUID_FMT L" [0x%08lx]...", 
            GUID_PRINTF_ARG(Snap.m_SnapshotId),
            Snap.m_pwszOriginalVolumeName,
            GUID_PRINTF_ARG(Snap.m_ProviderId),
            Snap.m_lSnapshotAttributes);
    
    bool bBlock = false;
    CHECK_COM(::ShouldBlockRevert(Snap.m_pwszOriginalVolumeName, &bBlock));
    if (bBlock)
    {
        ft.WriteLine(L"Revert is disabled on the volume %s because of writers",
                Snap.m_pwszOriginalVolumeName);
        return;
    }

    HRESULT hr = m_pVssObject->RevertToSnapshot(snapshotID, true);
    if (FAILED(hr))
    {
        switch (hr)
        {
        case VSS_E_OBJECT_NOT_FOUND:
                ft.WriteLine(L"Shadow Copy with id " WSTR_GUID_FMT L" was not found",
                    GUID_PRINTF_ARG(snapshotID));
                return;
            case VSS_E_VOLUME_IN_USE:
                ft.WriteLine(L"The voulume %s cannot be reverted since it is in use",
                    Snap.m_pwszOriginalVolumeName);
                return;
            case VSS_E_REVERT_IN_PROGRESS:
                ft.WriteLine(L"A revert is current in progress on the volume %s",
                    Snap.m_pwszOriginalVolumeName);
                return;
            case VSS_E_VOLUME_NOT_SUPPORTED:
                ft.WriteLine(L"Revert is not supported on the volume %s",
                    Snap.m_pwszOriginalVolumeName);
                return;            
            default:
                ft.WriteLine(L"RevertToSnapshot on Shadow Copy " WSTR_GUID_FMT L" failed with error 0x%08lx",
                            GUID_PRINTF_ARG(snapshotID),
                            hr);
                return;
        }
    }

    CComPtr<IVssAsync> pAsync;
    hr = m_pVssObject->QueryRevertStatus(Snap.m_pwszOriginalVolumeName, &pAsync);
    if (hr != VSS_E_OBJECT_NOT_FOUND)
    {
        if (FAILED(hr))
        {
            ft.WriteLine(L"QueryRevertStatus failed with error 0x%08lx", hr);
            ft.WriteLine(L"Revert may still be in progress, but cannot be tracked");
            return;
        }

        hr = pAsync->Wait();
        if (FAILED(hr))
        {
            ft.WriteLine(L"IVssAsync::Wait failed with error 0x%08lx", hr);
            ft.WriteLine(L"Revert may still be in progress, but cannot be tracked");
            return;
        }
    }

    ft.WriteLine(L"The shadow copy has been successfully reverted");
}
Exemplo n.º 27
0
// Make the volumes in this list read-write using VDS API
void VssClient::MakeVolumesReadWrite(vector<wstring> snapshotVolumes)
{
    FunctionTracer ft(DBG_INFO);

    ft.Trace(DBG_INFO, L"Clearing read-only on %d volumes ... ", snapshotVolumes.size());

    // Get the VDS loader
    CComPtr<IVdsServiceLoader> pLoader;
    CHECK_COM(CoCreateInstance(CLSID_VdsLoader,
        NULL,
        CLSCTX_LOCAL_SERVER,
        __uuidof(IVdsServiceLoader),
        (void **)&pLoader));

    // Get the service interface pointer
    CComPtr<IVdsService> pService;
    CHECK_COM(pLoader->LoadService(NULL, &pService));

    CHECK_COM(pService->WaitForServiceReady());

    vector<wstring> clearedVolumes;

    // Get the unique volume names for the cached snapshot volume names 
    // which might change after the break
    vector<wstring> snapshotVolumeUniqueNames;
    for (unsigned i = 0; i < snapshotVolumes.size( ); i++)
        snapshotVolumeUniqueNames.push_back(GetUniqueVolumeNameForMountPoint(snapshotVolumes[i]));


    // Enumerate the Software providers
    HRESULT hr;
    CComPtr<IEnumVdsObject> pEnumProvider;
    CHECK_COM(pService->QueryProviders(VDS_QUERY_SOFTWARE_PROVIDERS,&pEnumProvider));
    vector< CComPtr<IUnknown> > providers = EnumerateVdsObjects(pEnumProvider);
    for(unsigned iProvider = 0; iProvider < providers.size(); iProvider++)
    {
        // QueryInterface for IVdsSwProvider
        CComQIPtr<IVdsSwProvider> pSwProvider = providers[iProvider];

        ft.Trace(DBG_INFO, L"- Provider %d", iProvider);

        // Enumerate packs for this provider
        CComPtr<IEnumVdsObject> pEnumPack;
        CHECK_COM(pSwProvider->QueryPacks(&pEnumPack));
        vector< CComPtr<IUnknown> > packs = EnumerateVdsObjects(pEnumPack);
        for(unsigned iPack = 0; iPack < packs.size(); iPack++)
        {
            // QueryInterface for IVdsPack
            CComQIPtr<IVdsPack> pPack = packs[iPack];

            ft.Trace(DBG_INFO, L"- Pack %d/%d", iPack, iProvider);

            // Enumerate volumes
            CComPtr<IEnumVdsObject> pEnumVolumes;
            hr = pPack->QueryVolumes(&pEnumVolumes);
            if (FAILED(hr)) {
                if (hr == VDS_E_INVALID_PACK) {
                    hr = S_OK;
                } else ft.Trace( DBG_INFO, L"COM Error: GetProperties for VDS pack failed. hr = 0x%08lx", hr);
                continue;
            }

            vector< CComPtr<IUnknown> > volumes = EnumerateVdsObjects(pEnumVolumes);
            for(unsigned iVol = 0; iVol < volumes.size(); iVol++)
            {
                // QueryInterface for IVdsVolumeMF and IVdsVolume
                CComQIPtr<IVdsVolume> pVolume = volumes[iVol];

                // Get volume properties. Ignore deleted volumes
                VDS_VOLUME_PROP volProp;
                HRESULT innerHR = pVolume->GetProperties(&volProp);
                if (innerHR == VDS_E_OBJECT_DELETED )
                    continue;

                CHECK_COM_ERROR(innerHR, L"pVolume->GetProperties(&volProp)");

                // Skip failed volumes
                if ( (volProp.status == VDS_VS_FAILED) && (volProp.health == VDS_H_FAILED) || !volProp.pwszName)
                    continue;

                // Skip hidden volumes (it fails GetVolumeNameForMountPoint)
                if (volProp.ulFlags & VDS_VF_HIDDEN)
                    continue;

                // Automatically call CoTaskMemFree on this pointer at the end of scope
                CAutoComPointer ptrAutoCleanup(volProp.pwszName);

                // Get the initial device name (normally with the format \\?\GLOBALROOT\Device\HarddiskVolumeXX)
                wstring name = volProp.pwszName;

                // Get the unique volume guid name for this device name.
                wstring uniqueVolumeName = GetUniqueVolumeNameForMountPoint(name);

                ft.Trace(DBG_INFO, L"- Found volume %s [device = %s] in %d/%d", 
                    uniqueVolumeName.c_str(), name.c_str(), iPack, iProvider);

                // Check to see if this is one of our volumes. If not, continue
                if (!FindStringInList(uniqueVolumeName, snapshotVolumeUniqueNames))
                    continue;

                // Clear the read-only flag
                ft.WriteLine(L"- Clearing read-only flag for volume %s [%s] ...", uniqueVolumeName.c_str(), name.c_str());

                CHECK_COM(pVolume->ClearFlags(VDS_VF_READONLY));

                // Force-dismounts the volume 
                // since we want to re-mount the file system as read-write
                CComQIPtr<IVdsVolumeMF> pVolumeMF = pVolume;
                ft.WriteLine(L"- Dismounting volume %s ...", name.c_str());
                CHECK_COM(pVolumeMF->Dismount(TRUE, FALSE));

                clearedVolumes.push_back(uniqueVolumeName);
            }
        }
    }

    // Check that all volumes have been cleared ...
    if (clearedVolumes.size() != snapshotVolumeUniqueNames.size())
    {
        ft.WriteLine(L"WARNING: some volumes were not succesfully converted to read-write!");

        for (unsigned i = 0; i < snapshotVolumeUniqueNames.size(); i++)
            if (!FindStringInList(snapshotVolumeUniqueNames[i], clearedVolumes))
                ft.WriteLine(L"- Volume %s not found on the system. Clearing the read-only flag failed on it.",
                    snapshotVolumeUniqueNames[i].c_str());
    }
}
Exemplo n.º 28
0
// Initialize from a IVssWMFiledesc
void VssWriter::Initialize(IVssExamineWriterMetadata * pMetadata)
{
    FunctionTracer ft(DBG_INFO);

    // Get writer identity information
    VSS_ID idInstance = GUID_NULL;
    VSS_ID idWriter = GUID_NULL;
    CComBSTR bstrWriterName;
    VSS_USAGE_TYPE usage = VSS_UT_UNDEFINED;
    VSS_SOURCE_TYPE source= VSS_ST_UNDEFINED;
    CComBSTR bstrService;
    CComBSTR bstrUserProcedure;
    UINT iMappings;

    // Get writer identity
    CHECK_COM(pMetadata->GetIdentity (
        &idInstance,
        &idWriter,
        &bstrWriterName,
        &usage,
        &source
        ));

    // Get the restore method 
    CHECK_COM(pMetadata->GetRestoreMethod(
        &restoreMethod,
        &bstrService,
        &bstrUserProcedure,
        &writerRestoreConditions,
        &rebootRequiredAfterRestore,
        &iMappings
        ));

    // Initialize local members
    name = (LPWSTR)bstrWriterName;
    id = Guid2WString(idWriter);
    instanceId = Guid2WString(idInstance);
    supportsRestore = (writerRestoreConditions != VSS_WRE_NEVER);

    // Get file counts
    unsigned cIncludeFiles = 0;
    unsigned cExcludeFiles = 0;
    unsigned cComponents = 0;
    CHECK_COM(pMetadata->GetFileCounts(&cIncludeFiles, &cExcludeFiles, &cComponents));

    // Get exclude files
    for(unsigned i = 0; i < cExcludeFiles; i++)
    {
        CComPtr<IVssWMFiledesc> pFileDesc;
        CHECK_COM(pMetadata->GetExcludeFile(i, &pFileDesc));

        // Add this descriptor to the list of excluded files
        VssFileDescriptor excludedFile;
        excludedFile.Initialize(pFileDesc, VSS_FDT_EXCLUDE_FILES);
        excludedFiles.push_back(excludedFile);
    }

    // Enumerate components
    for(unsigned iComponent = 0; iComponent < cComponents; iComponent++)
    {
        // Get component
        CComPtr<IVssWMComponent> pComponent;
        CHECK_COM(pMetadata->GetComponent(iComponent, &pComponent));

        // Add this component to the list of components
        VssComponent component;
        component.Initialize(name, pComponent);
        components.push_back(component);
    }

    // Discover toplevel components
    for(unsigned i = 0; i < cComponents; i++)
    {
        components[i].isTopLevel = true;
        for(unsigned j = 0; j < cComponents; j++)
            if (components[j].IsAncestorOf(components[i]))
                components[i].isTopLevel = false;
    }
}
Exemplo n.º 29
0
  UNKNOWN_IMPL_END

  // *** IInArchive ***

  // read archive contents from IInStream
  // return S_FALSE if format is not recognized
  STDMETHODIMP Open(IInStream* stream, const UInt64* max_check_start_position, IArchiveOpenCallback* open_archive_callback) {
    COM_ERROR_HANDLER_BEGIN
    in_stream = stream;

    UInt64 file_size = 0;
    CHECK_COM(in_stream->Seek(0, STREAM_SEEK_END, &file_size));
    CHECK_COM(in_stream->Seek(0, STREAM_SEEK_SET, nullptr));

    CHECK_COM(open_archive_callback->SetTotal(nullptr, &file_size));

    char sig_buf[c_sig_size];
    if (read_stream(in_stream, sig_buf, c_sig_size) != c_sig_size)
      return S_FALSE;
    if (memcmp(c_sig, sig_buf, c_sig_size) != 0)
      return S_FALSE;

    if (read_stream(in_stream, &comp_level, sizeof(comp_level)) != sizeof(comp_level))
      return S_FALSE;

    UInt64 file_count = 0;
    list<FileInfo> file_list;
    size_t path_buf_size = MAX_PATH;
    unique_ptr<wchar_t[]> path_buf(new wchar_t[path_buf_size]);
    while (true) {
      FileInfo file_info;
      UInt32 path_size;
      UInt32 size_read = read_stream(in_stream, &path_size, sizeof(path_size));
      if (size_read == 0)
        break;
      if (size_read != sizeof(path_size))
        return S_FALSE;
      if (path_size > 32000)
        return S_FALSE;
      if (path_size > path_buf_size) {
        path_buf_size = path_size;
        path_buf.reset(new wchar_t[path_buf_size]);
      }
      if (read_stream(in_stream, path_buf.get(), path_size * sizeof(wchar_t)) != path_size * sizeof(wchar_t))
        return S_FALSE;
      file_info.path.assign(path_buf.get(), path_size);

      if (read_stream(in_stream, &file_info.size, sizeof(file_info.size)) != sizeof(file_info.size))
        return S_FALSE;
      CHECK_COM(in_stream->Seek(0, STREAM_SEEK_CUR, &file_info.offset));
      UInt64 file_pos;
      if (in_stream->Seek(file_info.size, STREAM_SEEK_CUR, &file_pos) != S_OK)
        return S_FALSE;
      
      file_list.push_back(file_info);

      file_count++;
      CHECK_COM(open_archive_callback->SetCompleted(&file_count, &file_pos));
    }

    files.reserve(file_list.size());
    copy(file_list.begin(), file_list.end(), back_inserter(files));

    return S_OK;
    COM_ERROR_HANDLER_END
  }
Exemplo n.º 30
0
void Archive::make_index() {
  num_indices = 0;
  CHECK_COM(in_arc->GetNumberOfItems(&num_indices));
  file_list.clear();
  file_list.reserve(num_indices);

  struct DirInfo {
    UInt32 index;
    UInt32 parent;
    wstring name;
    bool operator<(const DirInfo& dir_info) const {
      if (parent == dir_info.parent)
        return lstrcmpiW(name.c_str(), dir_info.name.c_str()) < 0;
      else
        return parent < dir_info.parent;
    }
  };
  typedef set<DirInfo> DirList;
  map<UInt32, unsigned> dir_index_map;
  DirList dir_list;

  DirInfo dir_info;
  UInt32 dir_index = 0;
  ArcFileInfo file_info;
  wstring path;
  PropVariant prop;
  for (UInt32 i = 0; i < num_indices; i++) {
    // is directory?
    file_info.is_dir = in_arc->GetProperty(i, kpidIsDir, prop.ref()) == S_OK && prop.is_bool() && prop.get_bool();

    // file name
    if (in_arc->GetProperty(i, kpidPath, prop.ref()) == S_OK && prop.is_str())
      path.assign(prop.get_str());
    else
      path.assign(get_default_name());
    size_t name_end_pos = path.size();
    while (name_end_pos && is_slash(path[name_end_pos - 1])) name_end_pos--;
    size_t name_pos = name_end_pos;
    while (name_pos && !is_slash(path[name_pos - 1])) name_pos--;
    file_info.name.assign(path.data() + name_pos, name_end_pos - name_pos);

    // split path into individual directories and put them into DirList
    dir_info.parent = c_root_index;
    size_t begin_pos = 0;
    while (begin_pos < name_pos) {
      dir_info.index = dir_index;
      size_t end_pos = begin_pos;
      while (end_pos < name_pos && !is_slash(path[end_pos])) end_pos++;
      if (end_pos != begin_pos) {
        dir_info.name.assign(path.data() + begin_pos, end_pos - begin_pos);
        pair<DirList::iterator, bool> ins_pos = dir_list.insert(dir_info);
        if (ins_pos.second)
          dir_index++;
        dir_info.parent = ins_pos.first->index;
      }
      begin_pos = end_pos + 1;
    }
    file_info.parent = dir_info.parent;

    if (file_info.is_dir) {
      dir_info.index = dir_index;
      dir_info.parent = file_info.parent;
      dir_info.name = file_info.name;
      pair<DirList::iterator, bool> ins_pos = dir_list.insert(dir_info);
      if (ins_pos.second) {
        dir_index++;
        dir_index_map[dir_info.index] = i;
      }
      else {
        if (dir_index_map.count(ins_pos.first->index))
          file_info.parent = c_dup_index;
        else
          dir_index_map[ins_pos.first->index] = i;
      }
    }

    file_list.push_back(file_info);
  }

  // add directories that not present in archive index
  file_list.reserve(file_list.size() + dir_list.size() - dir_index_map.size());
  dir_index = num_indices;
  for_each(dir_list.begin(), dir_list.end(), [&] (const DirInfo& dir_info) {
    if (dir_index_map.count(dir_info.index) == 0) {
      dir_index_map[dir_info.index] = dir_index;
      file_info.parent = dir_info.parent;
      file_info.name = dir_info.name;
      file_info.is_dir = true;
      dir_index++;
      file_list.push_back(file_info);
    }
  });

  // fix parent references
  for_each(file_list.begin(), file_list.end(), [&] (ArcFileInfo& file_info) {
    if (file_info.parent != c_root_index)
      file_info.parent = dir_index_map[file_info.parent];
  });

  // create search index
  file_list_index.clear();
  file_list_index.reserve(file_list.size());
  for (UInt32 i = 0; i < file_list.size(); i++) {
    file_list_index.push_back(i);
  }
  sort(file_list_index.begin(), file_list_index.end(), [&] (UInt32 left, UInt32 right) -> bool {
    return file_list[left] < file_list[right];
  });

  load_arc_attr();
}