CA_API UINT __stdcall Xml_DeleteNodes(MSIHANDLE hInstall) { MSI_EXCEPTION_HANDLER_PROLOG; MsiInstall msiInstall(hInstall); std::wstring filename = msiInstall.GetProperty(L"XML_FILENAME"); AppSecInc::Xml::XmlDocument doc; doc.Load(filename); std::wstring xpath = msiInstall.GetProperty(L"XML_XPATH"); MSXML2::IXMLDOMNodeListPtr nodes = doc.FindNodes(xpath); int count = 0; if (NULL != nodes) { MSXML2::IXMLDOMNodePtr node = NULL; while (NULL != (node = nodes->nextNode())) { node->parentNode->removeChild(node); count++; } } if (count > 0) { CHECK_HR(doc->save(CComVariant(filename.c_str())), L"Error saving '" << filename << L"'"); } msiInstall.SetProperty(L"XML_DELETED", AppSecInc::StringUtils::toWString(count)); MSI_EXCEPTION_HANDLER_EPILOG; return ERROR_SUCCESS; }
CA_API UINT __stdcall Win32_GenerateGuidString(MSIHANDLE hInstall) { MSI_EXCEPTION_HANDLER_PROLOG; MsiInstall msiInstall(hInstall); msiInstall.SetProperty(L"WIN32_GUID_STRING", AppSecInc::Com::GenerateGUIDStringW()); MSI_EXCEPTION_HANDLER_EPILOG; return ERROR_SUCCESS; }
CA_API UINT __stdcall Win32_IsValidGuid(MSIHANDLE hInstall) { MSI_EXCEPTION_HANDLER_PROLOG; MsiInstall msiInstall(hInstall); std::wstring guid = msiInstall.GetProperty(L"WIN32_GUID_STRING"); msiInstall.SetProperty(L"WIN32_GUID_VALID", AppSecInc::Com::IsValidGUID(guid) ? L"1" : L"0"); MSI_EXCEPTION_HANDLER_EPILOG; return ERROR_SUCCESS; }
CA_API UINT __stdcall TemplateFiles_Deferred(MSIHANDLE hInstall) { MSI_EXCEPTION_HANDLER_PROLOG; MsiInstall msiInstall(hInstall); AppSecInc::Xml::XmlDocument xmlDocument; xmlDocument.LoadXml(msiInstall.GetActionData()); MSXML2::IXMLDOMNodeListPtr rows = xmlDocument.SelectNodes(L"//TemplateFile[@execute='true']"); // \todo //Row[@rollback='false'] MSXML2::IXMLDOMNodePtr row = NULL; while (NULL != (row = rows->nextNode())) { std::wstring id = xmlDocument.GetAttributeValue(L"id", row); std::wstring source = xmlDocument.GetNodeValue(L"Source", row); std::wstring target = xmlDocument.GetNodeValue(L"Target", row, source); msiInstall.LogInfo(L"TemplateFiles_Deferred", source + L" => " + target); std::map<std::wstring, std::wstring> properties; { MSXML2::IXMLDOMNodeListPtr property_rows = xmlDocument.SelectNodes(L"Properties/Property", row); MSXML2::IXMLDOMNodePtr property_row = NULL; while (NULL != (property_row = property_rows->nextNode())) { std::wstring name = xmlDocument.GetAttributeValue(L"name", property_row); std::wstring value = xmlDocument.GetAttributeValue(L"value", property_row); long escape = AppSecInc::StringUtils::stringToLong(xmlDocument.GetAttributeValue(L"escape", property_row, L"0")); properties[name] = escape == 1 ? AppSecInc::StringUtils::escape(value) : value; } } std::wstring data; bool utf8 = AppSecInc::File::ReadAndConvertToEnd(source, data); data = AppSecInc::Formatter::FormatTemplate(data, properties); std::string char_data; if (utf8) { char_data = AppSecInc::StringUtils::wc2utf8(data); char_data.insert(0, std::string(reinterpret_cast<char *>(AppSecInc::File::utf8_bom))); } else { char_data = AppSecInc::StringUtils::wc2mb(data); } std::vector<char> binary_data; binary_data.assign(char_data.begin(), char_data.end()); AppSecInc::File::FileWrite(target, binary_data); } MSI_EXCEPTION_HANDLER_EPILOG; return ERROR_SUCCESS; }
CA_API UINT __stdcall GenerateRandomString(MSIHANDLE hInstall) { MSI_EXCEPTION_HANDLER_PROLOG; MsiInstall msiInstall(hInstall); long size = AppSecInc::StringUtils::stringToLong(msiInstall.GetProperty(L"GENERATE_RANDOM_LENGTH")); std::vector<byte> data = AppSecInc::Crypt::CryptoPPImpl::GenerateRandom(size); std::string output = AppSecInc::Crypt::CryptoPPImpl::Base64Encode(data); output.erase(size); msiInstall.SetProperty("GENERATE_RANDOM_RESULT", output); MSI_EXCEPTION_HANDLER_EPILOG; return ERROR_SUCCESS; }
CA_API UINT __stdcall Xml_SelectNodeValue(MSIHANDLE hInstall) { MSI_EXCEPTION_HANDLER_PROLOG; MsiInstall msiInstall(hInstall); std::wstring filename = msiInstall.GetProperty(L"XML_FILENAME"); AppSecInc::Xml::XmlDocument doc; doc.Load(filename); std::wstring xpath = msiInstall.GetProperty(L"XML_XPATH"); std::wstring value = doc.GetNodeValue(xpath); msiInstall.SetProperty(L"XML_NODEVALUE", value); MSI_EXCEPTION_HANDLER_EPILOG; return ERROR_SUCCESS; }
CA_API UINT __stdcall Xml_XslTransform(MSIHANDLE hInstall) { MSI_EXCEPTION_HANDLER_PROLOG; MsiInstall msiInstall(hInstall); std::wstring filename = msiInstall.GetProperty(L"XML_FILENAME"); AppSecInc::Xml::XmlDocument doc; doc.Load(filename); std::wstring xslt_filename = msiInstall.GetProperty(L"XSLT_FILENAME"); std::wstring xslt_result_filename = msiInstall.GetProperty(L"XSLT_RESULT_FILENAME"); std::wstring transformedData = doc.XslTransform(xslt_filename); std::string char_data = AppSecInc::StringUtils::wc2mb(transformedData); std::vector<char> binary_data; binary_data.assign(char_data.begin(), char_data.end()); AppSecInc::File::FileWrite(xslt_result_filename, binary_data); MSI_EXCEPTION_HANDLER_EPILOG; return ERROR_SUCCESS; }
CA_API UINT __stdcall TemplateFiles_Immediate(MSIHANDLE hInstall) { MSI_EXCEPTION_HANDLER_PROLOG; MsiInstall msiInstall(hInstall); // combined xml document AppSecInc::Xml::XmlDocument combined_xml_document; combined_xml_document.Create(); MSXML2::IXMLDOMNodePtr combined_xml_root = combined_xml_document.AppendChild(L"TemplateFiles"); std::wstring xml = msiInstall.GetViewData(L"SELECT * FROM `TemplateFiles`"); AppSecInc::Xml::XmlDocument xmlDocument; xmlDocument.LoadXml(xml); { MSXML2::IXMLDOMNodeListPtr rows = xmlDocument.SelectNodes(L"//Row"); MSXML2::IXMLDOMNodePtr row = NULL; while (NULL != (row = rows->nextNode())) { // id std::wstring templatefile_id = xmlDocument.GetNodeValue(L"Data[@Column=\"Id\"]", row, L""); // component id std::wstring component_id = xmlDocument.GetNodeValue(L"Data[@Column=\"ComponentId\"]", row, L""); // node condition std::wstring condition = xmlDocument.GetNodeValue(L"Data[@Column=\"Condition\"]", row); // operational attributes long attributes = AppSecInc::StringUtils::stringToLong(xmlDocument.GetNodeValue(L"Data[@Column=\"Attributes\"]", row)); // no condition (executes by default) or condition evaluates to true bool execute_per_condition = condition.empty() || msiInstall.EvaluateCondition(condition); if (! condition.empty()) { // set the evaluated value for debugging purposes xmlDocument.SelectNode(L"Data[@Column=\"Condition\"]", row)->text = _bstr_t(execute_per_condition ? L"1" : L"0"); } // execute on install bool execute_per_component_install = (component_id.empty() || msiInstall.IsComponentInstalling(component_id)); // execute on uninstall bool execute_per_component_uninstall = (component_id.empty() || msiInstall.IsComponentUnInstalling(component_id)); // execute on reinstall bool execute_per_component_reinstall = (component_id.empty() || msiInstall.IsComponentReInstalling(component_id)); bool execute = execute_per_condition && ( (execute_per_component_install && (attributes & ExecuteOnInstall) && msiInstall.IsInstalling()) || (execute_per_component_uninstall && (attributes & ExecuteOnUnInstall) && msiInstall.IsUnInstalling()) || (execute_per_component_reinstall && (attributes & ExecuteOnReInstall) && msiInstall.IsReInstalling()) ); MSXML2::IXMLDOMNodePtr templatefile_node = combined_xml_document.AppendChild(L"TemplateFile", combined_xml_root); combined_xml_document.SetAttribute(L"id", templatefile_id, templatefile_node); std::wstring source = xmlDocument.GetNodeValue(L"Data[@Column=\"Source\"]", row); std::wstring target = xmlDocument.GetNodeValue(L"Data[@Column=\"Target\"]", row, source); combined_xml_document.AppendChild(L"Source", templatefile_node)->text = _bstr_t(source.c_str()); combined_xml_document.AppendChild(L"Target", templatefile_node)->text = _bstr_t(target.c_str()); combined_xml_document.SetAttribute(L"execute", execute ? L"true" : L"false", templatefile_node); MSXML2::IXMLDOMNodePtr properties_node = combined_xml_document.AppendChild(L"Properties", templatefile_node); // append built-in properties { AppSecInc::Xml::XmlDocument xmlPropertiesDocument; xmlPropertiesDocument.LoadXml(msiInstall.GetViewData(L"SELECT * FROM `Property`")); MSXML2::IXMLDOMNodeListPtr property_rows = xmlPropertiesDocument.SelectNodes(L"//Row"); MSXML2::IXMLDOMNodePtr property_row = NULL; while (NULL != (property_row = property_rows->nextNode())) { std::wstring name = xmlPropertiesDocument.GetNodeValue(L"Data[@Column=\"Property\"]", property_row); std::wstring value = xmlPropertiesDocument.GetNodeValue(L"Data[@Column=\"Value\"]", property_row); MSXML2::IXMLDOMNodePtr property_node = combined_xml_document.AppendChild(L"Property", properties_node); combined_xml_document.SetAttribute(L"name", name, property_node); combined_xml_document.SetAttribute(L"value", value, property_node); } } // append properties from this TemplateFile { AppSecInc::Xml::XmlDocument xmlPropertiesDocument; xmlPropertiesDocument.LoadXml(msiInstall.GetViewData(L"SELECT * FROM `TemplateFileProperties`")); MSXML2::IXMLDOMNodeListPtr property_rows = xmlPropertiesDocument.SelectNodes(L"//Row"); MSXML2::IXMLDOMNodePtr property_row = NULL; while (NULL != (property_row = property_rows->nextNode())) { // \todo Change XPATH to fetch only rows that match ID std::wstring id = xmlPropertiesDocument.GetNodeValue(L"Data[@Column=\"TemplateFileId\"]", property_row); if (id != templatefile_id) continue; std::wstring name = xmlPropertiesDocument.GetNodeValue(L"Data[@Column=\"Name\"]", property_row); std::wstring value = xmlPropertiesDocument.GetNodeValue(L"Data[@Column=\"Value\"]", property_row); std::wstring escape = xmlPropertiesDocument.GetNodeValue(L"Data[@Column=\"Escape\"]", property_row); MSXML2::IXMLDOMNodePtr property_node = combined_xml_document.AppendChild(L"Property", properties_node); combined_xml_document.SetAttribute(L"name", name, property_node); combined_xml_document.SetAttribute(L"value", value, property_node); combined_xml_document.SetAttribute(L"escape", escape, property_node); } } } } msiInstall.SetActionData(L"TemplateFiles_Deferred", combined_xml_document.GetXml()); MSI_EXCEPTION_HANDLER_EPILOG; return ERROR_SUCCESS; }
CA_API UINT __stdcall LocalGroupMembers_Immediate(MSIHANDLE hInstall) { MSI_EXCEPTION_HANDLER_PROLOG; MsiInstall msiInstall(hInstall); typedef enum LocalGroupMemberAttributes { AddOnInstall = 1, AddOnUnInstall = 2, RemoveOnInstall = 4, RemoveOnUnInstall = 8, CheckIfMember = 16 }; // local groups std::map<std::wstring, std::wstring> localgroups_map; AppSecInc::Xml::XmlDocument localgroups_xml_document; localgroups_xml_document.LoadXml(msiInstall.GetViewData(L"SELECT * FROM `LocalGroups`")); MSXML2::IXMLDOMNodeListPtr localgroups_rows = localgroups_xml_document.SelectNodes(L"//Row"); MSXML2::IXMLDOMNodePtr localgroups_row = NULL; while (NULL != (localgroups_row = localgroups_rows->nextNode())) { std::wstring localgroup_id = localgroups_xml_document.GetNodeValue(L"Data[@Column=\"Id\"]", localgroups_row); std::wstring localgroup_name = localgroups_xml_document.GetNodeValue(L"Data[@Column=\"Name\"]", localgroups_row); localgroups_map[localgroup_id] = localgroup_name; } // local users std::map<std::wstring, std::wstring> localusers_map; AppSecInc::Xml::XmlDocument localusers_xml_document; localusers_xml_document.LoadXml(msiInstall.GetViewData(L"SELECT * FROM `LocalUsers`")); MSXML2::IXMLDOMNodeListPtr localusers_rows = localusers_xml_document.SelectNodes(L"//Row"); MSXML2::IXMLDOMNodePtr localusers_row = NULL; while (NULL != (localusers_row = localusers_rows->nextNode())) { std::wstring localuser_id = localusers_xml_document.GetNodeValue(L"Data[@Column=\"Id\"]", localusers_row); std::wstring localuser_username = localusers_xml_document.GetNodeValue(L"Data[@Column=\"Username\"]", localusers_row); localusers_map[localuser_id] = localuser_username; } // combined xml document AppSecInc::Xml::XmlDocument combined_xml_document; combined_xml_document.Create(); MSXML2::IXMLDOMNodePtr combined_xml_root = combined_xml_document.AppendChild(L"LocalGroupMembers"); // local groups AppSecInc::Xml::XmlDocument localgroupmembers_xml_document; localgroupmembers_xml_document.LoadXml(msiInstall.GetViewData(L"SELECT * FROM `LocalGroupMembers`")); MSXML2::IXMLDOMNodeListPtr localgroupmembers_rows = localgroupmembers_xml_document.SelectNodes(L"//Row"); MSXML2::IXMLDOMNodePtr localgroupmembers_row = NULL; while (NULL != (localgroupmembers_row = localgroupmembers_rows->nextNode())) { std::wstring localgroupmembers_id = localgroupmembers_xml_document.GetNodeValue(L"Data[@Column=\"Id\"]", localgroupmembers_row); std::wstring localgroupmemberscomponent_id = localgroupmembers_xml_document.GetNodeValue(L"Data[@Column=\"ComponentId\"]", localgroupmembers_row, L""); std::wstring localuser_id = localgroupmembers_xml_document.GetNodeValue(L"Data[@Column=\"LocalUserId\"]", localgroupmembers_row); std::wstring username = localusers_map[localuser_id]; std::wstring localgroup_id = localgroupmembers_xml_document.GetNodeValue(L"Data[@Column=\"LocalGroupId\"]", localgroupmembers_row, L""); std::wstring groupname = localgroups_map[localgroup_id]; long attributes = AppSecInc::StringUtils::stringToLong(localgroupmembers_xml_document.GetNodeValue(L"Data[@Column=\"Attributes\"]", localgroupmembers_row)); // execute on install bool execute_per_component_install = (localgroupmemberscomponent_id.empty() || msiInstall.IsComponentInstalling(localgroupmemberscomponent_id)); // execute on uninstall bool execute_per_component_uninstall = (localgroupmemberscomponent_id.empty() || msiInstall.IsComponentUnInstalling(localgroupmemberscomponent_id)); bool add_member = ( (execute_per_component_install && (attributes & AddOnInstall) && msiInstall.IsInstalling()) || (execute_per_component_uninstall && (attributes & AddOnUnInstall) && msiInstall.IsUnInstalling()) ); bool remove_member = ( (execute_per_component_install && (attributes & RemoveOnInstall) && msiInstall.IsInstalling()) || (execute_per_component_uninstall && (attributes & RemoveOnUnInstall) && msiInstall.IsUnInstalling()) ); // write the odbc query to xml MSXML2::IXMLDOMNodePtr combined_xml_localgroupmembers_root = combined_xml_document.AppendChild(L"LocalGroupMember", combined_xml_root); combined_xml_document.SetAttribute(L"add", add_member ? L"true" : L"false", combined_xml_localgroupmembers_root); combined_xml_document.SetAttribute(L"remove", remove_member ? L"true" : L"false", combined_xml_localgroupmembers_root); combined_xml_document.SetAttribute(L"check", (attributes & CheckIfMember) ? L"true" : L"false", combined_xml_localgroupmembers_root); combined_xml_document.SetAttribute(L"id", localgroupmembers_id, combined_xml_localgroupmembers_root); combined_xml_document.AppendChild(L"Username", combined_xml_localgroupmembers_root)->text = _bstr_t(username.c_str()); combined_xml_document.AppendChild(L"Group", combined_xml_localgroupmembers_root)->text = _bstr_t(groupname.c_str()); } msiInstall.SetActionData(L"AddLocalGroupMembers_Deferred", combined_xml_document.GetXml()); msiInstall.SetActionData(L"RemoveLocalGroupMembers_Deferred", combined_xml_document.GetXml()); MSI_EXCEPTION_HANDLER_EPILOG; return ERROR_SUCCESS; }
CA_API UINT __stdcall LocalGroupMembers_Deferred(MSIHANDLE hInstall) { MSI_EXCEPTION_HANDLER_PROLOG; MsiInstall msiInstall(hInstall); AppSecInc::Xml::XmlDocument xmlDocument; xmlDocument.LoadXml(msiInstall.GetActionData()); MSXML2::IXMLDOMNodeListPtr rows = xmlDocument.SelectNodes(L"/LocalGroupMembers/LocalGroupMember"); MSXML2::IXMLDOMNodePtr row = NULL; while (NULL != (row = rows->nextNode())) { std::wstring id = xmlDocument.GetAttributeValue(L"id", row); std::wstring username = xmlDocument.GetNodeValue(L"Username", row); std::wstring groupname = xmlDocument.GetNodeValue(L"Group", row, L""); bool add_member = xmlDocument.GetAttributeBoolValue(L"add", row); bool remove_member = xmlDocument.GetAttributeBoolValue(L"remove", row); bool check = xmlDocument.GetAttributeBoolValue(L"check", row); if (remove_member && (! check || AppSecInc::LSA::LocalGroup::IsMember(groupname, username))) { msiInstall.LogInfo(_T(__FUNCTION__), L"Removing \"" + username + L"\" from \"" + groupname + L"\""); AppSecInc::LSA::LocalGroup::DeleteMember(groupname, username); } if (add_member && (! check || ! AppSecInc::LSA::LocalGroup::IsMember(groupname, username))) { msiInstall.LogInfo(_T(__FUNCTION__), L"Adding \"" + username + L"\" to \"" + groupname + L"\""); AppSecInc::LSA::LocalGroup::AddMember(groupname, username); } } MSI_EXCEPTION_HANDLER_EPILOG; return ERROR_SUCCESS; }