urbackup_frontend_wx/SelectWindowsComponents.cpp
2020-07-14 19:16:35 +02:00

1101 lines
28 KiB
C++

#include "SelectWindowsComponents.h"
#include "Connector.h"
#include "Settings.h"
#include <wx/thread.h>
#include <wx/icon.h>
#include <fstream>
#include "stringtools.h"
#include "checked.xpm"
#include "unchecked.xpm"
#ifndef _WIN32
#include "config.h"
#endif
extern wxString res_path;
extern wxString ico_ext;
extern wxBitmapType ico_type;
extern std::string g_res_path;
SelectWindowsComponents::SelectWindowsComponents(wxWindow * parent)
: GUIWindowsComponents(parent)
{
SetIcon(wxIcon(res_path + wxT("backup-ok.") + ico_ext, ico_type));
Start(100);
wxIcon icons[2];
icons[0] = wxIcon(unchecked_xpm);
icons[1] = wxIcon(checked_xpm);
icon_width = icons[0].GetWidth();
icon_height = icons[0].GetHeight();
selectList = new wxImageList(icon_width, icon_height, true);
iconList = new wxImageList(icon_width, icon_height, true);
for (size_t i = 0; i < WXSIZEOF(icons); i++)
selectList->Add(icons[i]);
m_treeCtrl1->AssignStateImageList(selectList);
m_treeCtrl1->AddRoot(_("Loading..."));
#ifdef _DEBUG
settings = new CFileSettingsReader("urbackup/data/settings.cfg");
#elif _WIN32
settings = new CFileSettingsReader(g_res_path + "urbackup/data/settings.cfg");
#else
settings = new CFileSettingsReader(VARDIR "/urbackup/data/settings.cfg");
#endif
use_orig = 0;
std::string use_orig_str;
if (settings->getValue("vss_select_components.use", &use_orig_str))
use_orig = atoi(use_orig_str.c_str());
use_lm_orig = 0;
std::string use_lm_orig_str;
if (settings->getValue("vss_select_components.use_lm", &use_lm_orig_str))
wxString(use_lm_orig_str).ToLongLong(&use_lm_orig);
componentReader.Run();
}
SelectWindowsComponents::~SelectWindowsComponents()
{
delete settings;
}
void SelectWindowsComponents::Notify(void)
{
if (!componentReader.IsAlive())
{
Stop();
componentReader.Wait();
m_treeCtrl1->Delete(m_treeCtrl1->GetRootItem());
wxTreeItemId rootId = m_treeCtrl1->AddRoot(_("Windows components"));
m_treeCtrl1->SetItemState(rootId, 0);
SComponent* root = componentReader.getRoot();
tree_components[rootId] = root;
tree_items[root] = rootId;
addComponents(m_treeCtrl1, iconList, rootId, root, tree_components,
tree_items, icon_width, icon_height);
m_treeCtrl1->Toggle(rootId);
m_treeCtrl1->SetImageList(iconList);
std::string componentsStr = "default=0";
settings->getValue("vss_select_components.client", &componentsStr);
std::map<std::string, std::string> comps;
ParseParamStrHttp(componentsStr, &comps);
bool has_comps = true;
if (!comps["all"].empty()
&& comps["all"] != "0")
{
has_comps = false;
for (std::map<wxTreeItemId, SComponent*>::iterator it = tree_components.begin();
it != tree_components.end(); ++it)
{
if (m_treeCtrl1->GetItemState(it->first) == 0)
{
selectTreeItems(it->second, true);
}
}
}
else if (!comps["default"].empty()
&& comps["default"] != "0")
{
comps["writer_0"] = "{a65faa63-5ea8-4ebc-9dbd-a0c4db26912a}"; //MS SQL Server 2014
comps["writer_1"] = "{76fe1ac4-15f7-4bcd-987e-8e1acb462fb7}"; //MS Exchange 2010
}
if(has_comps)
{
for (std::map<std::string, std::string>::iterator it = comps.begin();
it != comps.end(); ++it)
{
if (next(it->first, 0, "writer_"))
{
std::string idx = getafter("writer_", it->first);
std::string componentName = comps["name_" + idx];
std::string logicalPath = comps["path_" + idx];
VSS_ID writerId;
HRESULT hr = IIDFromString(ConvertToUnicode(comps["writer_" + idx]).c_str(), &writerId);
if (hr == S_OK)
{
for (std::map<wxTreeItemId, SComponent*>::iterator it = tree_components.begin();
it != tree_components.end(); ++it)
{
if (!it->second->is_root
&& it->second->writerId == writerId
&& (it->second->name == componentName || (componentName.empty() && it->second->writer) )
&& it->second->logicalPath == logicalPath
&& m_treeCtrl1->GetItemState(it->first)==0)
{
selectTreeItems(it->second, true);
if (!it->second->children.empty())
{
wxTreeItemId nodeId = tree_items[it->second];
m_treeCtrl1->ExpandAllChildren(nodeId);
}
SComponent* node = it->second->parent;
while (node != NULL)
{
wxTreeItemId nodeId = tree_items[node];
m_treeCtrl1->Expand(nodeId);
node = node->parent;
}
break;
}
}
}
}
}
}
}
}
void SelectWindowsComponents::evtOnTreeItemGetTooltip(wxTreeEvent & event)
{
SComponent* component = tree_components[event.GetItem()];
if (component == NULL)
{
return;
}
std::string tooltip =component->name;
if (!tooltip.empty())
{
event.SetToolTip(tooltip);
}
}
void SelectWindowsComponents::evtOnTreeStateImageClick(wxTreeEvent & event)
{
SComponent* component = tree_components[event.GetItem()];
if (component == NULL)
{
return;
}
bool select = m_treeCtrl1->GetItemState(event.GetItem()) == 0;
selectTreeItems(component, select);
}
void SelectWindowsComponents::onOkClick(wxCommandEvent & event)
{
std::string res;
if (m_treeCtrl1->GetItemState(tree_items[componentReader.getRoot()]) == 1)
{
res = "all=1";
}
else
{
size_t idx = 0;
collectComponents(componentReader.getRoot(), idx, res);
}
int use = use_orig;
use |= c_use_value_client;
std::string s_data = "vss_select_components=" + res+"\n";
if (use != use_orig)
{
s_data += "vss_select_components.use=" + nconvert(use) + "\n";
int64 ctime = wxGetUTCTimeMillis().GetValue() / 1000;
if (use_lm_orig > ctime)
ctime = use_lm_orig + 1;
s_data += "default_dirs.use_lm=" + nconvert(ctime) + "\n";
}
Connector::updateSettings(s_data);
Close();
}
void SelectWindowsComponents::onCancel(wxCommandEvent & event)
{
Close();
}
void SelectWindowsComponents::addComponents(wxTreeCtrl* tree, wxImageList* iconList, wxTreeItemId treeId,
SComponent * node, std::map<wxTreeItemId, SComponent*>& tree_components,
std::map<SComponent*, wxTreeItemId>& tree_items, int icon_width, int icon_height)
{
for (size_t i = 0; i < node->children.size(); ++i)
{
SComponent* child = node->children[i];
int image = -1;
if (!child->icon.empty())
{
wxFileName tempFile;
tempFile.AssignTempFileName("winCompIco");
if (tempFile.IsOk())
{
std::fstream out;
out.open(tempFile.GetFullPath().ToStdWstring(), std::ios::out | std::ios::binary);
if (out.is_open())
{
out.write(child->icon.data(), child->icon.size());
out.close();
wxIcon icon(tempFile.GetFullPath(), wxBITMAP_TYPE_ICO, icon_width, icon_height);
if (icon.IsOk())
{
image = iconList->GetImageCount();
if (icon.GetWidth() == icon_width
&& icon.GetHeight() == icon_height)
{
iconList->Add(icon);
}
else
{
iconList->Add(wxBitmap(wxBitmap(icon).ConvertToImage().Rescale(icon_width, icon_height)));
}
}
}
DeleteFile(tempFile.GetFullPath().wc_str());
}
}
int checked = -1;
if (child->writer)
{
checked = 0;
}
else if (child->selectable)
{
checked = 0;
}
std::string name = child->displayName;
if (name.empty())
{
name = child->name;
}
wxTreeItemId childId = tree->AppendItem(treeId, name, image);
if (checked >= 0)
{
tree->SetItemState(childId, checked);
}
tree_components[childId] = child;
tree_items[child] = childId;
addComponents(tree, iconList, childId, child, tree_components, tree_items,
icon_width, icon_height);
}
}
void SelectWindowsComponents::selectTreeItems(wxTreeCtrl* tree, std::map<SComponent*, wxTreeItemId>& tree_items,
SComponent* root, SComponent * node, bool select, bool removeSelect)
{
wxTreeItemId nodeId = tree_items[node];
int new_itemstate=-5;
if (tree->GetItemState(nodeId) != wxTREE_ITEMSTATE_NONE)
{
if (select && removeSelect)
{
tree->SetItemState(nodeId, wxTREE_ITEMSTATE_NONE);
new_itemstate = wxTREE_ITEMSTATE_NONE;
}
else
{
new_itemstate = select ? 1 : 0;
tree->SetItemState(nodeId, new_itemstate);
}
}
else if (!select && !node->writer && node->selectable)
{
tree->SetItemState(nodeId, 0);
new_itemstate = 0;
}
if (!node->writer)
{
for (size_t i = 0; i < root->children.size(); ++i)
{
if (root->children[i]->writerId == node->writerId)
{
bool has_selectable_child = false;
if (!allChildrenSelected(tree, tree_items, root->children[i], has_selectable_child))
{
tree->SetItemState(tree_items[root->children[i]], 0);
}
if (!has_selectable_child)
{
tree->SetItemState(tree_items[root->children[i]], select ? 1 : 0);
}
break;
}
}
}
if (node != root)
{
bool has_selectable_child = false;
if (!allChildrenSelected(tree, tree_items, root, has_selectable_child))
{
tree->SetItemState(tree_items[root], 0);
}
}
for(size_t i=0;i<node->dependencies.size();++i)
{
selectTreeItems(tree, tree_items, root, node->dependencies[i], select);
}
for (size_t i = 0; i < node->children.size(); ++i)
{
bool curr_remove_select = select && !node->writer && node->selectable;
selectTreeItems(tree, tree_items, root, node->children[i], select, curr_remove_select);
}
if (new_itemstate != -5)
{
tree->SetItemState(nodeId, new_itemstate);
}
}
bool SelectWindowsComponents::hasSelectedChild(wxTreeCtrl* tree, std::map<SComponent*, wxTreeItemId>& tree_items,
SComponent * node)
{
for (size_t i = 0; i < node->children.size(); ++i)
{
SComponent* child = node->children[i];
wxTreeItemId nodeId = tree_items[child];
if (tree->GetItemState(nodeId) == 1)
{
return true;
}
if (hasSelectedChild(tree, tree_items, child))
{
return true;
}
}
return false;
}
bool SelectWindowsComponents::allChildrenSelected(wxTreeCtrl * tree, std::map<SComponent*, wxTreeItemId>& tree_items,
SComponent * node, bool& has_selectable_child)
{
for (size_t i = 0; i < node->children.size(); ++i)
{
SComponent* child = node->children[i];
wxTreeItemId nodeId = tree_items[child];
if (tree->GetItemState(nodeId) != wxTREE_ITEMSTATE_NONE)
{
has_selectable_child = true;
}
if (tree->GetItemState(nodeId)!=1
&& tree->GetItemState(nodeId)!= wxTREE_ITEMSTATE_NONE)
{
return false;
}
if (!allChildrenSelected(tree, tree_items, child, has_selectable_child))
{
return false;
}
}
return true;
}
void SelectWindowsComponents::selectTreeItems(SComponent * node, bool select, bool removeSelect)
{
selectTreeItems(m_treeCtrl1, tree_items, componentReader.getRoot(),
node, select, removeSelect);
}
void SelectWindowsComponents::collectComponents(SComponent * node, size_t & idx, std::string& res)
{
wxTreeItemId nodeId = tree_items[node];
int state = m_treeCtrl1->GetItemState(nodeId);
if (node != componentReader.getRoot())
{
if ( state==1 )
{
if (!res.empty())
{
res += "&";
}
res += "writer_" + convert(idx) + "=" + convert(node->writerId);
if (node->writer)
{
res += "&name_" + convert(idx) + "=";
}
else
{
res += "&name_" + convert(idx) + "=" + EscapeParamString(node->name);
}
res += "&path_" + convert(idx) + "=" + EscapeParamString(node->logicalPath);
++idx;
}
}
if( state != wxTREE_ITEMSTATE_NONE )
{
for (size_t i = 0; i < node->children.size(); ++i)
{
collectComponents(node->children[i], idx, res);
}
}
}
WindowsComponentReader::WindowsComponentReader()
: wxThread(wxTHREAD_JOINABLE)
{
root.is_root = true;
}
WindowsComponentReader::~WindowsComponentReader()
{
for (size_t i = 0; i < components.size(); ++i)
{
delete components[i];
}
}
SComponent * WindowsComponentReader::getRoot()
{
return &root;
}
bool WindowsComponentReader::readComponents(const std::string& restoreXml, const std::vector<std::string>& componentXmls,
const std::vector<SComponent>& filter_except, SComponent & root, std::vector<SComponent*>& components, std::string& errmsg)
{
HRESULT hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
if (hr != S_OK)
{
errmsg = "CoInitializeEx failed " + GetErrorHResErrStr(hr);
return false;
}
SCOPED_DECLARE_RELEASE_IUNKNOWN(IVssBackupComponents, backupcom);
hr = CreateVssBackupComponents(&backupcom);
if (hr != S_OK || backupcom == NULL)
{
errmsg = "Error creating backup components " + GetErrorHResErrStr(hr);
return false;
}
if (!restoreXml.empty())
{
hr = backupcom->InitializeForRestore(const_cast<BSTR>(ConvertToUnicode(restoreXml).c_str()));
if (hr != S_OK)
{
errmsg = "Error initializing components for restore " + GetErrorHResErrStr(hr);
return false;
}
}
else
{
hr = backupcom->InitializeForBackup();
if (hr != S_OK)
{
errmsg = "Error initializing components for backup " + GetErrorHResErrStr(hr);
return false;
}
}
UINT nwriters;
if (restoreXml.empty())
{
SCOPED_DECLARE_RELEASE_IUNKNOWN(IVssAsync, pb_result);
hr = backupcom->GatherWriterMetadata(&pb_result);
if (hr != S_OK)
{
errmsg = "Error gathering writer metadata " + GetErrorHResErrStr(hr);
return false;
}
if (!wait_for(pb_result, "Gathering writer metadata failed", errmsg))
{
return false;
}
hr = backupcom->GetWriterMetadataCount(&nwriters);
if (hr != S_OK)
{
errmsg = "Error getting writer metadata count";
return false;
}
}
else
{
nwriters = static_cast<UINT>(componentXmls.size());
}
size_t maxDepth = 0;
for (UINT i = 0; i < nwriters; ++i)
{
VSS_ID writerInstance;
SCOPED_DECLARE_RELEASE_IUNKNOWN(IVssExamineWriterMetadata, writerMetadata);
HRESULT hr;
if (restoreXml.empty())
{
hr = backupcom->GetWriterMetadata(i, &writerInstance, &writerMetadata);
}
else
{
hr = CreateVssExamineWriterMetadata(const_cast<BSTR>(ConvertToUnicode(componentXmls[i]).c_str()), &writerMetadata);
}
if (hr != S_OK)
{
errmsg = "Getting metadata of writer " + convert(i) + " failed. VSS error code " + GetErrorHResErrStr(hr);
continue;
}
VSS_ID instanceId;
VSS_ID writerId;
SCOPED_DECLARE_FREE_BSTR(writerName);
VSS_USAGE_TYPE usageType;
VSS_SOURCE_TYPE sourceType;
hr = writerMetadata->GetIdentity(&instanceId, &writerId, &writerName, &usageType, &sourceType);
if (hr != S_OK)
{
errmsg = "Getting identity of writer " + convert(i) + " failed. VSS error code " + GetErrorHResErrStr(hr);
continue;
}
//Always skip System writer and ASR writer
if (convert(writerId) == "{E8132975-6F93-4464-A53E-1050253AE220}"
|| convert(writerId) == "{BE000CBE-11FE-4426-9C58-531AA6355FC4}")
{
continue;
}
std::string writerNameStr = ConvertFromWchar(writerName);
UINT nIncludeFiles, nExcludeFiles, nComponents;
hr = writerMetadata->GetFileCounts(&nIncludeFiles, &nExcludeFiles, &nComponents);
if (hr != S_OK)
{
errmsg = "GetFileCounts of writer \"" + writerNameStr + "\" failed. VSS error code " + GetErrorHResErrStr(hr);
continue;
}
if (nComponents > 0)
{
SComponent* component = new SComponent;
component->writerId = writerId;
component->name = writerNameStr;
component->selectable = true;
component->writer = true;
component->parent = &root;
components.push_back(component);
if (maxDepth == 0) maxDepth = 1;
}
for (UINT j = 0; j < nComponents; ++j)
{
SCOPED_DECLARE_RELEASE_IUNKNOWN(IVssWMComponent, wmComponent);
hr = writerMetadata->GetComponent(j, &wmComponent);
if (hr != S_OK)
{
errmsg = "Error getting component " + convert(j) + " of writer \"" + writerNameStr + "\" failed. VSS error code " + GetErrorHResErrStr(hr);
continue;
}
SCOPED_DECLARE_FREE_COMPONENTINFO(wmComponent, componentInfo);
hr = wmComponent->GetComponentInfo(&componentInfo);
if (hr != S_OK)
{
errmsg = "Error getting component info " + convert(j) + " of writer \"" + writerNameStr + "\" failed. VSS error code " + GetErrorHResErrStr(hr);
continue;
}
std::string componentNameStr = ConvertFromWchar(componentInfo->bstrComponentName);
std::string logicalPathStr;
if (componentInfo->bstrLogicalPath != NULL)
{
logicalPathStr = ConvertFromWchar(componentInfo->bstrLogicalPath);
}
SComponent* component = new SComponent;
component->logicalPath = logicalPathStr;
component->name = componentNameStr;
component->writerId = writerId;
component->writer = false;
if (restoreXml.empty())
{
component->selectable = componentInfo->bSelectable == TRUE;
}
else
{
component->selectable = componentInfo->bSelectableForRestore == TRUE;
}
if (componentInfo->bstrCaption != NULL)
{
component->displayName = ConvertFromWchar(componentInfo->bstrCaption);
}
if (componentInfo->cbIcon > 0)
{
int abc = 5;
}
bool filtered = true;
if (filter_except.empty())
{
filtered = false;
}
else
{
for (size_t k = 0; k < filter_except.size(); ++k)
{
if (filter_except[k].name == component->name
&& filter_except[k].writerId == component->writerId
&& filter_except[k].logicalPath == component->logicalPath)
{
filtered = false;
break;
}
}
}
if (!filtered)
{
component->icon.resize(componentInfo->cbIcon);
memcpy(component->icon.data(), componentInfo->pbIcon, componentInfo->cbIcon);
components.push_back(component);
std::vector<std::string> toks;
TokenizeMail(logicalPathStr, toks, "\\");
if (toks.size() + 2 > maxDepth)
{
maxDepth = toks.size() + 2;
}
}
}
}
for (size_t depth = 0; depth < maxDepth; ++depth)
{
for (size_t i = 0; i < components.size(); ++i)
{
std::vector<std::string> toks;
TokenizeMail(components[i]->logicalPath, toks, "\\");
SComponent* parent = NULL;
if (components[i]->writer
&& depth == 0)
{
parent = &root;
}
else if (!components[i]->writer
&& toks.size() + 1 == depth)
{
parent = getComponent(&root, components[i]->writerId, components[i]->logicalPath);
}
if (parent != NULL)
{
if (!toks.empty())
{
size_t off = 0;
if (!parent->logicalPath.empty())
{
off = parent->logicalPath.size() + 1;
}
components[i]->logicalPathComponent = components[i]->logicalPath.substr(off);
}
if (components[i]->logicalPathComponent.empty())
{
components[i]->logicalPathComponent = components[i]->name;
}
else
{
components[i]->logicalPathComponent += "\\" + components[i]->name;
}
components[i]->parent = parent;
parent->children.push_back(components[i]);
}
}
}
for (UINT i = 0; i < nwriters; ++i)
{
VSS_ID writerInstance;
SCOPED_DECLARE_RELEASE_IUNKNOWN(IVssExamineWriterMetadata, writerMetadata);
HRESULT hr;
if (restoreXml.empty())
{
hr = backupcom->GetWriterMetadata(i, &writerInstance, &writerMetadata);
}
else
{
hr = CreateVssExamineWriterMetadata(const_cast<BSTR>(ConvertToUnicode(componentXmls[i]).c_str()), &writerMetadata);
}
if (hr != S_OK)
{
errmsg = "Getting metadata of writer " + convert(i) + " failed. VSS error code " + GetErrorHResErrStr(hr);
continue;
}
VSS_ID instanceId;
VSS_ID writerId;
SCOPED_DECLARE_FREE_BSTR(writerName);
VSS_USAGE_TYPE usageType;
VSS_SOURCE_TYPE sourceType;
hr = writerMetadata->GetIdentity(&instanceId, &writerId, &writerName, &usageType, &sourceType);
if (hr != S_OK)
{
errmsg = "Getting identity of writer " + convert(i) + " failed. VSS error code " + GetErrorHResErrStr(hr);
continue;
}
//Always skip System writer and ASR writer
if (convert(writerId) == "{E8132975-6F93-4464-A53E-1050253AE220}"
|| convert(writerId) == "{BE000CBE-11FE-4426-9C58-531AA6355FC4}")
{
continue;
}
std::string writerNameStr = ConvertFromWchar(writerName);
UINT nIncludeFiles, nExcludeFiles, nComponents;
hr = writerMetadata->GetFileCounts(&nIncludeFiles, &nExcludeFiles, &nComponents);
if (hr != S_OK)
{
errmsg = "GetFileCounts of writer \"" + writerNameStr + "\" failed. VSS error code " + GetErrorHResErrStr(hr);
continue;
}
for (UINT j = 0; j < nComponents; ++j)
{
SCOPED_DECLARE_RELEASE_IUNKNOWN(IVssWMComponent, wmComponent);
hr = writerMetadata->GetComponent(j, &wmComponent);
if (hr != S_OK)
{
errmsg = "Error getting component " + convert(j) + " of writer \"" + writerNameStr + "\" failed. VSS error code " + GetErrorHResErrStr(hr);
continue;
}
SCOPED_DECLARE_FREE_COMPONENTINFO(wmComponent, componentInfo);
hr = wmComponent->GetComponentInfo(&componentInfo);
if (hr != S_OK)
{
errmsg = "Error getting component info " + convert(j) + " of writer \"" + writerNameStr + "\" failed. VSS error code " + GetErrorHResErrStr(hr);
continue;
}
std::string componentNameStr = ConvertFromWchar(componentInfo->bstrComponentName);
std::string logicalPathStr;
if (componentInfo->bstrLogicalPath != NULL)
{
logicalPathStr = ConvertFromWchar(componentInfo->bstrLogicalPath);
}
SComponent* component = getComponent(&root, writerId, logicalPathStr);
if (component == NULL)
{
errmsg = "Error getting component node of component \"" +
componentNameStr + "\" of writer \"" + writerNameStr + "\"";
continue;
}
for (UINT k = 0; k < componentInfo->cDependencies; ++k)
{
SCOPED_DECLARE_RELEASE_IUNKNOWN(IVssWMDependency, wmDependency);
hr = wmComponent->GetDependency(k, &wmDependency);
if (hr != S_OK)
{
errmsg = "Error getting component dependency " + convert(k) + " of component \"" +
componentNameStr + "\" of writer \"" + writerNameStr + "\" failed. VSS error code " + GetErrorHResErrStr(hr);
continue;
}
SCOPED_DECLARE_FREE_BSTR(componentName);
hr = wmDependency->GetComponentName(&componentName);
if (hr != S_OK)
{
errmsg = "Error getting component name of dependency " + convert(k) + " of component \"" +
componentNameStr + "\" of writer \"" + writerNameStr + "\" failed. VSS error code " + GetErrorHResErrStr(hr);
continue;
}
SCOPED_DECLARE_FREE_BSTR(logicalPath);
hr = wmDependency->GetLogicalPath(&logicalPath);
if (hr != S_OK)
{
errmsg = "Error getting logical path of dependency " + convert(k) + " of component \"" +
componentNameStr + "\" of writer \"" + writerNameStr + "\" failed. VSS error code " + GetErrorHResErrStr(hr);
continue;
}
std::string dependencylogicalPathStr;
if (logicalPath != NULL)
{
dependencylogicalPathStr = ConvertFromWchar(logicalPath);
}
VSS_ID dependencyWriterId;
hr = wmDependency->GetWriterId(&dependencyWriterId);
if (hr != S_OK)
{
errmsg = "Error getting writer id of dependency " + convert(k) + " of component \"" +
componentNameStr + "\" of writer \"" + writerNameStr + "\" failed. VSS error code " + GetErrorHResErrStr(hr);
continue;
}
SComponent* dependency = getComponent(&root, dependencyWriterId, dependencylogicalPathStr);
if (dependency == NULL)
{
errmsg = "Could not find dependency " + convert(k) + " of component \"" +
componentNameStr + "\" of writer \"" + writerNameStr + "\"";
}
}
}
}
return true;
}
wxThread::ExitCode WindowsComponentReader::Entry()
{
readComponents(std::string(), std::vector<std::string>(), std::vector<SComponent>(),
root, components, errmsg);
return ExitCode();
}
std::string GetErrorHResErrStr(HRESULT res)
{
#define CASE_VSS_ERROR(x) case x: return #x
switch (res)
{
case S_OK:
return "S_OK";
case E_INVALIDARG:
return "E_INVALIDARG";
case E_OUTOFMEMORY:
return "E_OUTOFMEMORY";
case E_UNEXPECTED:
return "E_UNEXPECTED";
case E_ACCESSDENIED:
return "E_ACCESSDENIED";
case VSS_E_OBJECT_NOT_FOUND:
return "VSS_E_OBJECT_NOT_FOUND";
case VSS_E_PROVIDER_VETO:
return "VSS_E_PROVIDER_VETO";
case VSS_E_UNEXPECTED_PROVIDER_ERROR:
return "VSS_E_UNEXPECTED_PROVIDER_ERROR";
case VSS_E_BAD_STATE:
return "VSS_E_BAD_STATE";
case VSS_E_SNAPSHOT_SET_IN_PROGRESS:
return "VSS_E_SNAPSHOT_SET_IN_PROGRESS";
case VSS_E_MAXIMUM_NUMBER_OF_VOLUMES_REACHED:
return "VSS_E_MAXIMUM_NUMBER_OF_VOLUMES_REACHED";
case VSS_E_MAXIMUM_NUMBER_OF_SNAPSHOTS_REACHED:
return "VSS_E_MAXIMUM_NUMBER_OF_SNAPSHOTS_REACHED";
case VSS_E_PROVIDER_NOT_REGISTERED:
return "VSS_E_PROVIDER_NOT_REGISTERED";
case VSS_E_VOLUME_NOT_SUPPORTED:
return "VSS_E_VOLUME_NOT_SUPPORTED";
case VSS_E_VOLUME_NOT_SUPPORTED_BY_PROVIDER:
return "VSS_E_VOLUME_NOT_SUPPORTED_BY_PROVIDER";
CASE_VSS_ERROR(VSS_E_INSUFFICIENT_STORAGE);
CASE_VSS_ERROR(VSS_E_FLUSH_WRITES_TIMEOUT);
CASE_VSS_ERROR(VSS_E_HOLD_WRITES_TIMEOUT);
CASE_VSS_ERROR(VSS_E_NESTED_VOLUME_LIMIT);
CASE_VSS_ERROR(VSS_E_REBOOT_REQUIRED);
CASE_VSS_ERROR(VSS_E_TRANSACTION_FREEZE_TIMEOUT);
CASE_VSS_ERROR(VSS_E_TRANSACTION_THAW_TIMEOUT);
CASE_VSS_ERROR(S_FALSE);
CASE_VSS_ERROR(VSS_E_INVALID_XML_DOCUMENT);
CASE_VSS_ERROR(VSS_E_UNEXPECTED);
};
#undef CASE_VSS_ERROR
return "UNDEF(" + nconvert((long long int)res) + ")";
}
bool WindowsComponentReader::wait_for(IVssAsync * vsasync, const std::string & error_prefix, std::string& errmsg)
{
if (vsasync == NULL)
{
errmsg = "vsasync is NULL";
return false;
}
HRESULT hr = vsasync->Wait();
if (hr != S_OK)
{
errmsg = "Waiting for async result failed " + GetErrorHResErrStr(hr);
return false;
}
HRESULT res;
hr = vsasync->QueryStatus(&res, NULL);
if (hr != S_OK)
{
errmsg = "Querying async result status failed " + GetErrorHResErrStr(hr);
return false;
}
while (res == VSS_S_ASYNC_PENDING)
{
hr = vsasync->Wait();
if (hr != S_OK)
{
errmsg = "Waiting for async result failed (2) " + GetErrorHResErrStr(hr);
return false;
}
hr = vsasync->QueryStatus(&res, NULL);
if (hr != S_OK)
{
errmsg = "Querying async result status failed (2) " + GetErrorHResErrStr(hr);
return false;
}
}
if (res != VSS_S_ASYNC_FINISHED)
{
errmsg= error_prefix + ". Error code " + GetErrorHResErrStr(res);
return false;
}
return true;
}
SComponent * WindowsComponentReader::getComponent(SComponent* node, VSS_ID writerId, std::string logical_path)
{
if (node->is_root)
{
for (size_t i = 0; i < node->children.size(); ++i)
{
if (node->children[i]->writerId == writerId)
{
if (logical_path.empty())
{
return node->children[i];
}
SComponent* ret = getComponent(node->children[i], writerId, logical_path);
if (ret == NULL)
{
return node->children[i];
}
else
{
return ret;
}
}
}
return NULL;
}
std::string remainingPath = logical_path;
std::string nextPath;
do
{
if (!nextPath.empty())
{
nextPath += "\\";
}
nextPath += getuntil("\\", remainingPath);
std::string prevRemainingPath = remainingPath;
remainingPath = getafter("\\", remainingPath);
if (remainingPath.empty())
{
nextPath += prevRemainingPath;
remainingPath.clear();
}
for (size_t i = 0; i < node->children.size(); ++i)
{
if (node->children[i]->writerId == writerId
&& node->children[i]->logicalPathComponent == nextPath)
{
if (remainingPath.empty())
{
return node->children[i];
}
else
{
return getComponent(node->children[i], writerId, remainingPath);
}
}
}
} while (!remainingPath.empty());
return NULL;
}