msi: Implement and test MsiGetFeatureInfo.
This commit is contained in:
parent
aec97287bc
commit
4c9c50d86b
|
@ -999,7 +999,7 @@ static UINT load_component( MSIRECORD *row, LPVOID param )
|
|||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
static UINT load_all_components( MSIPACKAGE *package )
|
||||
UINT msi_load_all_components( MSIPACKAGE *package )
|
||||
{
|
||||
static const WCHAR query[] = {
|
||||
'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;
|
||||
}
|
||||
|
||||
static UINT load_all_features( MSIPACKAGE *package )
|
||||
UINT msi_load_all_features( MSIPACKAGE *package )
|
||||
{
|
||||
static const WCHAR query[] = {
|
||||
'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 );
|
||||
|
||||
load_all_folders( package );
|
||||
load_all_components( package );
|
||||
load_all_features( package );
|
||||
msi_load_all_components( package );
|
||||
msi_load_all_features( package );
|
||||
load_all_files( package );
|
||||
load_all_patches( package );
|
||||
load_all_media( package );
|
||||
|
|
|
@ -1254,6 +1254,126 @@ UINT WINAPI MsiGetFeatureCostW(MSIHANDLE hInstall, LPCWSTR szFeature,
|
|||
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.@)
|
||||
*/
|
||||
|
|
|
@ -48,8 +48,8 @@
|
|||
52 stdcall MsiGetDatabaseState(long)
|
||||
53 stdcall MsiGetFeatureCostA(long str long long ptr)
|
||||
54 stdcall MsiGetFeatureCostW(long wstr long long ptr)
|
||||
55 stub MsiGetFeatureInfoA
|
||||
56 stub MsiGetFeatureInfoW
|
||||
55 stdcall MsiGetFeatureInfoA(long str ptr ptr ptr ptr ptr)
|
||||
56 stdcall MsiGetFeatureInfoW(long wstr ptr ptr ptr ptr ptr)
|
||||
57 stdcall MsiGetFeatureStateA(long str ptr ptr)
|
||||
58 stdcall MsiGetFeatureStateW(long wstr ptr ptr)
|
||||
59 stdcall MsiGetFeatureUsageA(str str ptr ptr)
|
||||
|
|
|
@ -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 INSTALLSTATE msi_get_component_action( MSIPACKAGE *package, MSICOMPONENT *comp ) 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 */
|
||||
extern void MSI_CloseRecord( MSIOBJECTHDR * ) DECLSPEC_HIDDEN;
|
||||
|
|
|
@ -6386,6 +6386,89 @@ static void test_upgrade_code(void)
|
|||
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)
|
||||
{
|
||||
DWORD len;
|
||||
|
@ -6475,6 +6558,7 @@ START_TEST(install)
|
|||
test_package_validation();
|
||||
test_command_line_parsing();
|
||||
test_upgrade_code();
|
||||
test_MsiGetFeatureInfo();
|
||||
|
||||
DeleteFileA(log_file);
|
||||
|
||||
|
|
|
@ -207,6 +207,16 @@ typedef enum tagMSICODE
|
|||
MSICODE_PATCH = 0x40000000L
|
||||
} 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 {
|
||||
ULONG dwFileHashInfoSize;
|
||||
ULONG dwData[4];
|
||||
|
@ -523,6 +533,10 @@ INSTALLSTATE WINAPI MsiQueryFeatureStateA(LPCSTR, LPCSTR);
|
|||
INSTALLSTATE WINAPI MsiQueryFeatureStateW(LPCWSTR, LPCWSTR);
|
||||
#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 MsiGetFeatureUsageW(LPCWSTR, LPCWSTR, LPDWORD, LPWORD);
|
||||
#define MsiGetFeatureUsage WINELIB_NAME_AW(MsiGetFeatureUsage)
|
||||
|
|
Loading…
Reference in New Issue