aboutsummaryrefslogtreecommitdiff
path: root/src/libs/wcautil
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 /src/libs/wcautil
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.
Diffstat (limited to 'src/libs/wcautil')
-rw-r--r--src/libs/wcautil/WixToolset.WcaUtil/inc/wcautil.h6
-rw-r--r--src/libs/wcautil/WixToolset.WcaUtil/wcawrap.cpp33
2 files changed, 23 insertions, 16 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 {