diff options
author | Bob Arnson <bob@firegiant.com> | 2023-04-24 22:16:34 -0400 |
---|---|---|
committer | Rob Mensching <rob@firegiant.com> | 2023-06-03 01:24:39 -0700 |
commit | 1da29b425658bf1ddc774154d9bccaf940d0bc66 (patch) | |
tree | dda1d3320b8d855b3840e49b37d84d542b6824b7 | |
parent | 29146461effb7798e054aa9933a88f612237df47 (diff) | |
download | wix-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.
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 | |||
27 | the Error table | 27 | the Error table |
28 | 28 | ||
29 | NOTE: Any and all var_args (...) must be WCHAR* | 29 | NOTE: 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 | ********************************************************************/ |
32 | extern "C" UINT __cdecl WcaErrorMessage( | 34 | extern "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 | |||
79 | LExit: | 86 | LExit: |
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> |