msi: Check supported languages in the AppSearch action.

This commit is contained in:
Hans Leidekker 2012-04-23 15:47:15 +02:00 committed by Alexandre Julliard
parent 52f3d5bead
commit c8bb335990
3 changed files with 104 additions and 62 deletions

View File

@ -608,6 +608,65 @@ static void ACTION_ExpandAnyPath(MSIPACKAGE *package, WCHAR *src, WCHAR *dst,
msi_free(deformatted);
}
static LANGID *parse_languages( const WCHAR *languages, DWORD *num_ids )
{
UINT i, count = 1;
WCHAR *str = strdupW( languages ), *p, *q;
LANGID *ret;
if (!str) return NULL;
for (p = q = str; (q = strchrW( q, ',' )); q++) count++;
if (!(ret = msi_alloc( count * sizeof(LANGID) )))
{
msi_free( str );
return NULL;
}
i = 0;
while (*p)
{
q = strchrW( p, ',' );
if (q) *q = 0;
ret[i] = atoiW( p );
if (!q) break;
p = q + 1;
i++;
}
msi_free( str );
*num_ids = count;
return ret;
}
static BOOL match_languages( const void *version, const WCHAR *languages )
{
struct lang
{
USHORT id;
USHORT codepage;
} *lang;
DWORD len, num_ids, i, j;
BOOL found = FALSE;
LANGID *ids;
if (!languages || !languages[0]) return TRUE;
if (!VerQueryValueW( version, szLangResource, (void **)&lang, &len )) return FALSE;
if (!(ids = parse_languages( languages, &num_ids ))) return FALSE;
for (i = 0; i < num_ids; i++)
{
found = FALSE;
for (j = 0; j < len / sizeof(struct lang); j++)
{
if (!ids[i] || ids[i] == lang[j].id) found = TRUE;
}
if (!found) goto done;
}
done:
msi_free( ids );
return found;
}
/* Sets *matches to whether the file (whose path is filePath) matches the
* versions set in sig.
* Return ERROR_SUCCESS in case of success (whether or not the file matches),
@ -616,69 +675,55 @@ static void ACTION_ExpandAnyPath(MSIPACKAGE *package, WCHAR *src, WCHAR *dst,
static UINT ACTION_FileVersionMatches(const MSISIGNATURE *sig, LPCWSTR filePath,
BOOL *matches)
{
UINT rc = ERROR_SUCCESS;
UINT len;
void *version;
VS_FIXEDFILEINFO *info = NULL;
DWORD zero, size = GetFileVersionInfoSizeW( filePath, &zero );
*matches = FALSE;
if (sig->Languages)
{
FIXME(": need to check version for languages %s\n",
debugstr_w(sig->Languages));
}
else
{
DWORD zero, size = GetFileVersionInfoSizeW(filePath, &zero);
if (size)
if (!size) return ERROR_SUCCESS;
if (!(version = msi_alloc( size ))) return ERROR_OUTOFMEMORY;
if (GetFileVersionInfoW( filePath, 0, size, version ))
VerQueryValueW( version, szBackSlash, (void **)&info, &len );
if (info)
{
TRACE("comparing file version %d.%d.%d.%d:\n",
HIWORD(info->dwFileVersionMS),
LOWORD(info->dwFileVersionMS),
HIWORD(info->dwFileVersionLS),
LOWORD(info->dwFileVersionLS));
if (info->dwFileVersionMS < sig->MinVersionMS
|| (info->dwFileVersionMS == sig->MinVersionMS &&
info->dwFileVersionLS < sig->MinVersionLS))
{
LPVOID buf = msi_alloc( size);
if (buf)
{
UINT versionLen;
LPVOID subBlock = NULL;
if (GetFileVersionInfoW(filePath, 0, size, buf))
VerQueryValueW(buf, szBackSlash, &subBlock, &versionLen);
if (subBlock)
{
VS_FIXEDFILEINFO *info = subBlock;
TRACE("Comparing file version %d.%d.%d.%d:\n",
HIWORD(info->dwFileVersionMS),
LOWORD(info->dwFileVersionMS),
HIWORD(info->dwFileVersionLS),
LOWORD(info->dwFileVersionLS));
if (info->dwFileVersionMS < sig->MinVersionMS
|| (info->dwFileVersionMS == sig->MinVersionMS &&
info->dwFileVersionLS < sig->MinVersionLS))
{
TRACE("Less than minimum version %d.%d.%d.%d\n",
HIWORD(sig->MinVersionMS),
LOWORD(sig->MinVersionMS),
HIWORD(sig->MinVersionLS),
LOWORD(sig->MinVersionLS));
}
else if ((sig->MaxVersionMS || sig->MaxVersionLS) &&
(info->dwFileVersionMS > sig->MaxVersionMS ||
(info->dwFileVersionMS == sig->MaxVersionMS &&
info->dwFileVersionLS > sig->MaxVersionLS)))
{
TRACE("Greater than maximum version %d.%d.%d.%d\n",
HIWORD(sig->MaxVersionMS),
LOWORD(sig->MaxVersionMS),
HIWORD(sig->MaxVersionLS),
LOWORD(sig->MaxVersionLS));
}
else
*matches = TRUE;
}
msi_free( buf);
}
else
rc = ERROR_OUTOFMEMORY;
TRACE("less than minimum version %d.%d.%d.%d\n",
HIWORD(sig->MinVersionMS),
LOWORD(sig->MinVersionMS),
HIWORD(sig->MinVersionLS),
LOWORD(sig->MinVersionLS));
}
else if ((sig->MaxVersionMS || sig->MaxVersionLS) &&
(info->dwFileVersionMS > sig->MaxVersionMS ||
(info->dwFileVersionMS == sig->MaxVersionMS &&
info->dwFileVersionLS > sig->MaxVersionLS)))
{
TRACE("greater than maximum version %d.%d.%d.%d\n",
HIWORD(sig->MaxVersionMS),
LOWORD(sig->MaxVersionMS),
HIWORD(sig->MaxVersionLS),
LOWORD(sig->MaxVersionLS));
}
else if (!match_languages( version, sig->Languages ))
{
TRACE("languages %s not supported\n", debugstr_w( sig->Languages ));
}
else *matches = TRUE;
}
return rc;
msi_free( version );
return ERROR_SUCCESS;
}
/* Sets *matches to whether the file in findData matches that in sig.

View File

@ -3133,11 +3133,7 @@ static UINT get_file_version( const WCHAR *path, WCHAR *verbuf, DWORD *verlen,
WCHAR *langbuf, DWORD *langlen )
{
static const WCHAR szVersionResource[] = {'\\',0};
static const WCHAR szVersionFormat[] = {
'%','d','.','%','d','.','%','d','.','%','d',0};
static const WCHAR szLangResource[] = {
'\\','V','a','r','F','i','l','e','I','n','f','o','\\',
'T','r','a','n','s','l','a','t','i','o','n',0};
static const WCHAR szVersionFormat[] = {'%','d','.','%','d','.','%','d','.','%','d',0};
static const WCHAR szLangFormat[] = {'%','d',0};
UINT ret = ERROR_SUCCESS;
DWORD len, error;

View File

@ -1172,6 +1172,7 @@ static const WCHAR szAppDataFolder[] = {'A','p','p','D','a','t','a','F','o','l',
static const WCHAR szRollbackDisabled[] = {'R','o','l','l','b','a','c','k','D','i','s','a','b','l','e','d',0};
static const WCHAR szName[] = {'N','a','m','e',0};
static const WCHAR szData[] = {'D','a','t','a',0};
static const WCHAR szLangResource[] = {'\\','V','a','r','F','i','l','e','I','n','f','o','\\','T','r','a','n','s','l','a','t','i','o','n',0};
/* memory allocation macro functions */
static void *msi_alloc( size_t len ) __WINE_ALLOC_SIZE(1);