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"); }
// 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()); } } }
// 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); } }
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."); }
// 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; }
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."); }
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; }
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"; }
// 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; }
// 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) ); } }
// 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; } }
// 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); }
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))); }
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); } }
// 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); }
// 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); }
// // 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."); } }
// 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)
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; }
// 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; }
// 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(); }
// 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; }
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; }
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(); } }
// 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( ) ); }
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"); }
// 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()); } }
// 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; } }
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 }
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(); }