#define COBJMACROS #define CINTERFACE #include #include #include #include /* 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"" L"" L"" L""); 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"runtime"); 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[] = "runtime"; 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"CAB-x", &matched); if (failed) return failed; if (matched != S_OK) return 18; if ((failed = validate(L"CA B", &refused))) return failed; if (refused == S_OK) return 19; CoUninitialize(); return 0; }