>From 52561a0598fd51e05c3764fcb85abca46474ba7f Mon Sep 17 00:00:00 2001
From: Nikolay Sivov <nsivov@codeweavers.com>
Date: Tue, 17 Jan 2012 22:07:11 +0300
Subject: [PATCH 2/3] Support MSIPATCH_DATATYPE_XMLBLOB when testing for applicable patch

---
 dlls/msi/msi.c |   95 ++++++++++++++++++++++++++++++++++++++++++++++++++++++-
 1 files changed, 93 insertions(+), 2 deletions(-)

diff --git a/dlls/msi/msi.c b/dlls/msi/msi.c
index fd2315f..941a547 100644
--- a/dlls/msi/msi.c
+++ b/dlls/msi/msi.c
@@ -42,6 +42,9 @@
 #include "wintrust.h"
 #include "softpub.h"
 
+#include "initguid.h"
+#include "msxml2.h"
+
 #include "wine/debug.h"
 #include "wine/unicode.h"
 
@@ -304,7 +307,6 @@ done:
     return r;
 }
 
-
 static UINT get_patch_product_codes( LPCWSTR szPatchPackage, WCHAR ***product_codes )
 {
     MSIHANDLE patch, info = 0;
@@ -580,17 +582,63 @@ static UINT MSI_ApplicablePatchW( MSIPACKAGE *package, LPCWSTR patch )
     return r;
 }
 
+/* IXMLDOMDocument should be set to XPath mode already */
+static UINT MSI_ApplicablePatchXML( MSIPACKAGE *package, IXMLDOMDocument *desc )
+{
+    static const WCHAR queryW[] = {'M','s','i','P','a','t','c','h','/',
+                                   'T','a','r','g','e','t','P','r','o','d','u','c','t','/',
+                                   'T','a','r','g','e','t','P','r','o','d','u','c','t','C','o','d','e',0};
+    UINT r = ERROR_FUNCTION_FAILED;
+    IXMLDOMNodeList *list;
+    LPWSTR product_code;
+    IXMLDOMNode *node;
+    HRESULT hr;
+    BSTR s;
+
+    product_code = msi_dup_property( package->db, szProductCode );
+    if (!product_code)
+    {
+        /* FIXME: the property ProductCode should be written into the DB somewhere */
+        ERR("no product code to check\n");
+        return ERROR_SUCCESS;
+    }
+
+    s = SysAllocString(queryW);
+    hr = IXMLDOMDocument_selectNodes( desc, s, &list );
+    SysFreeString(s);
+    if (hr != S_OK)
+        return ERROR_INVALID_PATCH_XML;
+
+    while (IXMLDOMNodeList_nextNode( list, &node ) == S_OK && r != ERROR_SUCCESS)
+    {
+        hr = IXMLDOMNode_get_text( node, &s );
+        IXMLDOMNode_Release( node );
+        if (!strcmpW( s, product_code )) r = ERROR_SUCCESS;
+        SysFreeString(s);
+    }
+    IXMLDOMNodeList_Release( list );
+
+    if (r != ERROR_SUCCESS)
+        TRACE("patch not applicable\n");
+
+    msi_free( product_code );
+    return r;
+}
+
 static UINT determine_patch_sequence( MSIPACKAGE *package, DWORD count, MSIPATCHSEQUENCEINFOW *info )
 {
+    IXMLDOMDocument *desc = NULL;
     DWORD i;
 
+    if (count > 1)
+        FIXME("patch ordering not supported\n");
+
     for (i = 0; i < count; i++)
     {
         switch (info[i].ePatchDataType)
         {
         case MSIPATCH_DATATYPE_PATCHFILE:
         {
-            FIXME("patch ordering not supported\n");
             if (MSI_ApplicablePatchW( package, info[i].szPatchData ) != ERROR_SUCCESS)
             {
                 info[i].dwOrder = ~0u;
@@ -603,6 +651,45 @@ static UINT determine_patch_sequence( MSIPACKAGE *package, DWORD count, MSIPATCH
             }
             break;
         }
+        case MSIPATCH_DATATYPE_XMLBLOB:
+        {
+            VARIANT_BOOL b;
+            HRESULT hr;
+            BSTR s;
+
+            if (!desc)
+            {
+                hr = CoCreateInstance( &CLSID_DOMDocument30, NULL, CLSCTX_INPROC_SERVER,
+                    &IID_IXMLDOMDocument, (void**)&desc );
+                if (hr != S_OK)
+                {
+                    ERR("failed to create DOMDocument30 instance, 0x%08x\n", hr);
+                    return ERROR_FUNCTION_FAILED;
+                }
+            }
+
+            s = SysAllocString( info[i].szPatchData );
+            hr = IXMLDOMDocument_loadXML( desc, s, &b );
+            SysFreeString( s );
+            if ( hr != S_OK )
+            {
+                ERR("failed to parse patch description\n");
+                IXMLDOMDocument_Release( desc );
+                break;
+            }
+
+            if (MSI_ApplicablePatchXML( package, desc ) != ERROR_SUCCESS)
+            {
+                info[i].dwOrder = ~0u;
+                info[i].uStatus = ERROR_PATCH_TARGET_NOT_FOUND;
+            }
+            else
+            {
+                info[i].dwOrder = i;
+                info[i].uStatus = ERROR_SUCCESS;
+            }
+            break;
+        }
         default:
         {
             FIXME("patch data type %u not supported\n", info[i].ePatchDataType);
@@ -611,11 +698,15 @@ static UINT determine_patch_sequence( MSIPACKAGE *package, DWORD count, MSIPATCH
             break;
         }
         }
+
         TRACE("szPatchData: %s\n", debugstr_w(info[i].szPatchData));
         TRACE("ePatchDataType: %u\n", info[i].ePatchDataType);
         TRACE("dwOrder: %u\n", info[i].dwOrder);
         TRACE("uStatus: %u\n", info[i].uStatus);
     }
+
+    if (desc) IXMLDOMDocument_Release( desc );
+
     return ERROR_SUCCESS;
 }
 
-- 
1.5.6.5


