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