msi: Implement and test MsiGetFeatureInfo.

This commit is contained in:
Hans Leidekker 2011-06-10 10:13:34 +02:00 committed by Alexandre Julliard
parent aec97287bc
commit 4c9c50d86b
6 changed files with 226 additions and 6 deletions

View File

@ -999,7 +999,7 @@ static UINT load_component( MSIRECORD *row, LPVOID param )
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
static UINT load_all_components( MSIPACKAGE *package ) UINT msi_load_all_components( MSIPACKAGE *package )
{ {
static const WCHAR query[] = { static const WCHAR query[] = {
'S','E','L','E','C','T',' ','*',' ','F','R', 'O','M',' ', 'S','E','L','E','C','T',' ','*',' ','F','R', 'O','M',' ',
@ -1161,7 +1161,7 @@ static UINT find_feature_children(MSIRECORD * row, LPVOID param)
return ERROR_SUCCESS; return ERROR_SUCCESS;
} }
static UINT load_all_features( MSIPACKAGE *package ) UINT msi_load_all_features( MSIPACKAGE *package )
{ {
static const WCHAR query[] = { static const WCHAR query[] = {
'S','E','L','E','C','T',' ','*',' ', 'F','R','O','M',' ', 'S','E','L','E','C','T',' ','*',' ', 'F','R','O','M',' ',
@ -1550,8 +1550,8 @@ static UINT ACTION_CostInitialize(MSIPACKAGE *package)
msi_set_property( package->db, szRootDrive, szCRoot ); msi_set_property( package->db, szRootDrive, szCRoot );
load_all_folders( package ); load_all_folders( package );
load_all_components( package ); msi_load_all_components( package );
load_all_features( package ); msi_load_all_features( package );
load_all_files( package ); load_all_files( package );
load_all_patches( package ); load_all_patches( package );
load_all_media( package ); load_all_media( package );

View File

@ -1254,6 +1254,126 @@ UINT WINAPI MsiGetFeatureCostW(MSIHANDLE hInstall, LPCWSTR szFeature,
return ret; return ret;
} }
/***********************************************************************
* MsiGetFeatureInfoA (MSI.@)
*/
UINT WINAPI MsiGetFeatureInfoA( MSIHANDLE handle, LPCSTR feature, LPDWORD attrs,
LPSTR title, LPDWORD title_len, LPSTR help, LPDWORD help_len )
{
UINT r;
WCHAR *titleW = NULL, *helpW = NULL, *featureW = NULL;
TRACE("%u, %s, %p, %p, %p, %p, %p\n", handle, debugstr_a(feature), attrs, title,
title_len, help, help_len);
if (feature && !(featureW = strdupAtoW( feature ))) return ERROR_OUTOFMEMORY;
if (title && title_len && !(titleW = msi_alloc( *title_len * sizeof(WCHAR) )))
{
msi_free( featureW );
return ERROR_OUTOFMEMORY;
}
if (help && help_len && !(helpW = msi_alloc( *help_len * sizeof(WCHAR) )))
{
msi_free( featureW );
msi_free( titleW );
return ERROR_OUTOFMEMORY;
}
r = MsiGetFeatureInfoW( handle, featureW, attrs, titleW, title_len, helpW, help_len );
if (r == ERROR_SUCCESS)
{
if (titleW) WideCharToMultiByte( CP_ACP, 0, titleW, -1, title, *title_len + 1, NULL, NULL );
if (helpW) WideCharToMultiByte( CP_ACP, 0, helpW, -1, help, *help_len + 1, NULL, NULL );
}
msi_free( titleW );
msi_free( helpW );
msi_free( featureW );
return r;
}
static DWORD map_feature_attributes( DWORD attrs )
{
DWORD ret = 0;
if (attrs == msidbFeatureAttributesFavorLocal) ret |= INSTALLFEATUREATTRIBUTE_FAVORLOCAL;
if (attrs & msidbFeatureAttributesFavorSource) ret |= INSTALLFEATUREATTRIBUTE_FAVORSOURCE;
if (attrs & msidbFeatureAttributesFollowParent) ret |= INSTALLFEATUREATTRIBUTE_FOLLOWPARENT;
if (attrs & msidbFeatureAttributesFavorAdvertise) ret |= INSTALLFEATUREATTRIBUTE_FAVORADVERTISE;
if (attrs & msidbFeatureAttributesDisallowAdvertise) ret |= INSTALLFEATUREATTRIBUTE_DISALLOWADVERTISE;
if (attrs & msidbFeatureAttributesNoUnsupportedAdvertise) ret |= INSTALLFEATUREATTRIBUTE_NOUNSUPPORTEDADVERTISE;
return ret;
}
static UINT MSI_GetFeatureInfo( MSIPACKAGE *package, LPCWSTR name, LPDWORD attrs,
LPWSTR title, LPDWORD title_len, LPWSTR help, LPDWORD help_len )
{
UINT r = ERROR_SUCCESS;
MSIFEATURE *feature = msi_get_loaded_feature( package, name );
int len;
if (!feature) return ERROR_UNKNOWN_FEATURE;
if (attrs) *attrs = map_feature_attributes( feature->Attributes );
if (title_len)
{
if (feature->Title) len = strlenW( feature->Title );
else len = 0;
if (*title_len <= len)
{
*title_len = len;
if (title) r = ERROR_MORE_DATA;
}
else if (title)
{
if (feature->Title) strcpyW( title, feature->Title );
else *title = 0;
*title_len = len;
}
}
if (help_len)
{
if (feature->Description) len = strlenW( feature->Description );
else len = 0;
if (*help_len <= len)
{
*help_len = len;
if (help) r = ERROR_MORE_DATA;
}
else if (help)
{
if (feature->Description) strcpyW( help, feature->Description );
else *help = 0;
*help_len = len;
}
}
return r;
}
/***********************************************************************
* MsiGetFeatureInfoW (MSI.@)
*/
UINT WINAPI MsiGetFeatureInfoW( MSIHANDLE handle, LPCWSTR feature, LPDWORD attrs,
LPWSTR title, LPDWORD title_len, LPWSTR help, LPDWORD help_len )
{
UINT r;
MSIPACKAGE *package;
TRACE("%u, %s, %p, %p, %p, %p, %p\n", handle, debugstr_w(feature), attrs, title,
title_len, help, help_len);
if (!feature) return ERROR_INVALID_PARAMETER;
if (!(package = msihandle2msiinfo( handle, MSIHANDLETYPE_PACKAGE )))
return ERROR_INVALID_HANDLE;
/* features may not have been loaded yet */
msi_load_all_components( package );
msi_load_all_features( package );
r = MSI_GetFeatureInfo( package, feature, attrs, title, title_len, help, help_len );
msiobj_release( &package->hdr );
return r;
}
/*********************************************************************** /***********************************************************************
* MsiSetComponentStateA (MSI.@) * MsiSetComponentStateA (MSI.@)
*/ */

View File

@ -48,8 +48,8 @@
52 stdcall MsiGetDatabaseState(long) 52 stdcall MsiGetDatabaseState(long)
53 stdcall MsiGetFeatureCostA(long str long long ptr) 53 stdcall MsiGetFeatureCostA(long str long long ptr)
54 stdcall MsiGetFeatureCostW(long wstr long long ptr) 54 stdcall MsiGetFeatureCostW(long wstr long long ptr)
55 stub MsiGetFeatureInfoA 55 stdcall MsiGetFeatureInfoA(long str ptr ptr ptr ptr ptr)
56 stub MsiGetFeatureInfoW 56 stdcall MsiGetFeatureInfoW(long wstr ptr ptr ptr ptr ptr)
57 stdcall MsiGetFeatureStateA(long str ptr ptr) 57 stdcall MsiGetFeatureStateA(long str ptr ptr)
58 stdcall MsiGetFeatureStateW(long wstr ptr ptr) 58 stdcall MsiGetFeatureStateW(long wstr ptr ptr)
59 stdcall MsiGetFeatureUsageA(str str ptr ptr) 59 stdcall MsiGetFeatureUsageA(str str ptr ptr)

View File

@ -776,6 +776,8 @@ extern UINT msi_parse_command_line( MSIPACKAGE *package, LPCWSTR szCommandLine,
extern UINT msi_schedule_action( MSIPACKAGE *package, UINT script, const WCHAR *action ) DECLSPEC_HIDDEN; extern UINT msi_schedule_action( MSIPACKAGE *package, UINT script, const WCHAR *action ) DECLSPEC_HIDDEN;
extern INSTALLSTATE msi_get_component_action( MSIPACKAGE *package, MSICOMPONENT *comp ) DECLSPEC_HIDDEN; extern INSTALLSTATE msi_get_component_action( MSIPACKAGE *package, MSICOMPONENT *comp ) DECLSPEC_HIDDEN;
extern INSTALLSTATE msi_get_feature_action( MSIPACKAGE *package, MSIFEATURE *feature ) DECLSPEC_HIDDEN; extern INSTALLSTATE msi_get_feature_action( MSIPACKAGE *package, MSIFEATURE *feature ) DECLSPEC_HIDDEN;
extern UINT msi_load_all_components( MSIPACKAGE *package ) DECLSPEC_HIDDEN;
extern UINT msi_load_all_features( MSIPACKAGE *package ) DECLSPEC_HIDDEN;
/* record internals */ /* record internals */
extern void MSI_CloseRecord( MSIOBJECTHDR * ) DECLSPEC_HIDDEN; extern void MSI_CloseRecord( MSIOBJECTHDR * ) DECLSPEC_HIDDEN;

View File

@ -6386,6 +6386,89 @@ static void test_upgrade_code(void)
DeleteFile(msifile); DeleteFile(msifile);
} }
static void test_MsiGetFeatureInfo(void)
{
UINT r;
MSIHANDLE package;
char title[32], help[32], path[MAX_PATH];
DWORD attrs, title_len, help_len;
if (is_process_limited())
{
skip("process is limited\n");
return;
}
create_database( msifile, tables, sizeof(tables) / sizeof(tables[0]) );
strcpy( path, CURR_DIR );
strcat( path, "\\" );
strcat( path, msifile );
r = MsiOpenPackage( path, &package );
if (r == ERROR_INSTALL_PACKAGE_REJECTED)
{
skip("Not enough rights to perform tests\n");
DeleteFileA( msifile );
return;
}
ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
r = MsiGetFeatureInfoA( 0, NULL, NULL, NULL, NULL, NULL, NULL );
ok(r == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", r);
r = MsiGetFeatureInfoA( package, NULL, NULL, NULL, NULL, NULL, NULL );
ok(r == ERROR_INVALID_PARAMETER, "expected ERROR_INVALID_PARAMETER, got %u\n", r);
r = MsiGetFeatureInfoA( package, "", NULL, NULL, NULL, NULL, NULL );
ok(r == ERROR_UNKNOWN_FEATURE, "expected ERROR_UNKNOWN_FEATURE, got %u\n", r);
r = MsiGetFeatureInfoA( package, "One", NULL, NULL, NULL, NULL, NULL );
ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
r = MsiGetFeatureInfoA( 0, "One", NULL, NULL, NULL, NULL, NULL );
ok(r == ERROR_INVALID_HANDLE, "expected ERROR_INVALID_HANDLE, got %u\n", r);
title_len = help_len = 0;
r = MsiGetFeatureInfoA( package, "One", NULL, NULL, &title_len, NULL, &help_len );
ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
ok(title_len == 3, "expected 3, got %u\n", title_len);
ok(help_len == 15, "expected 15, got %u\n", help_len);
title[0] = help[0] = 0;
title_len = help_len = 0;
r = MsiGetFeatureInfoA( package, "One", NULL, title, &title_len, help, &help_len );
ok(r == ERROR_MORE_DATA, "expected ERROR_MORE_DATA, got %u\n", r);
ok(title_len == 3, "expected 3, got %u\n", title_len);
ok(help_len == 15, "expected 15, got %u\n", help_len);
attrs = 0;
title[0] = help[0] = 0;
title_len = sizeof(title);
help_len = sizeof(help);
r = MsiGetFeatureInfoA( package, "One", &attrs, title, &title_len, help, &help_len );
ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
ok(attrs == INSTALLFEATUREATTRIBUTE_FAVORLOCAL, "expected INSTALLFEATUREATTRIBUTE_FAVORLOCAL, got %u\n", attrs);
ok(title_len == 3, "expected 3, got %u\n", title_len);
ok(help_len == 15, "expected 15, got %u\n", help_len);
ok(!strcmp(title, "One"), "expected \"One\", got \"%s\"\n", title);
ok(!strcmp(help, "The One Feature"), "expected \"The One Feature\", got \"%s\"\n", help);
attrs = 0;
title[0] = help[0] = 0;
title_len = sizeof(title);
help_len = sizeof(help);
r = MsiGetFeatureInfoA( package, "feature", &attrs, title, &title_len, help, &help_len );
ok(r == ERROR_SUCCESS, "expected ERROR_SUCCESS, got %u\n", r);
ok(attrs == INSTALLFEATUREATTRIBUTE_FAVORLOCAL, "expected INSTALLFEATUREATTRIBUTE_FAVORLOCAL, got %u\n", attrs);
ok(!title_len, "expected 0, got %u\n", title_len);
ok(!help_len, "expected 0, got %u\n", help_len);
ok(!title[0], "expected \"\", got \"%s\"\n", title);
ok(!help[0], "expected \"\", got \"%s\"\n", help);
MsiCloseHandle( package );
DeleteFileA( msifile );
}
START_TEST(install) START_TEST(install)
{ {
DWORD len; DWORD len;
@ -6475,6 +6558,7 @@ START_TEST(install)
test_package_validation(); test_package_validation();
test_command_line_parsing(); test_command_line_parsing();
test_upgrade_code(); test_upgrade_code();
test_MsiGetFeatureInfo();
DeleteFileA(log_file); DeleteFileA(log_file);

View File

@ -207,6 +207,16 @@ typedef enum tagMSICODE
MSICODE_PATCH = 0x40000000L MSICODE_PATCH = 0x40000000L
} MSICODE; } MSICODE;
typedef enum tagINSTALLFEATUREATTRIBUTE
{
INSTALLFEATUREATTRIBUTE_FAVORLOCAL = 1 << 0,
INSTALLFEATUREATTRIBUTE_FAVORSOURCE = 1 << 1,
INSTALLFEATUREATTRIBUTE_FOLLOWPARENT = 1 << 2,
INSTALLFEATUREATTRIBUTE_FAVORADVERTISE = 1 << 3,
INSTALLFEATUREATTRIBUTE_DISALLOWADVERTISE = 1 << 4,
INSTALLFEATUREATTRIBUTE_NOUNSUPPORTEDADVERTISE = 1 << 5
} INSTALLFEATUREATTRIBUTE;
typedef struct _MSIFILEHASHINFO { typedef struct _MSIFILEHASHINFO {
ULONG dwFileHashInfoSize; ULONG dwFileHashInfoSize;
ULONG dwData[4]; ULONG dwData[4];
@ -523,6 +533,10 @@ INSTALLSTATE WINAPI MsiQueryFeatureStateA(LPCSTR, LPCSTR);
INSTALLSTATE WINAPI MsiQueryFeatureStateW(LPCWSTR, LPCWSTR); INSTALLSTATE WINAPI MsiQueryFeatureStateW(LPCWSTR, LPCWSTR);
#define MsiQueryFeatureState WINELIB_NAME_AW(MsiQueryFeatureState) #define MsiQueryFeatureState WINELIB_NAME_AW(MsiQueryFeatureState)
UINT WINAPI MsiGetFeatureInfoA(MSIHANDLE, LPCSTR, LPDWORD, LPSTR, LPDWORD, LPSTR, LPDWORD);
UINT WINAPI MsiGetFeatureInfoW(MSIHANDLE, LPCWSTR, LPDWORD, LPWSTR, LPDWORD, LPWSTR, LPDWORD);
#define MsiGetFeatureInfo WINELIB_NAME_AW(MsiGetFeatureInfo)
UINT WINAPI MsiGetFeatureUsageA(LPCSTR, LPCSTR, LPDWORD, LPWORD); UINT WINAPI MsiGetFeatureUsageA(LPCSTR, LPCSTR, LPDWORD, LPWORD);
UINT WINAPI MsiGetFeatureUsageW(LPCWSTR, LPCWSTR, LPDWORD, LPWORD); UINT WINAPI MsiGetFeatureUsageW(LPCWSTR, LPCWSTR, LPDWORD, LPWORD);
#define MsiGetFeatureUsage WINELIB_NAME_AW(MsiGetFeatureUsage) #define MsiGetFeatureUsage WINELIB_NAME_AW(MsiGetFeatureUsage)