msi: Support more transform validation flags.

Hans Leidekker hans at codeweavers.com
Mon Oct 20 11:18:20 CDT 2014


---
dlls/msi/msipriv.h |   1 +
dlls/msi/package.c |   2 +-
dlls/msi/patch.c   | 215 ++++++++++++++++++++++++++++++++++++++++++++++-------
3 files changed, 191 insertions(+), 27 deletions(-)

diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h
index d0b2247..bf788ba 100644
--- a/dlls/msi/msipriv.h
+++ b/dlls/msi/msipriv.h
@@ -940,6 +940,7 @@ extern LPWSTR msi_suminfo_dup_string( MSISUMMARYINFO *si, UINT uiProperty ) DECL
extern INT msi_suminfo_get_int32( MSISUMMARYINFO *si, UINT uiProperty ) DECLSPEC_HIDDEN;
extern LPWSTR msi_get_suminfo_product( IStorage *stg ) DECLSPEC_HIDDEN;
extern UINT msi_add_suminfo( MSIDATABASE *db, LPWSTR **records, int num_records, int num_columns ) DECLSPEC_HIDDEN;
+extern enum platform parse_platform( const WCHAR *str ) DECLSPEC_HIDDEN;

/* undocumented functions */
UINT WINAPI MsiCreateAndVerifyInstallerDirectory( DWORD );
diff --git a/dlls/msi/package.c b/dlls/msi/package.c
index 96de82d..2805003 100644
--- a/dlls/msi/package.c
+++ b/dlls/msi/package.c
@@ -1271,7 +1271,7 @@ UINT msi_create_empty_local_file( LPWSTR path, LPCWSTR suffix )
    return ERROR_SUCCESS;
}

-static enum platform parse_platform( WCHAR *str )
+enum platform parse_platform( const WCHAR *str )
{
    if (!str[0] || !strcmpW( str, szIntel )) return PLATFORM_INTEL;
    else if (!strcmpW( str, szIntel64 )) return PLATFORM_INTEL64;
diff --git a/dlls/msi/patch.c b/dlls/msi/patch.c
index a3a8d32..d862a20 100644
--- a/dlls/msi/patch.c
+++ b/dlls/msi/patch.c
@@ -44,57 +44,220 @@ static BOOL match_language( MSIPACKAGE *package, LANGID langid )
    return FALSE;
}

+struct transform_desc
+{
+    WCHAR *product_code_from;
+    WCHAR *product_code_to;
+    WCHAR *version_from;
+    WCHAR *version_to;
+    WCHAR *upgrade_code;
+};
+
+static void free_transform_desc( struct transform_desc *desc )
+{
+    msi_free( desc->product_code_from );
+    msi_free( desc->product_code_to );
+    msi_free( desc->version_from );
+    msi_free( desc->version_to );
+    msi_free( desc->upgrade_code );
+    msi_free( desc );
+}
+
+static struct transform_desc *parse_transform_desc( const WCHAR *str )
+{
+    struct transform_desc *ret;
+    const WCHAR *p = str, *q;
+    UINT len;
+
+    if (!(ret = msi_alloc_zero( sizeof(*ret) ))) return NULL;
+
+    q = strchrW( p, '}' );
+    if (*p != '{' || !q) goto error;
+
+    len = q - p + 1;
+    if (!(ret->product_code_from = msi_alloc( (len + 1) * sizeof(WCHAR) ))) goto error;
+    memcpy( ret->product_code_from, p, len * sizeof(WCHAR) );
+    ret->product_code_from[len] = 0;
+
+    p = q + 1;
+    if (!(q = strchrW( p, ';' ))) goto error;
+    len = q - p;
+    if (!(ret->version_from = msi_alloc( (len + 1) * sizeof(WCHAR) ))) goto error;
+    memcpy( ret->version_from, p, len * sizeof(WCHAR) );
+    ret->version_from[len] = 0;
+
+    p = q + 1;
+    q = strchrW( p, '}' );
+    if (*p != '{' || !q) goto error;
+
+    len = q - p + 1;
+    if (!(ret->product_code_to = msi_alloc( (len + 1) * sizeof(WCHAR) ))) goto error;
+    memcpy( ret->product_code_to, p, len * sizeof(WCHAR) );
+    ret->product_code_to[len] = 0; 
+
+    p = q + 1;
+    if (!(q = strchrW( p, ';' ))) goto error;
+    len = q - p;
+    if (!(ret->version_to = msi_alloc( (len + 1) * sizeof(WCHAR) ))) goto error;
+    memcpy( ret->version_to, p, len * sizeof(WCHAR) );
+    ret->version_to[len] = 0; 
+
+    p = q + 1;
+    q = strchrW( p, '}' );
+    if (*p != '{' || !q) goto error;
+
+    len = q - p + 1;
+    if (!(ret->upgrade_code = msi_alloc( (len + 1) * sizeof(WCHAR) ))) goto error;
+    memcpy( ret->upgrade_code, p, len * sizeof(WCHAR) );
+    ret->upgrade_code[len] = 0;
+
+    return ret;
+
+error:
+    free_transform_desc( ret );
+    return NULL;
+}
+
static UINT check_transform_applicable( MSIPACKAGE *package, IStorage *transform )
{
+    static const UINT supported_flags =
+        MSITRANSFORM_VALIDATE_PRODUCT  | MSITRANSFORM_VALIDATE_LANGUAGE |
+        MSITRANSFORM_VALIDATE_PLATFORM | MSITRANSFORM_VALIDATE_MAJORVERSION |
+        MSITRANSFORM_VALIDATE_MINORVERSION | MSITRANSFORM_VALIDATE_UPGRADECODE;
    MSISUMMARYINFO *si = MSI_GetSummaryInformationW( transform, 0 );
    UINT valid_flags = 0, wanted_flags = 0;
+    WCHAR *template, *product, *p;
+    struct transform_desc *desc;

-    if (si) wanted_flags = msi_suminfo_get_int32( si, PID_CHARCOUNT );
-    TRACE("validation flags %x\n", wanted_flags);
+    if (!si)
+    {
+        WARN("no summary information!\n");
+        return ERROR_FUNCTION_FAILED;
+    }
+    wanted_flags = msi_suminfo_get_int32( si, PID_CHARCOUNT );
+    wanted_flags &= 0xffff; /* mask off error condition flags */
+    TRACE("validation flags 0x%04x\n", wanted_flags);

-    if (wanted_flags & ~(MSITRANSFORM_VALIDATE_PRODUCT|MSITRANSFORM_VALIDATE_LANGUAGE))
-        FIXME("unsupported validation flags %x\n", wanted_flags);
+    if (wanted_flags & ~supported_flags)
+    {
+        FIXME("unsupported validation flags 0x%04x\n", wanted_flags);
+        msiobj_release( &si->hdr );
+        return ERROR_FUNCTION_FAILED;
+    }
+    if (!(template = msi_suminfo_dup_string( si, PID_TEMPLATE )))
+    {
+        WARN("no template property!\n");
+        msiobj_release( &si->hdr );
+        return ERROR_FUNCTION_FAILED;
+    }
+    TRACE("template property: %s\n", debugstr_w(template));
+    if (!(product = msi_get_suminfo_product( transform )))
+    {
+        WARN("no product property!\n");
+        msi_free( template );
+        msiobj_release( &si->hdr );
+        return ERROR_FUNCTION_FAILED;
+    }
+    TRACE("product property: %s\n", debugstr_w(product));
+    if (!(desc = parse_transform_desc( product )))
+    {
+        msi_free( template );
+        msiobj_release( &si->hdr );
+        return ERROR_FUNCTION_FAILED;
+    }
+    msi_free( product );

+    if (wanted_flags & MSITRANSFORM_VALIDATE_LANGUAGE)
+    {
+        if (!template[0] || ((p = strchrW( template, ';' )) && match_language( package, atoiW( p + 1 ) )))
+        {
+            valid_flags |= MSITRANSFORM_VALIDATE_LANGUAGE;
+        }
+    }
    if (wanted_flags & MSITRANSFORM_VALIDATE_PRODUCT)
    {
-        WCHAR *package_product = msi_dup_property( package->db, szProductCode );
-        WCHAR *transform_product = msi_get_suminfo_product( transform );
+        WCHAR *product_code_installed = msi_dup_property( package->db, szProductCode );

-        TRACE("package = %s transform = %s\n", debugstr_w(package_product), debugstr_w(transform_product));
-
-        if (!transform_product || strstrW( transform_product, package_product ))
+        if (!product_code_installed)
+        {
+            msi_free( template );
+            free_transform_desc( desc );
+            msiobj_release( &si->hdr );
+            return ERROR_INSTALL_PACKAGE_INVALID;
+        }
+        if (!strcmpW( desc->product_code_from, product_code_installed ))
        {
            valid_flags |= MSITRANSFORM_VALIDATE_PRODUCT;
        }
-        msi_free( transform_product );
-        msi_free( package_product );
+        msi_free( product_code_installed );
    }
-    if (wanted_flags & MSITRANSFORM_VALIDATE_LANGUAGE)
+    if (wanted_flags & MSITRANSFORM_VALIDATE_PLATFORM)
    {
-        WCHAR *template;
-        const WCHAR *p;
+        if ((p = strchrW( template, ';' )))
+        {
+            *p = 0;
+            if (package->platform == parse_platform( template ))
+                valid_flags |= MSITRANSFORM_VALIDATE_PLATFORM;
+        }
+    }
+    msi_free( template );
+    if (wanted_flags & MSITRANSFORM_VALIDATE_MAJORVERSION)
+    {
+        WCHAR *product_version_installed = msi_dup_property( package->db, szProductVersion );
+        DWORD major_installed, minor_installed, major, minor;

-        if (!si)
+        if (!product_version_installed)
        {
-            ERR("no summary information!\n");
-            goto end;
+            free_transform_desc( desc );
+            msiobj_release( &si->hdr );
+            return ERROR_INSTALL_PACKAGE_INVALID;
        }
-        if (!(template = msi_suminfo_dup_string( si, PID_TEMPLATE )))
+        msi_parse_version_string( product_version_installed, &major_installed, &minor_installed );
+        msi_parse_version_string( desc->version_from, &major, &minor );
+
+        if (major_installed == major)
        {
-            ERR("no template property!\n");
-            goto end;
+            valid_flags |= MSITRANSFORM_VALIDATE_MAJORVERSION;
+            wanted_flags &= ~MSITRANSFORM_VALIDATE_MINORVERSION;
        }
-        TRACE("template: %s\n", debugstr_w(template));
-        if (!template[0] || ((p = strchrW( template, ';' )) && match_language( package, atoiW( p + 1 ) )))
+        msi_free( product_version_installed );
+    }
+    else if (wanted_flags & MSITRANSFORM_VALIDATE_MINORVERSION)
+    {
+        WCHAR *product_version_installed = msi_dup_property( package->db, szProductVersion );
+        DWORD major_installed, minor_installed, major, minor;
+
+        if (!product_version_installed)
        {
-            valid_flags |= MSITRANSFORM_VALIDATE_LANGUAGE;
+            free_transform_desc( desc );
+            msiobj_release( &si->hdr );
+            return ERROR_INSTALL_PACKAGE_INVALID;
        }
-        msi_free( template );
+        msi_parse_version_string( product_version_installed, &major_installed, &minor_installed );
+        msi_parse_version_string( desc->version_from, &major, &minor );
+
+        if (major_installed == major && minor_installed == minor)
+            valid_flags |= MSITRANSFORM_VALIDATE_MINORVERSION;
+        msi_free( product_version_installed );
+    }
+    if (wanted_flags & MSITRANSFORM_VALIDATE_UPGRADECODE)
+    {
+        WCHAR *upgrade_code_installed = msi_dup_property( package->db, szUpgradeCode );
+
+        if (!upgrade_code_installed)
+        {
+            free_transform_desc( desc );
+            msiobj_release( &si->hdr );
+            return ERROR_INSTALL_PACKAGE_INVALID;
+        }
+        if (!strcmpW( desc->upgrade_code, upgrade_code_installed ))
+            valid_flags |= MSITRANSFORM_VALIDATE_UPGRADECODE;
+        msi_free( upgrade_code_installed );
    }

-end:
+    free_transform_desc( desc );
    msiobj_release( &si->hdr );
-    if (valid_flags & ~wanted_flags) return ERROR_FUNCTION_FAILED;
+    if ((valid_flags & wanted_flags) != wanted_flags) return ERROR_FUNCTION_FAILED;
    TRACE("applicable transform\n");
    return ERROR_SUCCESS;
}
-- 
2.1.1




More information about the wine-patches mailing list