Files
mirkobrombin 6dc4e2a318 feat: add MSXML 6 and XmlLite to the installer components
Assisted-by: Claude Code:claude-opus-5-5
AI-Scope: Added the MSXML 6 classes and XmlLite to the ReactOS component build, a libxml2 regexp patch and the tests.
2026-10-27 12:07:27 +00:00

132 lines
5.3 KiB
C

#define COBJMACROS
#define CINTERFACE
#include <windows.h>
#include <objbase.h>
#include <initguid.h>
#include <msxml2.h>
/* The XML document object as installers and their bootstrappers use it: found by its program identifier through the registry, made by
the library registered for its class, parsing a document and answering an XPath query; then loading the same document from a file in a
folder named like a bootstrapper's, through its URL. Last, a schema whose patterns use the code unit escapes of MSXML 6 inside character
classes, as the deployment schema of Click-to-Run Office does, validating one document that matches and one that does not. */
static int validate(const WCHAR *xml, HRESULT *result)
{
CLSID clsid;
IXMLDOMDocument2 *schema = NULL, *document = NULL;
IXMLDOMSchemaCollection *cache = NULL;
IXMLDOMParseError *error = NULL;
VARIANT_BOOL loaded = VARIANT_FALSE;
BSTR text, name;
VARIANT value;
if (CLSIDFromProgID(L"Msxml2.DOMDocument.6.0", &clsid) != S_OK ||
CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument2, (void **)&schema) != S_OK ||
CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument2, (void **)&document) != S_OK)
return 11;
text = SysAllocString(L"<xs:schema xmlns:xs=\"http://www.w3.org/2001/XMLSchema\" targetNamespace=\"urn:raven\" elementFormDefault=\"qualified\">"
L"<xs:element name=\"v\"><xs:simpleType><xs:restriction base=\"xs:string\">"
L"<xs:pattern value=\"[\\u0041-\\u0043]+[^&quot;\\u0000-\\u0020\\u007F]*\"/>"
L"</xs:restriction></xs:simpleType></xs:element></xs:schema>");
if (IXMLDOMDocument2_loadXML(schema, text, &loaded) != S_OK || loaded != VARIANT_TRUE)
return 12;
SysFreeString(text);
if (CLSIDFromProgID(L"Msxml2.XMLSchemaCache.6.0", &clsid) != S_OK ||
CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMSchemaCollection, (void **)&cache) != S_OK)
return 13;
name = SysAllocString(L"urn:raven");
V_VT(&value) = VT_DISPATCH;
V_DISPATCH(&value) = (IDispatch *)schema;
if (IXMLDOMSchemaCollection_add(cache, name, value) != S_OK)
return 14;
V_VT(&value) = VT_DISPATCH;
V_DISPATCH(&value) = (IDispatch *)cache;
if (IXMLDOMDocument2_putref_schemas(document, value) != S_OK)
return 15;
text = SysAllocString(xml);
loaded = VARIANT_FALSE;
if (IXMLDOMDocument2_put_validateOnParse(document, VARIANT_FALSE) != S_OK || IXMLDOMDocument2_loadXML(document, text, &loaded) != S_OK ||
loaded != VARIANT_TRUE)
return 16;
if (IXMLDOMDocument2_validate(document, &error) == E_NOTIMPL)
return 17;
*result = S_OK;
if (error)
IXMLDOMParseError_get_errorCode(error, (LONG *)result);
if (error)
IXMLDOMParseError_Release(error);
SysFreeString(text);
SysFreeString(name);
IXMLDOMSchemaCollection_Release(cache);
IXMLDOMDocument2_Release(document);
IXMLDOMDocument2_Release(schema);
return 0;
}
int raven_entry(void)
{
CLSID clsid;
IXMLDOMDocument *document = NULL;
IXMLDOMNode *node = NULL;
VARIANT_BOOL loaded = VARIANT_FALSE;
BSTR text = NULL, query, value = NULL;
if (FAILED(CoInitialize(NULL)))
return 1;
if (CLSIDFromProgID(L"Msxml2.DOMDocument", &clsid) != S_OK)
return 2;
if (CoCreateInstance(&clsid, NULL, CLSCTX_INPROC_SERVER, &IID_IXMLDOMDocument, (void **)&document) != S_OK || !document)
return 3;
text = SysAllocString(L"<bundle><package id=\"vcRuntime\" size=\"4242\">runtime</package></bundle>");
if (IXMLDOMDocument_loadXML(document, text, &loaded) != S_OK || loaded != VARIANT_TRUE)
return 4;
query = SysAllocString(L"/bundle/package/@size");
if (IXMLDOMDocument_selectSingleNode(document, query, &node) != S_OK || !node)
return 5;
if (IXMLDOMNode_get_text(node, &value) != S_OK || !value || lstrcmpW(value, L"4242"))
return 6;
SysFreeString(value);
IXMLDOMNode_Release(node);
WCHAR folder[MAX_PATH], path[MAX_PATH];
GetTempPathW(MAX_PATH, folder);
lstrcatW(folder, L"{F2DA498E-66A3-4183-B794-FD6A62ED92B0}");
CreateDirectoryW(folder, NULL);
lstrcatW(folder, L"\\.ba");
CreateDirectoryW(folder, NULL);
lstrcpyW(path, folder);
lstrcatW(path, L"\\BootstrapperApplicationData.xml");
static const char data[] = "<bundle><package id=\"vcRuntime\" size=\"4343\">runtime</package></bundle>";
DWORD written;
HANDLE file = CreateFileW(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
if (file == INVALID_HANDLE_VALUE || !WriteFile(file, data, sizeof data - 1, &written, NULL) || !CloseHandle(file))
return 7;
VARIANT source;
VariantInit(&source);
V_VT(&source) = VT_BSTR;
V_BSTR(&source) = SysAllocString(path);
loaded = VARIANT_FALSE;
if (IXMLDOMDocument_load(document, source, &loaded) != S_OK || loaded != VARIANT_TRUE)
return 8;
if (IXMLDOMDocument_selectSingleNode(document, query, &node) != S_OK || !node)
return 9;
if (IXMLDOMNode_get_text(node, &value) != S_OK || !value || lstrcmpW(value, L"4343"))
return 10;
DeleteFileW(path);
SysFreeString(value);
VariantClear(&source);
SysFreeString(query);
SysFreeString(text);
IXMLDOMNode_Release(node);
IXMLDOMDocument_Release(document);
HRESULT matched = E_FAIL, refused = S_OK;
int failed = validate(L"<v xmlns=\"urn:raven\">CAB-x</v>", &matched);
if (failed)
return failed;
if (matched != S_OK)
return 18;
if ((failed = validate(L"<v xmlns=\"urn:raven\">CA B</v>", &refused)))
return failed;
if (refused == S_OK)
return 19;
CoUninitialize();
return 0;
}