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;
|
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 );
|
||||||
|
|
|
@ -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.@)
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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;
|
||||||
|
|
|
@ -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);
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
Loading…
Reference in New Issue