From: Sebastian Lackner sebastian@fds-team.de
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- Changes from staging version:
* use .cross.res extension for cross-compiled resource * use replace_extension() instead of defining a new function * use phony targets in the tests makefile so that the custom DLL is always built * enforce directory name the same way we do for other targets
aclocal.m4 | 25 +++++++++ configure | 18 +++++++ tools/make_makefiles | 11 +++- tools/makedep.c | 142 ++++++++++++++++++++++++++++++++++++++++++++++++++- 4 files changed, 193 insertions(+), 3 deletions(-)
diff --git a/aclocal.m4 b/aclocal.m4 index 9364188..a711b20 100644 --- a/aclocal.m4 +++ b/aclocal.m4 @@ -540,6 +540,22 @@ $ac_dir/crosstest: __builddeps__ dummy fi }
+wine_fn_config_resource () +{ + ac_dir=$[1] + ac_name=$[2] + ac_flags=$[3] + + ac_clean= + test -n "$CROSSTARGET" && ac_clean=`expr $ac_dir/$ac_name : "\(.*\)\."`_crossres.`expr $ac_name : ".*\.\(.*\)"` + test -n "$DLLEXT" || ac_clean="$ac_dir/$ac_name" + + AS_VAR_IF([enable_tests],[no],[wine_fn_disabled_rules $ac_clean; return]) + + wine_fn_append_file SUBDIRS $ac_dir + wine_fn_clean_rules $ac_clean +} + wine_fn_config_tool () { ac_dir=$[1] @@ -643,6 +659,15 @@ wine_fn_config_test $1 ac_name[]ac_suffix [$2]dnl m4_popdef([ac_suffix])dnl m4_popdef([ac_name])])
+dnl **** Create a test resource makefile from config.status **** +dnl +dnl Usage: WINE_CONFIG_RESOURCE(dir,flags) +dnl +AC_DEFUN([WINE_CONFIG_RESOURCE],[AC_REQUIRE([WINE_CONFIG_HELPERS])dnl +m4_pushdef([ac_name],[m4_bpatsubst([$1],[.*/([^/]*)$],[\1])])dnl +wine_fn_config_resource $1 ac_name [$2]dnl +m4_popdef([ac_name])]) + dnl **** Create a static lib makefile from config.status **** dnl dnl Usage: WINE_CONFIG_LIB(name,flags) diff --git a/configure b/configure index 83f9b30..8ad89bd 100755 --- a/configure +++ b/configure @@ -8036,6 +8036,24 @@ $ac_dir/crosstest: __builddeps__ dummy fi }
+wine_fn_config_resource () +{ + ac_dir=$1 + ac_name=$2 + ac_flags=$3 + + ac_clean= + test -n "$CROSSTARGET" && ac_clean=`expr $ac_dir/$ac_name : "\(.*\)\."`_crossres.`expr $ac_name : ".*\.\(.*\)"` + test -n "$DLLEXT" || ac_clean="$ac_dir/$ac_name" + + if test "x$enable_tests" = xno; then : + wine_fn_disabled_rules $ac_clean; return +fi + + wine_fn_append_file SUBDIRS $ac_dir + wine_fn_clean_rules $ac_clean +} + wine_fn_config_tool () { ac_dir=$1 diff --git a/tools/make_makefiles b/tools/make_makefiles index f57a7e2..44f0fc2 100755 --- a/tools/make_makefiles +++ b/tools/make_makefiles @@ -224,7 +224,7 @@ sub parse_makefile($) { die "Configure substitution is not allowed in $file" unless $file eq "Makefile"; } - if (/^\s*(MODULE|IMPORTLIB|TESTDLL|PARENTSRC|APPMODE)\s*=\s*(.*)/) + if (/^\s*(MODULE|IMPORTLIB|TESTDLL|RESOURCE|PARENTSRC|APPMODE)\s*=\s*(.*)/) { my $var = $1; $make{$var} = $2; @@ -466,6 +466,15 @@ sub update_makefiles(@) (my $dir = $file) =~ s/^(.*)/Makefile/$1/; push @lines, "WINE_CONFIG_TEST($dir$flag_args)\n"; } + elsif (defined($make{"RESOURCE"})) # test resource + { + die "MODULE should not be defined in $file" if defined $make{"MODULE"}; + die "STATICLIB should not be defined in $file" if defined $make{"STATICLIB"}; + (my $dir = $file) =~ s/^(.*)/Makefile/$1/; + (my $name = $dir) =~ s/^.*/(.*)$/$1/; + die "Invalid RESOURCE in $file" unless $make{"RESOURCE"} eq $name; + push @lines, "WINE_CONFIG_RESOURCE($dir$flag_args)\n"; + } elsif (defined($make{"MODULE"}) && $make{"MODULE"} =~ /.a$/) # import lib { die "MODULE should not be defined as static lib in $file" unless $file =~ /^dlls//; diff --git a/tools/makedep.c b/tools/makedep.c index ec339e0..afa061a 100644 --- a/tools/makedep.c +++ b/tools/makedep.c @@ -174,6 +174,7 @@ struct makefile const char *parent_dir; const char *module; const char *testdll; + const char *resource; const char *sharedlib; const char *staticlib; const char *staticimplib; @@ -2345,6 +2346,7 @@ static struct strarray output_sources( const struct makefile *make ) struct strarray includes = empty_strarray; struct strarray phony_targets = empty_strarray; struct strarray all_targets = empty_strarray; + struct strarray resource_dlls = get_expanded_make_var_array( make, "RC_DLLS" ); struct strarray install_rules[NB_INSTALL_RULES]; char *ldrpath_local = get_expanded_make_variable( make, "LDRPATH_LOCAL" ); char *ldrpath_install = get_expanded_make_variable( make, "LDRPATH_INSTALL" ); @@ -2642,7 +2644,7 @@ static struct strarray output_sources( const struct makefile *make ) } else { - int need_cross = make->testdll || + int need_cross = make->testdll || make->resource || (source->file->flags & FLAG_C_IMPLIB) || (make->module && make->staticlib);
@@ -2656,7 +2658,7 @@ static struct strarray output_sources( const struct makefile *make ) output_filenames( includes ); output_filenames( make->define_args ); output_filenames( extradefs ); - if (make->module || make->staticlib || make->sharedlib || make->testdll) + if (make->module || make->staticlib || make->sharedlib || make->testdll || make->resource) { output_filenames( dll_flags ); if (make->use_msvcrt) output_filenames( msvcrt_flags ); @@ -2710,6 +2712,66 @@ static struct strarray output_sources( const struct makefile *make ) output( "\n" ); }
+ /* rules for resource dlls, call Makefile in subdirectory */ + + if (resource_dlls.count) + { + for (i = 0; i < resource_dlls.count; i++) + { + output( ".PHONY: %s\n", resource_dlls.str[i] ); + output( "%s:\n", resource_dlls.str[i] ); + output( "\t@cd %s && $(MAKE) %s%s\n", resource_dlls.str[i], + resource_dlls.str[i], dll_ext ); + } + + output( "%s:", obj_dir_path( make, "resource_dlls.res" )); + for (i = 0; i < resource_dlls.count; i++) + output( " %s", resource_dlls.str[i] ); + output( "\n" ); + output( "\t(" ); + for (i = 0; i < resource_dlls.count; i++) + { + if (i != 0) output( "; \\n " ); + output( "echo "%s RCDATA %s/%s%s"", resource_dlls.str[i], + resource_dlls.str[i], resource_dlls.str[i], dll_ext ); + } + output( ") | %s -o $@\n", tools_path( make, "wrc" ) ); + strarray_add( &clean_files, "resource_dlls.res" ); + strarray_add( &object_files, "resource_dlls.res" ); + + if (crosstarget && (make->testdll || (make->module && make->staticlib))) + { + for (i = 0; i < resource_dlls.count; i++) + { + char *name = replace_extension( resource_dlls.str[i], ".dll", "_crossres.dll" ); + output( ".PHONY: %s/crossres\n", resource_dlls.str[i] ); + output( "%s/crossres:\n", resource_dlls.str[i] ); + output( "\t@cd %s && $(MAKE) %s\n", resource_dlls.str[i], name ); + free( name ); + } + + output( "%s:", obj_dir_path( make, "resource_dlls.cross.res" )); + for (i = 0; i < resource_dlls.count; i++) + { + char *name = replace_extension( resource_dlls.str[i], ".dll", "_crossres.dll" ); + output( " %s/crossres", resource_dlls.str[i] ); + free( name ); + } + output( "\n" ); + output( "\t(" ); + for (i = 0; i < resource_dlls.count; i++) + { + char *name = replace_extension( resource_dlls.str[i], ".dll", "_crossres.dll" ); + if (i != 0) output( "; \\n " ); + output( "echo "%s RCDATA %s/%s"", resource_dlls.str[i], resource_dlls.str[i], name ); + free( name ); + } + output( ") | %s -o $@\n", tools_path( make, "wrc" ) ); + strarray_add( &clean_files, "resource_dlls.cross.res" ); + strarray_add( &crossobj_files, "resource_dlls.cross.res" ); + } + } + if (make->module && !make->staticlib) { struct strarray all_libs = empty_strarray; @@ -3101,6 +3163,81 @@ static struct strarray output_sources( const struct makefile *make ) add_install_rule( make, install_rules, make->scripts.str[i], make->scripts.str[i], strmake( "S$(bindir)/%s", make->scripts.str[i] ));
+ if (make->resource) + { + char *extra_wine_flags = get_expanded_make_variable( make, "WINEFLAGS" ); + char *extra_cross_flags = get_expanded_make_variable( make, "CROSSFLAGS" ); + struct strarray all_libs = empty_strarray; + char *module_path = obj_dir_path( make, make->resource ); + char *spec_file = NULL; + + if (!make->appmode.count) + spec_file = src_dir_path( make, replace_extension( make->resource, ".dll", ".spec" )); + for (i = 0; i < make->imports.count; i++) + strarray_add( &all_libs, strmake( "-l%s", make->imports.str[i] )); + strarray_addall( &all_libs, get_expanded_make_var_array( make, "LIBS" )); + + if (*dll_ext) + { + strarray_add( &all_targets, strmake( "%s%s", make->resource, dll_ext )); + strarray_add( &all_targets, strmake( "%s.fake", make->resource )); + output( "%s%s %s.fake:", module_path, dll_ext, module_path ); + } + else + { + strarray_add( &all_targets, make->resource ); + output( "%s:", module_path ); + } + if (spec_file) output_filename( spec_file ); + output_filenames_obj_dir( make, object_files ); + output_filenames_obj_dir( make, res_files ); + output( "\n" ); + output( "\t%s -o $@", tools_path( make, "winegcc" )); + output_filename( strmake( "-B%s", tools_dir_path( make, "winebuild" ))); + if (tools_dir) output_filename( strmake( "--sysroot=%s", top_obj_dir_path( make, "" ))); + output_filenames( target_flags ); + output_filenames( unwind_flags ); + if (spec_file) + { + output( " -shared %s", spec_file ); + output_filenames( make->extradllflags ); + } + else output_filenames( make->appmode ); + if (extra_wine_flags) output( " %s", extra_wine_flags ); + output_filenames_obj_dir( make, object_files ); + output_filenames_obj_dir( make, res_files ); + output_filenames( all_libs ); + output_filename( "$(LDFLAGS)" ); + output( "\n" ); + + if (crosstarget) + { + char *crossres = replace_extension( make->resource, ".dll", "_crossres.dll" ); + + strarray_add( &clean_files, crossres ); + output( "%s:", obj_dir_path( make, crossres )); + output_filenames_obj_dir( make, crossobj_files ); + output_filenames_obj_dir( make, res_files ); + output( "\n" ); + output( "\t%s -o $@ -b %s", tools_path( make, "winegcc" ), crosstarget ); + output_filename( strmake( "-B%s", tools_dir_path( make, "winebuild" ))); + if (tools_dir) output_filename( strmake( "--sysroot=%s", top_obj_dir_path( make, "" ))); + output_filename( "--lib-suffix=.cross.a" ); + if (spec_file) + { + output( " -shared %s", spec_file ); + output_filenames( make->extradllflags ); + } + else output_filenames( make->appmode ); + if (extra_cross_flags) output( " %s", extra_cross_flags ); + output_filenames_obj_dir( make, crossobj_files ); + output_filenames_obj_dir( make, res_files ); + output_filenames( all_libs ); + output_filename( "$(LDFLAGS)" ); + output( "\n" ); + } + } + if (!make->disabled) { if (all_targets.count) @@ -3476,6 +3613,7 @@ static void load_sources( struct makefile *make ) make->parent_dir = get_expanded_make_variable( make, "PARENTSRC" ); make->module = get_expanded_make_variable( make, "MODULE" ); make->testdll = get_expanded_make_variable( make, "TESTDLL" ); + make->resource = get_expanded_make_variable( make, "RESOURCE" ); make->sharedlib = get_expanded_make_variable( make, "SHAREDLIB" ); make->staticlib = get_expanded_make_variable( make, "STATICLIB" ); make->importlib = get_expanded_make_variable( make, "IMPORTLIB" );
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- configure | 1 + configure.ac | 1 + dlls/msi/tests/Makefile.in | 3 +++ dlls/msi/tests/custom.dll/Makefile.in | 4 ++++ dlls/msi/tests/custom.dll/custom.spec | 0 dlls/msi/tests/custom.dll/main.c | 26 ++++++++++++++++++++++++++ 6 files changed, 35 insertions(+) create mode 100644 dlls/msi/tests/custom.dll/Makefile.in create mode 100644 dlls/msi/tests/custom.dll/custom.spec create mode 100644 dlls/msi/tests/custom.dll/main.c
diff --git a/configure b/configure index 8ad89bd..483b1a3 100755 --- a/configure +++ b/configure @@ -18719,6 +18719,7 @@ wine_fn_config_dll mshtml enable_mshtml clean,implib wine_fn_config_test dlls/mshtml/tests mshtml_test clean wine_fn_config_dll msi enable_msi clean,implib wine_fn_config_test dlls/msi/tests msi_test +wine_fn_config_resource dlls/msi/tests/custom.dll custom.dll wine_fn_config_dll msident enable_msident clean wine_fn_config_dll msimg32 enable_msimg32 implib wine_fn_config_dll msimsg enable_msimsg diff --git a/configure.ac b/configure.ac index 22620ec..dd19098 100644 --- a/configure.ac +++ b/configure.ac @@ -3316,6 +3316,7 @@ WINE_CONFIG_DLL(mshtml,,[clean,implib]) WINE_CONFIG_TEST(dlls/mshtml/tests,[clean]) WINE_CONFIG_DLL(msi,,[clean,implib]) WINE_CONFIG_TEST(dlls/msi/tests) +WINE_CONFIG_RESOURCE(dlls/msi/tests/custom.dll) WINE_CONFIG_DLL(msident,,[clean]) WINE_CONFIG_DLL(msimg32,,[implib]) WINE_CONFIG_DLL(msimsg) diff --git a/dlls/msi/tests/Makefile.in b/dlls/msi/tests/Makefile.in index 66f8abb..fd3d9bd 100644 --- a/dlls/msi/tests/Makefile.in +++ b/dlls/msi/tests/Makefile.in @@ -13,3 +13,6 @@ C_SRCS = \ record.c \ source.c \ suminfo.c + +RC_DLLS = \ + custom.dll diff --git a/dlls/msi/tests/custom.dll/Makefile.in b/dlls/msi/tests/custom.dll/Makefile.in new file mode 100644 index 0000000..a711e4b --- /dev/null +++ b/dlls/msi/tests/custom.dll/Makefile.in @@ -0,0 +1,4 @@ +RESOURCE = custom.dll + +C_SRCS = \ + main.c diff --git a/dlls/msi/tests/custom.dll/custom.spec b/dlls/msi/tests/custom.dll/custom.spec new file mode 100644 index 0000000..e69de29 diff --git a/dlls/msi/tests/custom.dll/main.c b/dlls/msi/tests/custom.dll/main.c new file mode 100644 index 0000000..838b8ae --- /dev/null +++ b/dlls/msi/tests/custom.dll/main.c @@ -0,0 +1,26 @@ +/* + * DLL for testing type 1 custom actions + * + * Copyright 2017 Zebediah Figura + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, write to the Free Software + * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA + */ + +#include <windef.h> + +BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, void *reserved) +{ + return TRUE; +}
Hi,
While running your changed tests on Windows, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check? Full results can be found at https://testbot.winehq.org/JobDetails.pl?Key=35946
Your paranoid android.
=== w7u (32 bit msi) === The task timed out
=== w7u (32 bit install) === The task timed out
Signed-off-by: Hans Leidekker hans@codeweavers.com
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/msi/tests/custom.dll/Makefile.in | 1 + dlls/msi/tests/custom.dll/custom.spec | 1 + dlls/msi/tests/custom.dll/main.c | 17 ++++++ dlls/msi/tests/install.c | 100 ++++++++++++++++++++++++++++++++++ 4 files changed, 119 insertions(+)
diff --git a/dlls/msi/tests/custom.dll/Makefile.in b/dlls/msi/tests/custom.dll/Makefile.in index a711e4b..c606b22 100644 --- a/dlls/msi/tests/custom.dll/Makefile.in +++ b/dlls/msi/tests/custom.dll/Makefile.in @@ -1,4 +1,5 @@ RESOURCE = custom.dll +IMPORTS = msi
C_SRCS = \ main.c diff --git a/dlls/msi/tests/custom.dll/custom.spec b/dlls/msi/tests/custom.dll/custom.spec index e69de29..2a01b3d 100644 --- a/dlls/msi/tests/custom.dll/custom.spec +++ b/dlls/msi/tests/custom.dll/custom.spec @@ -0,0 +1 @@ +@ stdcall test_retval(long) diff --git a/dlls/msi/tests/custom.dll/main.c b/dlls/msi/tests/custom.dll/main.c index 838b8ae..7a970bf 100644 --- a/dlls/msi/tests/custom.dll/main.c +++ b/dlls/msi/tests/custom.dll/main.c @@ -18,9 +18,26 @@ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */
+#include <stdarg.h> +#include <stdio.h> + #include <windef.h> +#include <winbase.h> +#include <msi.h> +#include <msiquery.h>
BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, void *reserved) { return TRUE; } + +UINT WINAPI test_retval(MSIHANDLE hinst) +{ + char prop[10]; + DWORD len = sizeof(prop); + UINT retval; + + MsiGetPropertyA(hinst, "TEST_RETVAL", prop, &len); + sscanf(prop, "%u", &retval); + return retval; +} diff --git a/dlls/msi/tests/install.c b/dlls/msi/tests/install.c index 9d2a75b..cc1b536 100644 --- a/dlls/msi/tests/install.c +++ b/dlls/msi/tests/install.c @@ -70,6 +70,8 @@ static CHAR COMMON_FILES_DIR[MAX_PATH]; static CHAR APP_DATA_DIR[MAX_PATH]; static CHAR WINDOWS_DIR[MAX_PATH];
+static const char *customdll; + /* msi database data */
static const CHAR component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n" @@ -690,6 +692,16 @@ static const CHAR wrv_component_dat[] = "Component\tComponentId\tDirectory_\tAtt "Component\tComponent\n" "augustus\t\tMSITESTDIR\t0\t\taugustus\n";
+static const CHAR ca1_install_exec_seq_dat[] = "Action\tCondition\tSequence\n" + "s72\tS255\tI2\n" + "InstallExecuteSequence\tAction\n" + "testretval\t\t710\n"; + +static const CHAR ca1_custom_action_dat[] = "Action\tType\tSource\tTarget\n" + "s72\ti2\tS64\tS0\n" + "CustomAction\tAction\n" + "testretval\t1\tcustom.dll\ttest_retval\n"; + static const CHAR ca51_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n" "s72\tS38\ts72\ti2\tS255\tS72\n" "Component\tComponent\n" @@ -1689,6 +1701,13 @@ static const msi_table sf_tables[] = ADD_TABLE(property), };
+static const msi_table ca1_tables[] = +{ + ADD_TABLE(property), + ADD_TABLE(ca1_install_exec_seq), + ADD_TABLE(ca1_custom_action), +}; + static const msi_table ca51_tables[] = { ADD_TABLE(ca51_component), @@ -2595,6 +2614,29 @@ static LONG delete_key( HKEY key, LPCSTR subkey, REGSAM access ) return RegDeleteKeyA( key, subkey ); }
+static char *load_resource(const char *name) +{ + static char path[MAX_PATH]; + DWORD written; + HANDLE file; + HRSRC res; + void *ptr; + + GetTempFileNameA(".", name, 0, path); + + file = CreateFileA(path, GENERIC_READ|GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0); + ok(file != INVALID_HANDLE_VALUE, "file creation failed, at %s, error %d\n", path, GetLastError()); + + res = FindResourceA(NULL, name, (LPCSTR)RT_RCDATA); + ok( res != 0, "couldn't find resource\n" ); + ptr = LockResource( LoadResource( GetModuleHandleA(NULL), res )); + WriteFile( file, ptr, SizeofResource( GetModuleHandleA(NULL), res ), &written, NULL ); + ok( written == SizeofResource( GetModuleHandleA(NULL), res ), "couldn't write resource\n" ); + CloseHandle( file ); + + return path; +} + static void test_MsiInstallProduct(void) { UINT r; @@ -4020,6 +4062,59 @@ error: DeleteFileA("augustus"); }
+static void add_custom_dll(void) +{ + MSIHANDLE hdb = 0, record; + UINT res; + + res = MsiOpenDatabaseW(msifileW, MSIDBOPEN_TRANSACT, &hdb); + ok(res == ERROR_SUCCESS, "failed to open db: %u\n", res); + + res = run_query(hdb, 0, "CREATE TABLE `Binary` (`Name` CHAR(72) NOT NULL, `Data` OBJECT NOT NULL PRIMARY KEY `Name`)"); + ok(res == ERROR_SUCCESS, "failed to create Binary table: %u\n", res); + + record = MsiCreateRecord(1); + res = MsiRecordSetStreamA(record, 1, customdll); + ok(res == ERROR_SUCCESS, "failed to add %s to stream: %u\n", customdll, res); + + res = run_query(hdb, record, "INSERT INTO `Binary` (`Name`, `Data`) VALUES ('custom.dll', ?)"); + ok(res == ERROR_SUCCESS, "failed to insert into Binary table: %u\n", res); + + res = MsiDatabaseCommit(hdb); + ok(res == ERROR_SUCCESS, "failed to commit database: %u\n", res); + + MsiCloseHandle(record); + MsiCloseHandle(hdb); +} + +static void test_customaction1(void) +{ + UINT r; + + create_database(msifile, ca1_tables, sizeof(ca1_tables) / sizeof(msi_table)); + add_custom_dll(); + + MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL); + + r = MsiInstallProductA(msifile, "TEST_RETVAL=0"); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); + + r = MsiInstallProductA(msifile, "TEST_RETVAL=1626"); /* ERROR_FUNCTION_NOT_CALLED*/ + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); + + r = MsiInstallProductA(msifile, "TEST_RETVAL=1602"); + ok(r == ERROR_INSTALL_USEREXIT, "Expected ERROR_INSTALL_USEREXIT, got %u\n", r); + + r = MsiInstallProductA(msifile, "TEST_RETVAL=259"); /* ERROR_NO_MORE_ITEMS */ + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); + + /* any other error maps to ERROR_INSTALL_FAILURE */ + r = MsiInstallProductA(msifile, "TEST_RETVAL=1"); + ok(r == ERROR_INSTALL_FAILURE, "Expected ERROR_INSTALL_FAILURE, got %u\n", r); + + DeleteFileA(msifile); +} + static void test_customaction51(void) { UINT r; @@ -5996,6 +6091,8 @@ START_TEST(install) lstrcatA(log_file, "\msitest.log"); MsiEnableLogA(INSTALLLOGMODE_FATALEXIT, log_file, 0);
+ customdll = load_resource("custom.dll"); + if (pSRSetRestorePointA) /* test has side-effects on win2k3 that cause failures in following tests */ test_MsiInstallProduct(); test_MsiSetComponentState(); @@ -6015,6 +6112,7 @@ START_TEST(install) test_adminprops(); test_missingcab(); test_sourcefolder(); + test_customaction1(); test_customaction51(); test_installstate(); test_sourcepath(); @@ -6040,6 +6138,8 @@ START_TEST(install) test_feature_tree(); test_deferred_action();
+ DeleteFileA(customdll); + DeleteFileA(log_file);
if (pSRSetRestorePointA && !pMsiGetComponentPathExA && ret)
Signed-off-by: Hans Leidekker hans@codeweavers.com
For bug #18070.
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/msi/tests/custom.dll/Makefile.in | 2 +- dlls/msi/tests/custom.dll/custom.spec | 1 + dlls/msi/tests/custom.dll/main.c | 41 +++++++++++++++++++++++++++++++++++ dlls/msi/tests/install.c | 30 ++++++++++++++++++++++++- 4 files changed, 72 insertions(+), 2 deletions(-)
diff --git a/dlls/msi/tests/custom.dll/Makefile.in b/dlls/msi/tests/custom.dll/Makefile.in index c606b22..1e7babe 100644 --- a/dlls/msi/tests/custom.dll/Makefile.in +++ b/dlls/msi/tests/custom.dll/Makefile.in @@ -1,5 +1,5 @@ RESOURCE = custom.dll -IMPORTS = msi +IMPORTS = msi uuid ole32
C_SRCS = \ main.c diff --git a/dlls/msi/tests/custom.dll/custom.spec b/dlls/msi/tests/custom.dll/custom.spec index 2a01b3d..9d1e821 100644 --- a/dlls/msi/tests/custom.dll/custom.spec +++ b/dlls/msi/tests/custom.dll/custom.spec @@ -1 +1,2 @@ +@ stdcall main_test(long) @ stdcall test_retval(long) diff --git a/dlls/msi/tests/custom.dll/main.c b/dlls/msi/tests/custom.dll/main.c index 7a970bf..d174c6e 100644 --- a/dlls/msi/tests/custom.dll/main.c +++ b/dlls/msi/tests/custom.dll/main.c @@ -23,14 +23,55 @@
#include <windef.h> #include <winbase.h> +#define COBJMACROS +#include <objbase.h> +#include <unknwn.h> #include <msi.h> #include <msiquery.h>
+static void ok_(MSIHANDLE hinst, int todo, const char *file, int line, int condition, const char *msg, ...) +{ + static char buffer[2000]; + MSIHANDLE record; + va_list valist; + + va_start(valist, msg); + vsprintf(buffer, msg, valist); + va_end(valist); + + record = MsiCreateRecord(5); + MsiRecordSetInteger(record, 1, todo); + MsiRecordSetStringA(record, 2, file); + MsiRecordSetInteger(record, 3, line); + MsiRecordSetInteger(record, 4, condition); + MsiRecordSetStringA(record, 5, buffer); + MsiProcessMessage(hinst, INSTALLMESSAGE_USER, record); + MsiCloseHandle(record); +} +#define ok(hinst, condition, ...) ok_(hinst, 0, __FILE__, __LINE__, condition, __VA_ARGS__) +#define todo_wine_ok(hinst, condition, ...) ok_(hinst, 1, __FILE__, __LINE__, condition, __VA_ARGS__) + BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, void *reserved) { return TRUE; }
+/* Main test. Anything that doesn't depend on a specific install configuration + * or have undesired side effects should go here. */ +UINT WINAPI main_test(MSIHANDLE hinst) +{ + IUnknown *unk = NULL; + HRESULT hres; + + /* Test for an MTA apartment */ + hres = CoCreateInstance(&CLSID_Picture_Metafile, NULL, CLSCTX_INPROC_SERVER, &IID_IUnknown, (void **)&unk); + todo_wine_ok(hinst, hres == S_OK, "CoCreateInstance failed with %08x\n", hres); + + if (unk) IUnknown_Release(unk); + + return ERROR_SUCCESS; +} + UINT WINAPI test_retval(MSIHANDLE hinst) { char prop[10]; diff --git a/dlls/msi/tests/install.c b/dlls/msi/tests/install.c index cc1b536..118530f 100644 --- a/dlls/msi/tests/install.c +++ b/dlls/msi/tests/install.c @@ -695,11 +695,13 @@ static const CHAR wrv_component_dat[] = "Component\tComponentId\tDirectory_\tAtt static const CHAR ca1_install_exec_seq_dat[] = "Action\tCondition\tSequence\n" "s72\tS255\tI2\n" "InstallExecuteSequence\tAction\n" - "testretval\t\t710\n"; + "maintest\tMAIN_TEST\t700\n" + "testretval\tTEST_RETVAL\t710\n";
static const CHAR ca1_custom_action_dat[] = "Action\tType\tSource\tTarget\n" "s72\ti2\tS64\tS0\n" "CustomAction\tAction\n" + "maintest\t1\tcustom.dll\tmain_test\n" "testretval\t1\tcustom.dll\ttest_retval\n";
static const CHAR ca51_component_dat[] = "Component\tComponentId\tDirectory_\tAttributes\tCondition\tKeyPath\n" @@ -4087,6 +4089,27 @@ static void add_custom_dll(void) MsiCloseHandle(hdb); }
+static INT CALLBACK ok_callback(void *context, UINT message_type, MSIHANDLE record) +{ + if (message_type == INSTALLMESSAGE_USER) + { + char file[200]; + char msg[2000]; + DWORD len; + + len = sizeof(file); + MsiRecordGetStringA(record, 2, file, &len); + len = sizeof(msg); + MsiRecordGetStringA(record, 5, msg, &len); + + todo_wine_if(MsiRecordGetInteger(record, 1)) + ok_(file, MsiRecordGetInteger(record, 3)) (MsiRecordGetInteger(record, 4), "%s", msg); + + return 1; + } + return 0; +} + static void test_customaction1(void) { UINT r; @@ -4096,6 +4119,10 @@ static void test_customaction1(void)
MsiSetInternalUI(INSTALLUILEVEL_NONE, NULL);
+ r = MsiInstallProductA(msifile, "MAIN_TEST=1"); + ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r); + + /* Test return values */ r = MsiInstallProductA(msifile, "TEST_RETVAL=0"); ok(r == ERROR_SUCCESS, "Expected ERROR_SUCCESS, got %u\n", r);
@@ -6092,6 +6119,7 @@ START_TEST(install) MsiEnableLogA(INSTALLLOGMODE_FATALEXIT, log_file, 0);
customdll = load_resource("custom.dll"); + MsiSetExternalUIRecord(ok_callback, INSTALLLOGMODE_USER, NULL, NULL);
if (pSRSetRestorePointA) /* test has side-effects on win2k3 that cause failures in following tests */ test_MsiInstallProduct();
Signed-off-by: Hans Leidekker hans@codeweavers.com
Signed-off-by: Zebediah Figura z.figura12@gmail.com --- dlls/msi/tests/custom.dll/main.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/dlls/msi/tests/custom.dll/main.c b/dlls/msi/tests/custom.dll/main.c index d174c6e..3730e3a 100644 --- a/dlls/msi/tests/custom.dll/main.c +++ b/dlls/msi/tests/custom.dll/main.c @@ -60,6 +60,7 @@ BOOL WINAPI DllMain(HINSTANCE hinst, DWORD reason, void *reserved) * or have undesired side effects should go here. */ UINT WINAPI main_test(MSIHANDLE hinst) { + UINT res; IUnknown *unk = NULL; HRESULT hres;
@@ -69,6 +70,10 @@ UINT WINAPI main_test(MSIHANDLE hinst)
if (unk) IUnknown_Release(unk);
+ /* Test MsiGetDatabaseState() */ + res = MsiGetDatabaseState(hinst); + todo_wine_ok(hinst, res == MSIDBSTATE_ERROR, "expected MSIDBSTATE_ERROR, got %u\n", res); + return ERROR_SUCCESS; }
Signed-off-by: Hans Leidekker hans@codeweavers.com