/* Copyright 2015-2016 Amebis Copyright 2016 GÉANT This file is part of GÉANTLink. GÉANTLink is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. GÉANTLink is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with GÉANTLink. If not, see . */ #include #include #include #include #include #include namespace eapxml { /// /// \defgroup EAPBaseXML XML DOM /// Easy interaction with MSXML /// /// @{ /// /// Returns owner document object for a given node /// /// \param[in ] pXmlNode XML node /// \param[out] ppXmlDoc XML document /// /// \returns /// - >0 if succeeded with warnings; /// - =0 (\c S_OK) if successful; /// - <0 if failed. /// Use `SUCCEEDED()` macro to test for first two cases (>=0) or `FAILED()` to test for failure. /// inline HRESULT get_document(_In_ IXMLDOMNode *pXmlNode, _Out_ winstd::com_obj &ppXmlDoc); /// /// Selects single child node by name /// /// \param[in ] pXmlParent Parent XML node /// \param[in ] bstrNodeName XML node selection name /// \param[out] ppXmlNode Child XML node found /// /// \returns /// - >0 if succeeded with warnings; /// - =0 (\c S_OK) if successful; /// - <0 if failed. /// Use `SUCCEEDED()` macro to test for first two cases (>=0) or `FAILED()` to test for failure. /// inline HRESULT select_node(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrNodeName, _Out_ winstd::com_obj &ppXmlNode); /// /// Selects child nodes by name /// /// \param[in ] pXmlParent Parent XML node /// \param[in ] bstrNodeName XML node selection name /// \param[out] ppXmlNodes List of child XML nodes found /// /// \returns /// - >0 if succeeded with warnings; /// - =0 (\c S_OK) if successful; /// - <0 if failed. /// Use `SUCCEEDED()` macro to test for first two cases (>=0) or `FAILED()` to test for failure. /// inline HRESULT select_nodes(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrNodeName, _Out_ winstd::com_obj &ppXmlNodes); /// /// Selects single child element by name /// /// \param[in ] pXmlParent Parent XML node /// \param[in ] bstrElementName XML element selection name /// \param[out] ppXmlElement Child XML element found /// /// \returns /// - >0 if succeeded with warnings; /// - =0 (\c S_OK) if successful; /// - <0 if failed. /// Use `SUCCEEDED()` macro to test for first two cases (>=0) or `FAILED()` to test for failure. /// inline HRESULT select_element(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementName, _Out_ winstd::com_obj &ppXmlElement); /// /// Creates a new element /// /// \param[in ] pDoc Owner XML document /// \param[in ] bstrElementName XML element name /// \param[in ] bstrNamespace XML element namespace /// \param[out] ppXmlElement XML element created /// /// \returns /// - >0 if succeeded with warnings; /// - =0 (\c S_OK) if successful; /// - <0 if failed. /// Use `SUCCEEDED()` macro to test for first two cases (>=0) or `FAILED()` to test for failure. /// inline HRESULT create_element(_In_ IXMLDOMDocument *pDoc, _In_z_ const BSTR bstrElementName, _In_z_ const BSTR bstrNamespace, _Out_ winstd::com_obj &ppXmlElement); /// /// Creates a new child element if not already present /// /// \param[in ] pDoc Owner XML document /// \param[in ] pXmlParent Parent XML node /// \param[in ] bstrElementNameSelect XML element selection name /// \param[in ] bstrElementNameCreate XML element name /// \param[in ] bstrNamespace XML element namespace /// \param[out] ppXmlElement XML element found or created /// /// \returns /// - >0 if succeeded with warnings; /// - =0 (\c S_OK) if successful; /// - <0 if failed. /// Use `SUCCEEDED()` macro to test for first two cases (>=0) or `FAILED()` to test for failure. /// inline HRESULT create_element(_In_ IXMLDOMDocument *pDoc, IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementNameSelect, _In_z_ const BSTR bstrElementNameCreate, _In_z_ const BSTR bstrNamespace, _Out_ winstd::com_obj &ppXmlElement); /// /// Tests if node has a parent set /// /// \param[in] pXmlNode XML node /// /// \returns /// - Non zero when \p pXmlNode has a parent set; /// - Zero otherwise. /// inline bool has_parent(_In_ IXMLDOMNode *pXmlNode); /// /// Returns child element text /// /// \param[in ] pXmlParent Parent XML node /// \param[in ] bstrElementName XML element selection name /// \param[out] pbstrValue XML element text /// \param[out] ppXmlElement Child XML element found /// /// \returns /// - >0 if succeeded with warnings; /// - =0 (\c S_OK) if successful; /// - <0 if failed. /// Use `SUCCEEDED()` macro to test for first two cases (>=0) or `FAILED()` to test for failure. /// inline HRESULT get_element_value(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementName, _Out_ winstd::bstr &pbstrValue, _Out_opt_ winstd::com_obj *ppXmlElement = NULL); /// /// Returns child element text /// /// \param[in ] pXmlParent Parent XML node /// \param[in ] bstrElementName XML element selection name /// \param[out] sValue XML element text /// \param[out] ppXmlElement Child XML element found /// /// \returns /// - >0 if succeeded with warnings; /// - =0 (\c S_OK) if successful; /// - <0 if failed. /// Use `SUCCEEDED()` macro to test for first two cases (>=0) or `FAILED()` to test for failure. /// template inline HRESULT get_element_value(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementName, _Out_ std::basic_string &sValue, _Out_opt_ winstd::com_obj *ppXmlElement = NULL); /// /// Returns child element text converted to number /// /// \param[in ] pXmlParent Parent XML node /// \param[in ] bstrElementName XML element selection name /// \param[out] pdwValue XML element text converted to number /// \param[out] ppXmlElement Child XML element found /// /// \returns /// - >0 if succeeded with warnings; /// - =0 (\c S_OK) if successful; /// - <0 if failed. /// Use `SUCCEEDED()` macro to test for first two cases (>=0) or `FAILED()` to test for failure. /// inline HRESULT get_element_value(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementName, _Out_ DWORD &pdwValue, _Out_opt_ winstd::com_obj *ppXmlElement = NULL); /// /// Returns child element text converted to boolean /// /// \param[in ] pXmlParent Parent XML node /// \param[in ] bstrElementName XML element selection name /// \param[out] pbValue XML element text converted to boolean /// \param[out] ppXmlElement Child XML element found /// /// \returns /// - >0 if succeeded with warnings; /// - =0 (\c S_OK) if successful; /// - <0 if failed. /// Use `SUCCEEDED()` macro to test for first two cases (>=0) or `FAILED()` to test for failure. /// inline HRESULT get_element_value(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementName, _Out_ bool &pbValue, _Out_opt_ winstd::com_obj *ppXmlElement = NULL); /// /// Returns child element BLOB encoded as Base64 text /// /// \param[in ] pXmlParent Parent XML node /// \param[in ] bstrElementName XML element selection name /// \param[out] aValue XML element BLOB /// \param[out] ppXmlElement Child XML element found /// /// \returns /// - >0 if succeeded with warnings; /// - =0 (\c S_OK) if successful; /// - <0 if failed. /// Use `SUCCEEDED()` macro to test for first two cases (>=0) or `FAILED()` to test for failure. /// template inline HRESULT get_element_base64(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementName, _Out_ std::vector<_Ty, _Ax> &aValue, _Out_opt_ winstd::com_obj *ppXmlElement = NULL); /// /// Returns child element BLOB encoded as hexadecimal text /// /// \param[in ] pXmlParent Parent XML node /// \param[in ] bstrElementName XML element selection name /// \param[out] aValue XML element BLOB /// \param[out] ppXmlElement Child XML element found /// /// \returns /// - >0 if succeeded with warnings; /// - =0 (\c S_OK) if successful; /// - <0 if failed. /// Use `SUCCEEDED()` macro to test for first two cases (>=0) or `FAILED()` to test for failure. /// template inline HRESULT get_element_hex(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementName, _Out_ std::vector<_Ty, _Ax> &aValue, _Out_opt_ winstd::com_obj *ppXmlElement = NULL); /// /// Returns child element localizable text /// /// \param[in ] pXmlParent Parent XML node /// \param[in ] bstrElementName XML element selection name /// \param[in ] pszLang Desired localization /// \param[out] pbstrValue XML element text /// \param[out] ppXmlElement Child XML element found /// /// \returns /// - >0 if succeeded with warnings; /// - =0 (\c S_OK) if successful; /// - <0 if failed. /// Use `SUCCEEDED()` macro to test for first two cases (>=0) or `FAILED()` to test for failure. /// inline HRESULT get_element_localized(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementName, _In_z_ LPCWSTR pszLang, _Out_ winstd::bstr &pbstrValue, _Out_opt_ winstd::com_obj *ppXmlElement = NULL); /// /// Returns child element localizable text /// /// \param[in ] pXmlParent Parent XML node /// \param[in ] bstrElementName XML element selection name /// \param[in ] pszLang Desired localization /// \param[out] sValue XML element text /// \param[out] ppXmlElement Child XML element found /// /// \returns /// - >0 if succeeded with warnings; /// - =0 (\c S_OK) if successful; /// - <0 if failed. /// Use `SUCCEEDED()` macro to test for first two cases (>=0) or `FAILED()` to test for failure. /// template inline HRESULT get_element_localized(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementName, _In_z_ LPCWSTR pszLang, _Out_ std::basic_string &sValue, _Out_opt_ winstd::com_obj *ppXmlElement = NULL); /// /// Creates a new child element /// /// \param[in ] pDoc Owner XML document /// \param[in ] pCurrentDOMNode Parent XML node /// \param[in ] bstrElementName XML element name /// \param[in ] bstrNamespace XML element namespace /// \param[out] ppXmlElement XML element created /// /// \returns /// - >0 if succeeded with warnings; /// - =0 (\c S_OK) if successful; /// - <0 if failed. /// Use `SUCCEEDED()` macro to test for first two cases (>=0) or `FAILED()` to test for failure. /// inline HRESULT put_element(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pCurrentDOMNode, _In_z_ const BSTR bstrElementName, _In_opt_z_ const BSTR bstrNamespace, _Out_ winstd::com_obj &ppXmlElement); /// /// Creates a new child element with text /// /// \param[in ] pDoc Owner XML document /// \param[in ] pCurrentDOMNode Parent XML node /// \param[in ] bstrElementName XML element name /// \param[in ] bstrNamespace XML element namespace /// \param[in ] bstrValue XML element text /// \param[out] ppXmlElement XML element created /// /// \returns /// - >0 if succeeded with warnings; /// - =0 (\c S_OK) if successful; /// - <0 if failed. /// Use `SUCCEEDED()` macro to test for first two cases (>=0) or `FAILED()` to test for failure. /// inline HRESULT put_element_value(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pCurrentDOMNode, _In_z_ const BSTR bstrElementName, _In_opt_z_ const BSTR bstrNamespace, _In_z_ const BSTR bstrValue, _Out_opt_ winstd::com_obj *ppXmlElement = NULL); /// /// Creates a new child element with text converted from number /// /// \param[in ] pDoc Owner XML document /// \param[in ] pCurrentDOMNode Parent XML node /// \param[in ] bstrElementName XML element name /// \param[in ] bstrNamespace XML element namespace /// \param[in ] dwValue XML element number /// \param[out] ppXmlElement XML element created /// /// \returns /// - >0 if succeeded with warnings; /// - =0 (\c S_OK) if successful; /// - <0 if failed. /// Use `SUCCEEDED()` macro to test for first two cases (>=0) or `FAILED()` to test for failure. /// inline HRESULT put_element_value(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pCurrentDOMNode, _In_z_ const BSTR bstrElementName, _In_opt_z_ const BSTR bstrNamespace, _In_ DWORD dwValue, _Out_opt_ winstd::com_obj *ppXmlElement = NULL); /// /// Creates a new child element with text converted from boolean /// /// \param[in ] pDoc Owner XML document /// \param[in ] pCurrentDOMNode Parent XML node /// \param[in ] bstrElementName XML element name /// \param[in ] bstrNamespace XML element namespace /// \param[in ] bValue XML element boolean /// \param[out] ppXmlElement XML element created /// /// \returns /// - >0 if succeeded with warnings; /// - =0 (\c S_OK) if successful; /// - <0 if failed. /// Use `SUCCEEDED()` macro to test for first two cases (>=0) or `FAILED()` to test for failure. /// inline HRESULT put_element_value(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pCurrentDOMNode, _In_z_ const BSTR bstrElementName, _In_opt_z_ const BSTR bstrNamespace, _In_ bool bValue, _Out_opt_ winstd::com_obj *ppXmlElement = NULL); /// /// Creates a new child element with Base64 encoded text from BLOB /// /// \param[in ] pDoc Owner XML document /// \param[in ] pCurrentDOMNode Parent XML node /// \param[in ] bstrElementName XML element name /// \param[in ] bstrNamespace XML element namespace /// \param[in ] pValue Pointer to BLOB data /// \param[in ] nValueLen Size of \p pValue in bytes /// \param[out] ppXmlElement XML element created /// /// \returns /// - >0 if succeeded with warnings; /// - =0 (\c S_OK) if successful; /// - <0 if failed. /// Use `SUCCEEDED()` macro to test for first two cases (>=0) or `FAILED()` to test for failure. /// inline HRESULT put_element_base64(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pCurrentDOMNode, _In_z_ const BSTR bstrElementName, _In_opt_z_ const BSTR bstrNamespace, _In_bytecount_(nValueLen) LPCVOID pValue, _In_ SIZE_T nValueLen, _Out_opt_ winstd::com_obj *ppXmlElement = NULL); /// /// Creates a new child element with hexadecimal encoded text from BLOB /// /// \param[in ] pDoc Owner XML document /// \param[in ] pCurrentDOMNode Parent XML node /// \param[in ] bstrElementName XML element name /// \param[in ] bstrNamespace XML element namespace /// \param[in ] pValue Pointer to BLOB data /// \param[in ] nValueLen Size of \p pValue in bytes /// \param[out] ppXmlElement XML element created /// /// \returns /// - >0 if succeeded with warnings; /// - =0 (\c S_OK) if successful; /// - <0 if failed. /// Use `SUCCEEDED()` macro to test for first two cases (>=0) or `FAILED()` to test for failure. /// inline HRESULT put_element_hex(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pCurrentDOMNode, _In_z_ const BSTR bstrElementName, _In_opt_z_ const BSTR bstrNamespace, _In_bytecount_(nValueLen) LPCVOID pValue, _In_ SIZE_T nValueLen, _Out_opt_ winstd::com_obj *ppXmlElement = NULL); /// /// Returns attribute text /// /// \param[in ] pXmlParent Parent XML node /// \param[in ] bstrAttributeName XML attribute selection name /// \param[out] pbstrValue XML atribute value /// /// \returns /// - >0 if succeeded with warnings; /// - =0 (\c S_OK) if successful; /// - <0 if failed. /// Use `SUCCEEDED()` macro to test for first two cases (>=0) or `FAILED()` to test for failure. /// inline HRESULT get_attrib_value(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrAttributeName, _Out_ winstd::bstr &pbstrValue); /// /// Returns attribute text /// /// \param[in ] pXmlParent Parent XML node /// \param[in ] bstrAttributeName XML attribute selection name /// \param[out] sValue XML atribute value /// /// \returns /// - >0 if succeeded with warnings; /// - =0 (\c S_OK) if successful; /// - <0 if failed. /// Use `SUCCEEDED()` macro to test for first two cases (>=0) or `FAILED()` to test for failure. /// template inline HRESULT get_attrib_value(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrAttributeName, _Out_ std::basic_string &sValue); /// /// Returns attribute text converted to number /// /// \param[in ] pXmlParent Parent XML node /// \param[in ] bstrAttributeName XML attribute selection name /// \param[out] pdwValue XML atribute value /// /// \returns /// - >0 if succeeded with warnings; /// - =0 (\c S_OK) if successful; /// - <0 if failed. /// Use `SUCCEEDED()` macro to test for first two cases (>=0) or `FAILED()` to test for failure. /// inline HRESULT get_attrib_value(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrAttributeName, _Out_ DWORD &pdwValue); /// /// Returns attribute text converted to boolean /// /// \param[in ] pXmlParent Parent XML node /// \param[in ] bstrAttributeName XML attribute selection name /// \param[out] pbValue XML atribute value /// /// \returns /// - >0 if succeeded with warnings; /// - =0 (\c S_OK) if successful; /// - <0 if failed. /// Use `SUCCEEDED()` macro to test for first two cases (>=0) or `FAILED()` to test for failure. /// inline HRESULT get_attrib_value(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrAttributeName, _Out_ bool &pbValue); /// /// Returns attribute BLOB converted from Base64 encoded text /// /// \param[in ] pXmlParent Parent XML node /// \param[in ] bstrAttributeName XML attribute selection name /// \param[out] aValue XML atribute value /// /// \returns /// - >0 if succeeded with warnings; /// - =0 (\c S_OK) if successful; /// - <0 if failed. /// Use `SUCCEEDED()` macro to test for first two cases (>=0) or `FAILED()` to test for failure. /// template inline HRESULT get_attrib_base64(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrAttributeName, _Out_ std::vector<_Ty, _Ax> &aValue); /// /// Returns attribute BLOB converted from hexadecimal encoded text /// /// \param[in ] pXmlParent Parent XML node /// \param[in ] bstrAttributeName XML attribute selection name /// \param[out] aValue XML atribute value /// /// \returns /// - >0 if succeeded with warnings; /// - =0 (\c S_OK) if successful; /// - <0 if failed. /// Use `SUCCEEDED()` macro to test for first two cases (>=0) or `FAILED()` to test for failure. /// template inline HRESULT get_attrib_hex(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrAttributeName, _Out_ std::vector<_Ty, _Ax> &aValue); /// /// Sets node attribute /// /// \param[in ] pCurrentDOMNode Parent XML node /// \param[in ] bstrAttributeName XML attribute name /// \param[out] bstrValue XML atribute value /// /// \returns /// - >0 if succeeded with warnings; /// - =0 (\c S_OK) if successful; /// - <0 if failed. /// Use `SUCCEEDED()` macro to test for first two cases (>=0) or `FAILED()` to test for failure. /// inline HRESULT put_attrib_value(_In_ IXMLDOMNode *pCurrentDOMNode, _In_z_ const BSTR bstrAttributeName, _In_z_ const BSTR bstrValue); /// /// Sets node attribute converted from number /// /// \param[in ] pCurrentDOMNode Parent XML node /// \param[in ] bstrAttributeName XML attribute name /// \param[out] dwValue XML atribute value /// /// \returns /// - >0 if succeeded with warnings; /// - =0 (\c S_OK) if successful; /// - <0 if failed. /// Use `SUCCEEDED()` macro to test for first two cases (>=0) or `FAILED()` to test for failure. /// inline HRESULT put_attrib_value(_In_ IXMLDOMNode *pCurrentDOMNode, _In_z_ const BSTR bstrAttributeName, _In_ DWORD dwValue); /// /// Sets node attribute converted from boolean /// /// \param[in ] pCurrentDOMNode Parent XML node /// \param[in ] bstrAttributeName XML attribute name /// \param[out] bValue XML atribute value /// /// \returns /// - >0 if succeeded with warnings; /// - =0 (\c S_OK) if successful; /// - <0 if failed. /// Use `SUCCEEDED()` macro to test for first two cases (>=0) or `FAILED()` to test for failure. /// inline HRESULT put_attrib_value(_In_ IXMLDOMNode *pCurrentDOMNode, _In_z_ const BSTR bstrAttributeName, _In_ bool bValue); /// /// Sets node attribute to Base64 encoded text from BLOB /// /// \param[in ] pCurrentDOMNode Parent XML node /// \param[in ] bstrAttributeName XML attribute name /// \param[in ] pValue Pointer to BLOB data /// \param[in ] nValueLen Size of \p pValue in bytes /// /// \returns /// - >0 if succeeded with warnings; /// - =0 (\c S_OK) if successful; /// - <0 if failed. /// Use `SUCCEEDED()` macro to test for first two cases (>=0) or `FAILED()` to test for failure. /// inline HRESULT put_attrib_base64(_In_ IXMLDOMNode *pCurrentDOMNode, _In_z_ const BSTR bstrAttributeName, _In_bytecount_(nValueLen) LPCVOID pValue, _In_ SIZE_T nValueLen); /// /// Sets node attribute to hexadecimal encoded text from BLOB /// /// \param[in ] pCurrentDOMNode Parent XML node /// \param[in ] bstrAttributeName XML attribute name /// \param[in ] pValue Pointer to BLOB data /// \param[in ] nValueLen Size of \p pValue in bytes /// /// \returns /// - >0 if succeeded with warnings; /// - =0 (\c S_OK) if successful; /// - <0 if failed. /// Use `SUCCEEDED()` macro to test for first two cases (>=0) or `FAILED()` to test for failure. /// inline HRESULT put_attrib_hex(_In_ IXMLDOMNode *pCurrentDOMNode, _In_z_ const BSTR bstrAttributeName, _In_bytecount_(nValueLen) LPCVOID pValue, _In_ SIZE_T nValueLen); /// /// Builds XPath for a given node /// /// \param[in] pXmlNode XML node /// /// \returns String with XPath for a given node up to node terminal parent /// inline std::wstring get_xpath(_In_ IXMLDOMNode *pXmlNode); /// @} } #pragma once #include #include #include namespace eapxml { inline HRESULT get_document(_In_ IXMLDOMNode *pXmlNode, _Out_ winstd::com_obj &ppXmlDoc) { assert(pXmlNode); HRESULT hr; winstd::com_obj doc; return SUCCEEDED(hr = pXmlNode->get_ownerDocument(&doc)) && SUCCEEDED(hr = doc.query_interface(ppXmlDoc)) ? S_OK : hr; } inline HRESULT select_node(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrNodeName, _Out_ winstd::com_obj &ppXmlNode) { assert(pXmlParent); HRESULT hr; IXMLDOMNode *pXmlNode; if (SUCCEEDED(hr = pXmlParent->selectSingleNode(bstrNodeName, &pXmlNode))) { ppXmlNode.attach(pXmlNode); return pXmlNode ? S_OK : E_NOT_SET; } else return hr; } inline HRESULT select_nodes(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrNodeName, _Out_ winstd::com_obj &ppXmlNodes) { assert(pXmlParent); HRESULT hr; IXMLDOMNodeList *pXmlNodes; if (SUCCEEDED(hr = pXmlParent->selectNodes(bstrNodeName, &pXmlNodes))) { ppXmlNodes.attach(pXmlNodes); return pXmlNodes ? S_OK : E_NOT_SET; } else return hr; } inline HRESULT select_element(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementName, _Out_ winstd::com_obj &ppXmlElement) { HRESULT hr; winstd::com_obj pXmlNode; return SUCCEEDED(hr = select_node(pXmlParent, bstrElementName, pXmlNode)) ? SUCCEEDED(hr = pXmlNode.query_interface(ppXmlElement)) ? ppXmlElement ? S_OK : E_NOT_SET : hr : hr; } inline HRESULT create_element(_In_ IXMLDOMDocument *pDoc, _In_z_ const BSTR bstrElementName, _In_z_ const BSTR bstrNamespace, _Out_ winstd::com_obj &ppXmlElement) { assert(pDoc); static const winstd::variant varNodeTypeEl(NODE_ELEMENT); HRESULT hr; winstd::com_obj pXmlNode; return SUCCEEDED(hr = pDoc->createNode(varNodeTypeEl, bstrElementName, bstrNamespace, &pXmlNode)) ? SUCCEEDED(hr = pXmlNode.query_interface(ppXmlElement)) ? ppXmlElement ? S_OK : E_NOT_SET : hr : hr; } inline HRESULT create_element(_In_ IXMLDOMDocument *pDoc, IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementNameSelect, _In_z_ const BSTR bstrElementNameCreate, _In_z_ const BSTR bstrNamespace, _Out_ winstd::com_obj &ppXmlElement) { assert(pDoc); assert(pXmlParent); HRESULT hr; return SUCCEEDED(hr = select_element(pXmlParent, bstrElementNameSelect, ppXmlElement)) ? S_OK : SUCCEEDED(hr = create_element(pDoc, bstrElementNameCreate, bstrNamespace, ppXmlElement)) ? SUCCEEDED(hr = pXmlParent->appendChild(ppXmlElement, NULL)) ? S_OK : hr : hr; } inline bool has_parent(_In_ IXMLDOMNode *pXmlNode) { assert(pXmlNode); winstd::com_obj pXmlNodeParent; return SUCCEEDED(pXmlNode->get_parentNode(&pXmlNodeParent)) && pXmlNodeParent; } inline HRESULT get_element_value(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementName, _Out_ winstd::bstr &pbstrValue, _Out_opt_ winstd::com_obj *ppXmlElement) { HRESULT hr; winstd::com_obj pXmlElement; BSTR bstrValue; if (SUCCEEDED(hr = select_element(pXmlParent, bstrElementName, pXmlElement)) && SUCCEEDED(hr = pXmlElement->get_text(&bstrValue))) { pbstrValue.attach(bstrValue); if (ppXmlElement) *ppXmlElement = std::move(pXmlElement); return bstrValue ? S_OK : E_NOT_SET; } else return hr; } template inline HRESULT get_element_value(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementName, _Out_ std::basic_string &sValue, _Out_opt_ winstd::com_obj *ppXmlElement) { winstd::bstr bstr; HRESULT hr = get_element_value(pXmlParent, bstrElementName, bstr, ppXmlElement); if (SUCCEEDED(hr)) sValue.assign(bstr, bstr.length()); return hr; } inline HRESULT get_element_value(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementName, _Out_ DWORD &pdwValue, _Out_opt_ winstd::com_obj *ppXmlElement) { winstd::bstr bstr; HRESULT hr = get_element_value(pXmlParent, bstrElementName, bstr, ppXmlElement); if (SUCCEEDED(hr)) pdwValue = wcstoul(bstr, NULL, 10); return hr; } inline HRESULT get_element_value(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementName, _Out_ bool &pbValue, _Out_opt_ winstd::com_obj *ppXmlElement) { winstd::bstr bstr; HRESULT hr = get_element_value(pXmlParent, bstrElementName, bstr, ppXmlElement); if (SUCCEEDED(hr)) { if (CompareStringEx(LOCALE_NAME_INVARIANT, NORM_IGNORECASE, bstr, bstr.length(), L"true" , -1, NULL, NULL, 0) == CSTR_EQUAL || CompareStringEx(LOCALE_NAME_INVARIANT, NORM_IGNORECASE, bstr, bstr.length(), L"1" , -1, NULL, NULL, 0) == CSTR_EQUAL) pbValue = true; else if ( CompareStringEx(LOCALE_NAME_INVARIANT, NORM_IGNORECASE, bstr, bstr.length(), L"false", -1, NULL, NULL, 0) == CSTR_EQUAL || CompareStringEx(LOCALE_NAME_INVARIANT, NORM_IGNORECASE, bstr, bstr.length(), L"0" , -1, NULL, NULL, 0) == CSTR_EQUAL) pbValue = false; else hr = E_NOT_VALID_STATE; } return hr; } template inline HRESULT get_element_base64(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementName, _Out_ std::vector<_Ty, _Ax> &aValue, _Out_opt_ winstd::com_obj *ppXmlElement) { winstd::bstr bstr; HRESULT hr = get_element_value(pXmlParent, bstrElementName, bstr, ppXmlElement); if (SUCCEEDED(hr)) { winstd::base64_dec dec; bool is_last; dec.decode(aValue, is_last, (BSTR)bstr, bstr.length()); } return hr; } template inline HRESULT get_element_hex(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementName, _Out_ std::vector<_Ty, _Ax> &aValue, _Out_opt_ winstd::com_obj *ppXmlElement) { winstd::bstr bstr; HRESULT hr = get_element_value(pXmlParent, bstrElementName, bstr, ppXmlElement); if (SUCCEEDED(hr)) { winstd::hex_dec dec; bool is_last; dec.decode(aValue, is_last, (BSTR)bstr, bstr.length()); } return hr; } inline HRESULT get_element_localized(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementName, _In_z_ LPCWSTR pszLang, _Out_ winstd::bstr &pbstrValue, _Out_opt_ winstd::com_obj *ppXmlElement) { HRESULT hr; winstd::com_obj pXmlElement; if (FAILED(hr = select_element(pXmlParent, bstrElementName, pXmlElement))) return hr; if (ppXmlElement) *ppXmlElement = pXmlElement; winstd::com_obj pXmlListLocalizedText; long lCount = 0; if (FAILED(select_nodes(pXmlElement, winstd::bstr(L"eap-metadata:localized-text"), pXmlListLocalizedText)) || FAILED(pXmlListLocalizedText->get_length(&lCount)) || lCount <= 0) { BSTR bstr; if (SUCCEEDED(hr = pXmlElement->get_text(&bstr))) { pbstrValue.attach(bstr); return bstr ? S_OK : E_NOT_SET; } else return hr; } winstd::bstr bstrDefault, bstrEn; for (long i = 0; ; i++) { if (i >= lCount) { if (bstrDefault != NULL) { // Return "C" localization. pbstrValue = std::move(bstrDefault); return S_OK; } else if (bstrEn != NULL) { // Return "en" localization. pbstrValue = std::move(bstrEn); return S_OK; } else return HRESULT_FROM_WIN32(ERROR_NOT_FOUND); } winstd::com_obj pXmlElLocalizedText; pXmlListLocalizedText->get_item(i, &pXmlElLocalizedText); { // Read . winstd::bstr bstrLang; if (FAILED(get_element_value(pXmlElLocalizedText, winstd::bstr(L"eap-metadata:lang"), bstrLang)) || CompareStringEx(LOCALE_NAME_INVARIANT, NORM_IGNORECASE, bstrLang, bstrLang.length(), L"C" , -1, NULL, NULL, 0) == CSTR_EQUAL) { // is missing or "C" language found. winstd::bstr bstr; if (SUCCEEDED(hr = get_element_value(pXmlElLocalizedText, winstd::bstr(L"eap-metadata:text"), bstr))) bstrDefault = std::move(bstr); } else if (CompareStringEx(LOCALE_NAME_INVARIANT, NORM_IGNORECASE, bstrLang, bstrLang.length(), pszLang, -1, NULL, NULL, 0) == CSTR_EQUAL) { // Found an exact match. return get_element_value(pXmlElLocalizedText, winstd::bstr(L"eap-metadata:text"), pbstrValue); } else if (CompareStringEx(LOCALE_NAME_INVARIANT, NORM_IGNORECASE, bstrLang, bstrLang.length(), L"en", -1, NULL, NULL, 0) == CSTR_EQUAL) { // "en" language found. winstd::bstr bstr; if (SUCCEEDED(hr = get_element_value(pXmlElLocalizedText, winstd::bstr(L"eap-metadata:text"), bstr))) bstrEn = std::move(bstr); } } } } template inline HRESULT get_element_localized(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrElementName, _In_z_ LPCWSTR pszLang, _Out_ std::basic_string &sValue, _Out_opt_ winstd::com_obj *ppXmlElement) { winstd::bstr bstr; HRESULT hr = get_element_localized(pXmlParent, bstrElementName, pszLang, bstr, ppXmlElement); if (SUCCEEDED(hr)) sValue.assign(bstr, bstr.length()); return hr; } inline HRESULT put_element(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pCurrentDOMNode, _In_z_ const BSTR bstrElementName, _In_opt_z_ const BSTR bstrNamespace, _Out_ winstd::com_obj &ppXmlElement) { assert(pDoc); assert(pCurrentDOMNode); static const VARIANT varNodeTypeEl = { VT_I4, 0, 0, 0, { NODE_ELEMENT } }; HRESULT hr; winstd::com_obj pXmlEl; return SUCCEEDED(hr = pDoc->createNode(varNodeTypeEl, bstrElementName, bstrNamespace, &pXmlEl)) && SUCCEEDED(hr = pCurrentDOMNode->appendChild(pXmlEl, NULL)) && SUCCEEDED(hr = pXmlEl.query_interface(ppXmlElement)) ? S_OK : hr; } inline HRESULT put_element_value(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pCurrentDOMNode, _In_z_ const BSTR bstrElementName, _In_opt_z_ const BSTR bstrNamespace, _In_z_ const BSTR bstrValue, _Out_opt_ winstd::com_obj *ppXmlElement) { assert(pDoc); static const VARIANT varNodeTypeEl = { VT_I4, 0, 0, 0, { NODE_ELEMENT } }; HRESULT hr; winstd::com_obj pXmlEl; winstd::com_obj pXmlElText; if (SUCCEEDED(hr = pDoc->createNode(varNodeTypeEl, bstrElementName, bstrNamespace, &pXmlEl)) && SUCCEEDED(hr = pDoc->createTextNode(bstrValue, &pXmlElText)) && SUCCEEDED(hr = pXmlEl->appendChild(pXmlElText, NULL)) && SUCCEEDED(hr = pCurrentDOMNode->appendChild(pXmlEl, NULL))) { if (ppXmlElement) pXmlEl.query_interface(*ppXmlElement); return S_OK; } else return hr; } inline HRESULT put_element_value(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pCurrentDOMNode, _In_z_ const BSTR bstrElementName, _In_opt_z_ const BSTR bstrNamespace, _In_ DWORD dwValue, _Out_opt_ winstd::com_obj *ppXmlElement) { return put_element_value(pDoc, pCurrentDOMNode, bstrElementName, bstrNamespace, winstd::bstr(winstd::wstring_printf(L"%d", dwValue)), ppXmlElement); } inline HRESULT put_element_value(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pCurrentDOMNode, _In_z_ const BSTR bstrElementName, _In_opt_z_ const BSTR bstrNamespace, _In_ bool bValue, _Out_opt_ winstd::com_obj *ppXmlElement) { return put_element_value(pDoc, pCurrentDOMNode, bstrElementName, bstrNamespace, winstd::bstr(bValue ? L"true": L"false"), ppXmlElement); } inline HRESULT put_element_base64(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pCurrentDOMNode, _In_z_ const BSTR bstrElementName, _In_opt_z_ const BSTR bstrNamespace, _In_bytecount_(nValueLen) LPCVOID pValue, _In_ SIZE_T nValueLen, _Out_opt_ winstd::com_obj *ppXmlElement) { std::wstring sBase64; winstd::base64_enc enc; enc.encode(sBase64, pValue, nValueLen); return put_element_value(pDoc, pCurrentDOMNode, bstrElementName, bstrNamespace, winstd::bstr(sBase64), ppXmlElement); } inline HRESULT put_element_hex(_In_ IXMLDOMDocument *pDoc, _In_ IXMLDOMNode *pCurrentDOMNode, _In_z_ const BSTR bstrElementName, _In_opt_z_ const BSTR bstrNamespace, _In_bytecount_(nValueLen) LPCVOID pValue, _In_ SIZE_T nValueLen, _Out_opt_ winstd::com_obj *ppXmlElement) { std::wstring sHex; winstd::hex_enc enc; enc.encode(sHex, pValue, nValueLen); return put_element_value(pDoc, pCurrentDOMNode, bstrElementName, bstrNamespace, winstd::bstr(sHex), ppXmlElement); } inline HRESULT get_attrib_value(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrAttributeName, _Out_ winstd::bstr &pbstrValue) { HRESULT hr; winstd::com_obj pXmlAttributes; winstd::com_obj pXmlAt; VARIANT varValue; V_VT(&varValue) = VT_EMPTY; return SUCCEEDED(hr = pXmlParent->get_attributes(&pXmlAttributes)) && SUCCEEDED(hr = pXmlAttributes->getNamedItem(bstrAttributeName, &pXmlAt)) ? pXmlAt ? SUCCEEDED(hr = pXmlAt->get_nodeValue(&varValue)) ? V_VT(&varValue) == VT_BSTR ? pbstrValue.attach(V_BSTR(&varValue)), V_VT(&varValue) = VT_EMPTY, S_OK : E_UNEXPECTED : hr : E_NOT_SET : hr; } template inline HRESULT get_attrib_value(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrAttributeName, _Out_ std::basic_string &sValue) { winstd::bstr bstr; HRESULT hr = get_attrib_value(pXmlParent, bstrAttributeName, bstr); if (SUCCEEDED(hr)) sValue.assign(bstr, bstr.length()); return hr; } inline HRESULT get_attrib_value(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrAttributeName, _Out_ DWORD &pdwValue) { winstd::bstr bstr; HRESULT hr = get_attrib_value(pXmlParent, bstrAttributeName, bstr); if (SUCCEEDED(hr)) pdwValue = wcstoul(bstr, NULL, 10); return hr; } inline HRESULT get_attrib_value(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrAttributeName, _Out_ bool &pbValue) { winstd::bstr bstr; HRESULT hr = get_attrib_value(pXmlParent, bstrAttributeName, bstr); if (SUCCEEDED(hr)) { if (CompareStringEx(LOCALE_NAME_INVARIANT, NORM_IGNORECASE, bstr, bstr.length(), L"true" , -1, NULL, NULL, 0) == CSTR_EQUAL || CompareStringEx(LOCALE_NAME_INVARIANT, NORM_IGNORECASE, bstr, bstr.length(), L"1" , -1, NULL, NULL, 0) == CSTR_EQUAL) pbValue = true; else if ( CompareStringEx(LOCALE_NAME_INVARIANT, NORM_IGNORECASE, bstr, bstr.length(), L"false", -1, NULL, NULL, 0) == CSTR_EQUAL || CompareStringEx(LOCALE_NAME_INVARIANT, NORM_IGNORECASE, bstr, bstr.length(), L"0" , -1, NULL, NULL, 0) == CSTR_EQUAL) pbValue = false; else hr = E_NOT_VALID_STATE; } return hr; } template inline HRESULT get_attrib_base64(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrAttributeName, _Out_ std::vector<_Ty, _Ax> &aValue) { winstd::bstr bstr; HRESULT hr = get_attrib_value(pXmlParent, bstrAttributeName, &bstr); if (SUCCEEDED(hr)) { winstd::base64_dec dec; bool is_last; dec.decode(aValue, is_last, (BSTR)bstr, bstr.length()); } return hr; } template inline HRESULT get_attrib_hex(_In_ IXMLDOMNode *pXmlParent, _In_z_ const BSTR bstrAttributeName, _Out_ std::vector<_Ty, _Ax> &aValue) { winstd::bstr bstr; HRESULT hr = get_attrib_value(pXmlParent, bstrAttributeName, &bstr); if (SUCCEEDED(hr)) { winstd::hex_dec dec; bool is_last; dec.decode(aValue, is_last, (BSTR)bstr, bstr.length()); } return hr; } inline HRESULT put_attrib_value(_In_ IXMLDOMNode *pCurrentDOMNode, _In_z_ const BSTR bstrAttributeName, _In_z_ const BSTR bstrValue) { HRESULT hr; winstd::com_obj pXmlEl; VARIANT varValue; V_VT(&varValue) = VT_BSTR; V_BSTR(&varValue) = bstrValue; return SUCCEEDED(hr = pCurrentDOMNode->QueryInterface(__uuidof(IXMLDOMElement), (void**)&pXmlEl)) && SUCCEEDED(hr = pXmlEl->setAttribute(bstrAttributeName, varValue)) ? S_OK : hr; } inline HRESULT put_attrib_value(_In_ IXMLDOMNode *pCurrentDOMNode, _In_z_ const BSTR bstrAttributeName, _In_ DWORD dwValue) { return put_attrib_value(pCurrentDOMNode, bstrAttributeName, winstd::bstr(winstd::wstring_printf(L"%d", dwValue))); } inline HRESULT put_attrib_value(_In_ IXMLDOMNode *pCurrentDOMNode, _In_z_ const BSTR bstrAttributeName, _In_ bool bValue) { return put_attrib_value(pCurrentDOMNode, bstrAttributeName, winstd::bstr(bValue ? L"true": L"false")); } inline HRESULT put_attrib_base64(_In_ IXMLDOMNode *pCurrentDOMNode, _In_z_ const BSTR bstrAttributeName, _In_bytecount_(nValueLen) LPCVOID pValue, _In_ SIZE_T nValueLen) { std::wstring sBase64; winstd::base64_enc enc; enc.encode(sBase64, pValue, nValueLen); return put_attrib_value(pCurrentDOMNode, bstrAttributeName, winstd::bstr(sBase64)); } inline HRESULT put_attrib_hex(_In_ IXMLDOMNode *pCurrentDOMNode, _In_z_ const BSTR bstrAttributeName, _In_bytecount_(nValueLen) LPCVOID pValue, _In_ SIZE_T nValueLen) { std::wstring sHex; winstd::hex_enc enc; enc.encode(sHex, pValue, nValueLen); return put_attrib_value(pCurrentDOMNode, bstrAttributeName, winstd::bstr(sHex)); } inline std::wstring get_xpath(_In_ IXMLDOMNode *pXmlNode) { if (pXmlNode) { winstd::bstr bstr; winstd::com_obj pXmlNodeParent; return SUCCEEDED(pXmlNode->get_nodeName(&bstr)) ? SUCCEEDED(pXmlNode->get_parentNode(&pXmlNodeParent)) ? get_xpath(pXmlNodeParent) + L"/" + (LPCWSTR)bstr : (LPCWSTR)bstr : L"?"; } else return L""; } }