[4/5] msi: Implement and test MsiGetFeatureInfo.
Hans Leidekker
hans at codeweavers.com
Fri Jun 10 03:13:34 CDT 2011
---
dlls/msi/action.c | 8 ++--
dlls/msi/install.c | 120 ++++++++++++++++++++++++++++++++++++++++++++++
dlls/msi/msi.spec | 4 +-
dlls/msi/msipriv.h | 2 +
dlls/msi/tests/install.c | 84 ++++++++++++++++++++++++++++++++
include/msi.h | 14 +++++
6 files changed, 226 insertions(+), 6 deletions(-)
diff --git a/dlls/msi/action.c b/dlls/msi/action.c
index 3f6eae7..437c8d9 100644
--- a/dlls/msi/action.c
+++ b/dlls/msi/action.c
@@ -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 );
diff --git a/dlls/msi/install.c b/dlls/msi/install.c
index 31ab558..6225281 100644
--- a/dlls/msi/install.c
+++ b/dlls/msi/install.c
@@ -1255,6 +1255,126 @@ UINT WINAPI MsiGetFeatureCostW(MSIHANDLE hInstall, LPCWSTR szFeature,
}
/***********************************************************************
+* 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.@)
*/
UINT WINAPI MsiSetComponentStateA(MSIHANDLE hInstall, LPCSTR szComponent,
diff --git a/dlls/msi/msi.spec b/dlls/msi/msi.spec
index 0fe2177..1008813 100644
--- a/dlls/msi/msi.spec
+++ b/dlls/msi/msi.spec
@@ -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)
diff --git a/dlls/msi/msipriv.h b/dlls/msi/msipriv.h
index 6e9c959..414b70c 100644
--- a/dlls/msi/msipriv.h
+++ b/dlls/msi/msipriv.h
@@ -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;
diff --git a/dlls/msi/tests/install.c b/dlls/msi/tests/install.c
index d54f923..81e1c1e 100644
--- a/dlls/msi/tests/install.c
+++ b/dlls/msi/tests/install.c
@@ -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);
diff --git a/include/msi.h b/include/msi.h
index 550ce95..5b7eff2 100644
--- a/include/msi.h
+++ b/include/msi.h
@@ -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)
--
1.7.4.1
More information about the wine-patches
mailing list