aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBob Arnson <bob@firegiant.com>2023-04-24 22:16:34 -0400
committerRob Mensching <rob@firegiant.com>2023-06-03 01:24:39 -0700
commit1da29b425658bf1ddc774154d9bccaf940d0bc66 (patch)
treedda1d3320b8d855b3840e49b37d84d542b6824b7
parent29146461effb7798e054aa9933a88f612237df47 (diff)
downloadwix-1da29b425658bf1ddc774154d9bccaf940d0bc66.tar.gz
wix-1da29b425658bf1ddc774154d9bccaf940d0bc66.tar.bz2
wix-1da29b425658bf1ddc774154d9bccaf940d0bc66.zip
Fix WcaErrorMessage `cArgs==-1` case.
- Count args before creating message record. - Document terminating NULL requirement. - Add terminating NULL in MessageExit* macros. - Enhance tests for problems encountered fixing this nightmare. Fixes https://github.com/wixtoolset/issues/issues/7422. Fixes https://github.com/wixtoolset/issues/issues/7444.
-rw-r--r--src/libs/wcautil/WixToolset.WcaUtil/inc/wcautil.h6
-rw-r--r--src/libs/wcautil/WixToolset.WcaUtil/wcawrap.cpp33
-rw-r--r--src/test/burn/WixTestTools/MSIExec.cs2
-rw-r--r--src/test/msi/TestData/UtilExtensionUserTests/ProductNonVitalUserGroup/NonVitalUserGroup.wxs2
4 files changed, 26 insertions, 17 deletions
diff --git a/src/libs/wcautil/WixToolset.WcaUtil/inc/wcautil.h b/src/libs/wcautil/WixToolset.WcaUtil/inc/wcautil.h
index 9b331b34..b72c8d3f 100644
--- a/src/libs/wcautil/WixToolset.WcaUtil/inc/wcautil.h
+++ b/src/libs/wcautil/WixToolset.WcaUtil/inc/wcautil.h
@@ -15,9 +15,9 @@ extern "C" {
15 15
16#include "dutil.h" 16#include "dutil.h"
17 17
18#define MessageExitOnLastErrorSource(d, x, e, s, ...) { x = ::GetLastError(); x = HRESULT_FROM_WIN32(x); if (FAILED(x)) { ExitTraceSource(d, x, s, __VA_ARGS__); WcaErrorMessage(e, x, MB_OK, -1, __VA_ARGS__); goto LExit; } } 18#define MessageExitOnLastErrorSource(d, x, e, s, ...) { x = ::GetLastError(); x = HRESULT_FROM_WIN32(x); if (FAILED(x)) { ExitTraceSource(d, x, s, __VA_ARGS__); WcaErrorMessage(e, x, MB_OK, -1, __VA_ARGS__, NULL); goto LExit; } }
19#define MessageExitOnFailureSource(d, x, e, s, ...) if (FAILED(x)) { ExitTraceSource(d, x, s, __VA_ARGS__); WcaErrorMessage(e, x, INSTALLMESSAGE_ERROR | MB_OK, -1, __VA_ARGS__); goto LExit; } 19#define MessageExitOnFailureSource(d, x, e, s, ...) if (FAILED(x)) { ExitTraceSource(d, x, s, __VA_ARGS__); WcaErrorMessage(e, x, INSTALLMESSAGE_ERROR | MB_OK, -1, __VA_ARGS__, NULL); goto LExit; }
20#define MessageExitOnNullWithLastErrorSource(d, p, x, e, s, ...) if (NULL == p) { x = ::GetLastError(); x = HRESULT_FROM_WIN32(x); if (!FAILED(x)) { x = E_FAIL; } ExitTraceSource(d, x, s, __VA_ARGS__); WcaErrorMessage(e, x, MB_OK, -1, __VA_ARGS__); goto LExit; } 20#define MessageExitOnNullWithLastErrorSource(d, p, x, e, s, ...) if (NULL == p) { x = ::GetLastError(); x = HRESULT_FROM_WIN32(x); if (!FAILED(x)) { x = E_FAIL; } ExitTraceSource(d, x, s, __VA_ARGS__); WcaErrorMessage(e, x, MB_OK, -1, __VA_ARGS__, NULL); goto LExit; }
21 21
22#define MessageExitOnLastError(x, e, s, ...) MessageExitOnLastErrorSource(DUTIL_SOURCE_DEFAULT, x, e, s, __VA_ARGS__) 22#define MessageExitOnLastError(x, e, s, ...) MessageExitOnLastErrorSource(DUTIL_SOURCE_DEFAULT, x, e, s, __VA_ARGS__)
23#define MessageExitOnFailure(x, e, s, ...) MessageExitOnFailureSource(DUTIL_SOURCE_DEFAULT, x, e, s, __VA_ARGS__) 23#define MessageExitOnFailure(x, e, s, ...) MessageExitOnFailureSource(DUTIL_SOURCE_DEFAULT, x, e, s, __VA_ARGS__)
diff --git a/src/libs/wcautil/WixToolset.WcaUtil/wcawrap.cpp b/src/libs/wcautil/WixToolset.WcaUtil/wcawrap.cpp
index 86b7602e..9259e97a 100644
--- a/src/libs/wcautil/WixToolset.WcaUtil/wcawrap.cpp
+++ b/src/libs/wcautil/WixToolset.WcaUtil/wcawrap.cpp
@@ -27,7 +27,9 @@ WcaErrorMessage() - sends an error message from the CustomAction using
27the Error table 27the Error table
28 28
29NOTE: Any and all var_args (...) must be WCHAR* 29NOTE: Any and all var_args (...) must be WCHAR*
30 If you pass -1 to cArgs the count will be determined 30 If you pass -1 to cArgs, the count will be determined by
31 looking for a trailing NULL argment. If you omit a terminating
32 NULL, the results are undefined and probably crashy.
31********************************************************************/ 33********************************************************************/
32extern "C" UINT __cdecl WcaErrorMessage( 34extern "C" UINT __cdecl WcaErrorMessage(
33 __in int iError, 35 __in int iError,
@@ -41,6 +43,22 @@ extern "C" UINT __cdecl WcaErrorMessage(
41 MSIHANDLE hRec = NULL; 43 MSIHANDLE hRec = NULL;
42 va_list args = NULL; 44 va_list args = NULL;
43 45
46 if (-1 == cArgs)
47 {
48 LPCWSTR wzArg = NULL;
49 va_list iter = NULL;
50
51 va_start(iter, cArgs);
52 cArgs = 0;
53
54 while (NULL != (wzArg = va_arg(iter, WCHAR*)) && L'\0' != *wzArg)
55 {
56 ++cArgs;
57 }
58
59 va_end(iter);
60 }
61
44 uiType |= INSTALLMESSAGE_ERROR; // ensure error type is set 62 uiType |= INSTALLMESSAGE_ERROR; // ensure error type is set
45 hRec = ::MsiCreateRecord(cArgs + 2); 63 hRec = ::MsiCreateRecord(cArgs + 2);
46 if (!hRec) 64 if (!hRec)
@@ -56,18 +74,6 @@ extern "C" UINT __cdecl WcaErrorMessage(
56 ExitOnFailure(HRESULT_FROM_WIN32(er), "failed to set hresult code into error message"); 74 ExitOnFailure(HRESULT_FROM_WIN32(er), "failed to set hresult code into error message");
57 75
58 va_start(args, cArgs); 76 va_start(args, cArgs);
59 if (-1 == cArgs)
60 {
61 LPCWSTR wzArg = NULL;
62 va_list iter = args;
63 cArgs = 0;
64
65 while (NULL != (wzArg = va_arg(iter, WCHAR*)) && L'\0' != *wzArg)
66 {
67 ++cArgs;
68 }
69 }
70
71 for (INT i = 0; i < cArgs; i++) 77 for (INT i = 0; i < cArgs; i++)
72 { 78 {
73 er = ::MsiRecordSetStringW(hRec, i + 3, va_arg(args, WCHAR*)); 79 er = ::MsiRecordSetStringW(hRec, i + 3, va_arg(args, WCHAR*));
@@ -76,6 +82,7 @@ extern "C" UINT __cdecl WcaErrorMessage(
76 va_end(args); 82 va_end(args);
77 83
78 er = WcaProcessMessage(static_cast<INSTALLMESSAGE>(uiType), hRec); 84 er = WcaProcessMessage(static_cast<INSTALLMESSAGE>(uiType), hRec);
85
79LExit: 86LExit:
80 if (args) 87 if (args)
81 { 88 {
diff --git a/src/test/burn/WixTestTools/MSIExec.cs b/src/test/burn/WixTestTools/MSIExec.cs
index 98f54c56..f8c73afc 100644
--- a/src/test/burn/WixTestTools/MSIExec.cs
+++ b/src/test/burn/WixTestTools/MSIExec.cs
@@ -111,7 +111,7 @@ namespace WixTestTools
111 this.ForceRestart = false; 111 this.ForceRestart = false;
112 this.PromptRestart = false; 112 this.PromptRestart = false;
113 this.LogFile = String.Empty; 113 this.LogFile = String.Empty;
114 this.LoggingOptions = MSIExecLoggingOptions.VOICEWARMUP; 114 this.LoggingOptions = MSIExecLoggingOptions.Log_All_Information | MSIExecLoggingOptions.Verbose_Output | MSIExecLoggingOptions.Extra_Debugging_Information; // `/l*vx`
115 this.OtherArguments = String.Empty; 115 this.OtherArguments = String.Empty;
116 } 116 }
117 117
diff --git a/src/test/msi/TestData/UtilExtensionUserTests/ProductNonVitalUserGroup/NonVitalUserGroup.wxs b/src/test/msi/TestData/UtilExtensionUserTests/ProductNonVitalUserGroup/NonVitalUserGroup.wxs
index 461648ee..7ab4bbe1 100644
--- a/src/test/msi/TestData/UtilExtensionUserTests/ProductNonVitalUserGroup/NonVitalUserGroup.wxs
+++ b/src/test/msi/TestData/UtilExtensionUserTests/ProductNonVitalUserGroup/NonVitalUserGroup.wxs
@@ -10,12 +10,14 @@
10 10
11 <Fragment> 11 <Fragment>
12 <util:Group Id="ShouldNotExist" Name="Should Not Exist" /> 12 <util:Group Id="ShouldNotExist" Name="Should Not Exist" />
13 <util:Group Id="AlsoShouldNotExist" Name="Also Should Not Exist" />
13 14
14 <Component Id="Component1" Guid="00030829-0000-0000-C000-000000000046" Directory="INSTALLFOLDER"> 15 <Component Id="Component1" Guid="00030829-0000-0000-C000-000000000046" Directory="INSTALLFOLDER">
15 <File Source="$(sys.SOURCEFILEPATH)" KeyPath="yes" /> 16 <File Source="$(sys.SOURCEFILEPATH)" KeyPath="yes" />
16 17
17 <util:User Id="CurrentUser" Name="[LogonUser]" Domain="[%USERDOMAIN]" RemoveOnUninstall="no" Vital="no"> 18 <util:User Id="CurrentUser" Name="[LogonUser]" Domain="[%USERDOMAIN]" RemoveOnUninstall="no" Vital="no">
18 <util:GroupRef Id="ShouldNotExist" /> 19 <util:GroupRef Id="ShouldNotExist" />
20 <util:GroupRef Id="AlsoShouldNotExist" />
19 </util:User> 21 </util:User>
20 </Component> 22 </Component>
21 </Fragment> 23 </Fragment>