msi: Support more transform validation flags.
This commit is contained in:
parent
5a6558b854
commit
1e3f15d88c
|
@ -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 );
|
||||
|
|
|
@ -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;
|
||||
|
|
233
dlls/msi/patch.c
233
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 (wanted_flags & ~(MSITRANSFORM_VALIDATE_PRODUCT|MSITRANSFORM_VALIDATE_LANGUAGE))
|
||||
FIXME("unsupported validation flags %x\n", wanted_flags);
|
||||
|
||||
if (wanted_flags & MSITRANSFORM_VALIDATE_PRODUCT)
|
||||
if (!si)
|
||||
{
|
||||
WCHAR *package_product = msi_dup_property( package->db, szProductCode );
|
||||
WCHAR *transform_product = msi_get_suminfo_product( transform );
|
||||
|
||||
TRACE("package = %s transform = %s\n", debugstr_w(package_product), debugstr_w(transform_product));
|
||||
|
||||
if (!transform_product || strstrW( transform_product, package_product ))
|
||||
{
|
||||
valid_flags |= MSITRANSFORM_VALIDATE_PRODUCT;
|
||||
}
|
||||
msi_free( transform_product );
|
||||
msi_free( package_product );
|
||||
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 & ~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)
|
||||
{
|
||||
WCHAR *template;
|
||||
const WCHAR *p;
|
||||
|
||||
if (!si)
|
||||
{
|
||||
ERR("no summary information!\n");
|
||||
goto end;
|
||||
}
|
||||
if (!(template = msi_suminfo_dup_string( si, PID_TEMPLATE )))
|
||||
{
|
||||
ERR("no template property!\n");
|
||||
goto end;
|
||||
}
|
||||
TRACE("template: %s\n", debugstr_w(template));
|
||||
if (!template[0] || ((p = strchrW( template, ';' )) && match_language( package, atoiW( p + 1 ) )))
|
||||
{
|
||||
valid_flags |= MSITRANSFORM_VALIDATE_LANGUAGE;
|
||||
}
|
||||
msi_free( template );
|
||||
}
|
||||
if (wanted_flags & MSITRANSFORM_VALIDATE_PRODUCT)
|
||||
{
|
||||
WCHAR *product_code_installed = msi_dup_property( package->db, szProductCode );
|
||||
|
||||
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( product_code_installed );
|
||||
}
|
||||
if (wanted_flags & MSITRANSFORM_VALIDATE_PLATFORM)
|
||||
{
|
||||
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 (!product_version_installed)
|
||||
{
|
||||
free_transform_desc( desc );
|
||||
msiobj_release( &si->hdr );
|
||||
return ERROR_INSTALL_PACKAGE_INVALID;
|
||||
}
|
||||
msi_parse_version_string( product_version_installed, &major_installed, &minor_installed );
|
||||
msi_parse_version_string( desc->version_from, &major, &minor );
|
||||
|
||||
if (major_installed == major)
|
||||
{
|
||||
valid_flags |= MSITRANSFORM_VALIDATE_MAJORVERSION;
|
||||
wanted_flags &= ~MSITRANSFORM_VALIDATE_MINORVERSION;
|
||||
}
|
||||
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)
|
||||
{
|
||||
free_transform_desc( desc );
|
||||
msiobj_release( &si->hdr );
|
||||
return ERROR_INSTALL_PACKAGE_INVALID;
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue