diff options
| author | Bob Arnson <bob@firegiant.com> | 2023-04-24 22:16:34 -0400 |
|---|---|---|
| committer | Bob Arnson <github@bobs.org> | 2023-04-27 11:07:23 -0400 |
| commit | b3b9decfab8a26851e2bc85d777824220ff804b6 (patch) | |
| tree | 8c05f1c2c64ca54c91811069468487b5d4a788b2 /src | |
| parent | 3c40f43c76d44787bfc1602cb7d95ea3a0787748 (diff) | |
| download | wix-b3b9decfab8a26851e2bc85d777824220ff804b6.tar.gz wix-b3b9decfab8a26851e2bc85d777824220ff804b6.tar.bz2 wix-b3b9decfab8a26851e2bc85d777824220ff804b6.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.
Diffstat (limited to 'src')
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> |
