diff options
author | Rob Mensching <rob@firegiant.com> | 2021-12-02 19:57:44 -0800 |
---|---|---|
committer | Rob Mensching <rob@firegiant.com> | 2021-12-03 07:48:37 -0800 |
commit | fd5138896d596a6f3226a5c9438e456d4c8c2068 (patch) | |
tree | cb9c87dd0f8d36aaeff4a5bf882238018c043fcd /src | |
parent | 2c01f5fa3ac1e7be66b86561f32d2d1c220d7a8f (diff) | |
download | wix-fd5138896d596a6f3226a5c9438e456d4c8c2068.tar.gz wix-fd5138896d596a6f3226a5c9438e456d4c8c2068.tar.bz2 wix-fd5138896d596a6f3226a5c9438e456d4c8c2068.zip |
Handle unexpected BOM when reading from stdin in wixnative.exe
In certain cases, the encoding of stdin/stdout can be changed in
Windows to cause a BOM to be added on the first read of stdin.
To handle the unexpected BOM, the first line read from stdin is
now a "preamble" where the last character is expected to be a ":".
We use the last character because a multibyte BOM value may appear
before it.
Also updated SAL annotations to resolve IDE warnings.
Diffstat (limited to 'src')
-rw-r--r-- | src/wix/WixToolset.Core.Native/Cabinet.cs | 13 | ||||
-rw-r--r-- | src/wix/WixToolset.Core.Native/WixNativeExe.cs | 4 | ||||
-rw-r--r-- | src/wix/wixnative/extractcab.cpp | 8 | ||||
-rw-r--r-- | src/wix/wixnative/precomp.h | 10 | ||||
-rw-r--r-- | src/wix/wixnative/resetacls.cpp | 7 | ||||
-rw-r--r-- | src/wix/wixnative/smartcab.cpp | 16 | ||||
-rw-r--r-- | src/wix/wixnative/wixnative.cpp | 28 |
7 files changed, 57 insertions, 29 deletions
diff --git a/src/wix/WixToolset.Core.Native/Cabinet.cs b/src/wix/WixToolset.Core.Native/Cabinet.cs index 9b77bd37..e383d8fa 100644 --- a/src/wix/WixToolset.Core.Native/Cabinet.cs +++ b/src/wix/WixToolset.Core.Native/Cabinet.cs | |||
@@ -57,19 +57,6 @@ namespace WixToolset.Core.Native | |||
57 | } | 57 | } |
58 | 58 | ||
59 | wixnative.Run(); | 59 | wixnative.Run(); |
60 | |||
61 | #if TOOD_ERROR_HANDLING | ||
62 | catch (COMException ce) | ||
63 | { | ||
64 | // If we get a "the file exists" error, we must have a full temp directory - so report the issue | ||
65 | if (0x80070050 == unchecked((uint)ce.ErrorCode)) | ||
66 | { | ||
67 | throw new WixException(WixErrors.FullTempDirectory("WSC", Path.GetTempPath())); | ||
68 | } | ||
69 | |||
70 | throw; | ||
71 | } | ||
72 | #endif | ||
73 | } | 60 | } |
74 | 61 | ||
75 | /// <summary> | 62 | /// <summary> |
diff --git a/src/wix/WixToolset.Core.Native/WixNativeExe.cs b/src/wix/WixToolset.Core.Native/WixNativeExe.cs index 6e8d64ca..13d7a4ea 100644 --- a/src/wix/WixToolset.Core.Native/WixNativeExe.cs +++ b/src/wix/WixToolset.Core.Native/WixNativeExe.cs | |||
@@ -4,7 +4,6 @@ namespace WixToolset.Core.Native | |||
4 | { | 4 | { |
5 | using System; | 5 | using System; |
6 | using System.Collections.Generic; | 6 | using System.Collections.Generic; |
7 | using System.ComponentModel; | ||
8 | using System.Diagnostics; | 7 | using System.Diagnostics; |
9 | using System.IO; | 8 | using System.IO; |
10 | 9 | ||
@@ -54,6 +53,9 @@ namespace WixToolset.Core.Native | |||
54 | process.BeginOutputReadLine(); | 53 | process.BeginOutputReadLine(); |
55 | process.BeginErrorReadLine(); | 54 | process.BeginErrorReadLine(); |
56 | 55 | ||
56 | // Send the stdin preamble. | ||
57 | process.StandardInput.WriteLine(":"); | ||
58 | |||
57 | if (this.stdinLines.Count > 0) | 59 | if (this.stdinLines.Count > 0) |
58 | { | 60 | { |
59 | foreach (var line in this.stdinLines) | 61 | foreach (var line in this.stdinLines) |
diff --git a/src/wix/wixnative/extractcab.cpp b/src/wix/wixnative/extractcab.cpp index 53f53266..2de37992 100644 --- a/src/wix/wixnative/extractcab.cpp +++ b/src/wix/wixnative/extractcab.cpp | |||
@@ -2,12 +2,12 @@ | |||
2 | 2 | ||
3 | #include "precomp.h" | 3 | #include "precomp.h" |
4 | 4 | ||
5 | static HRESULT ProgressCallback(BOOL fBeginFile, LPCWSTR wzFileId, LPVOID pvContext); | 5 | static HRESULT ProgressCallback(__in BOOL fBeginFile, __in_z LPCWSTR wzFileId, __in_opt LPVOID pvContext); |
6 | 6 | ||
7 | 7 | ||
8 | HRESULT ExtractCabCommand( | 8 | HRESULT ExtractCabCommand( |
9 | __in int argc, | 9 | __in int argc, |
10 | __in LPWSTR argv[] | 10 | __in_ecount(argc) LPWSTR argv[] |
11 | ) | 11 | ) |
12 | { | 12 | { |
13 | HRESULT hr = E_INVALIDARG; | 13 | HRESULT hr = E_INVALIDARG; |
@@ -37,8 +37,8 @@ LExit: | |||
37 | 37 | ||
38 | static HRESULT ProgressCallback( | 38 | static HRESULT ProgressCallback( |
39 | __in BOOL fBeginFile, | 39 | __in BOOL fBeginFile, |
40 | __in LPCWSTR wzFileId, | 40 | __in_z LPCWSTR wzFileId, |
41 | __in LPVOID /*pvContext*/ | 41 | __in_opt LPVOID /*pvContext*/ |
42 | ) | 42 | ) |
43 | { | 43 | { |
44 | if (fBeginFile) | 44 | if (fBeginFile) |
diff --git a/src/wix/wixnative/precomp.h b/src/wix/wixnative/precomp.h index 5bd617e5..490bbdcf 100644 --- a/src/wix/wixnative/precomp.h +++ b/src/wix/wixnative/precomp.h | |||
@@ -4,6 +4,7 @@ | |||
4 | #include <windows.h> | 4 | #include <windows.h> |
5 | #include <aclapi.h> | 5 | #include <aclapi.h> |
6 | #include <mergemod.h> | 6 | #include <mergemod.h> |
7 | #include <strsafe.h> | ||
7 | 8 | ||
8 | #include "dutil.h" | 9 | #include "dutil.h" |
9 | #include "conutil.h" | 10 | #include "conutil.h" |
@@ -13,7 +14,8 @@ | |||
13 | #include "cabcutil.h" | 14 | #include "cabcutil.h" |
14 | #include "cabutil.h" | 15 | #include "cabutil.h" |
15 | 16 | ||
16 | HRESULT SmartCabCommand(int argc, LPWSTR argv[]); | 17 | HRESULT WixNativeReadStdinPreamble(); |
17 | HRESULT ResetAclsCommand(int argc, LPWSTR argv[]); | 18 | HRESULT SmartCabCommand(__in int argc, __in_ecount(argc) LPWSTR argv[]); |
18 | HRESULT EnumCabCommand(int argc, LPWSTR argv[]); | 19 | HRESULT ResetAclsCommand(__in int argc, __in_ecount(argc) LPWSTR argv[]); |
19 | HRESULT ExtractCabCommand(int argc, LPWSTR argv[]); | 20 | HRESULT EnumCabCommand(__in int argc, __in_ecount(argc) LPWSTR argv[]); |
21 | HRESULT ExtractCabCommand(__in int argc, __in_ecount(argc) LPWSTR argv[]); | ||
diff --git a/src/wix/wixnative/resetacls.cpp b/src/wix/wixnative/resetacls.cpp index 8c5bdc56..91bc633d 100644 --- a/src/wix/wixnative/resetacls.cpp +++ b/src/wix/wixnative/resetacls.cpp | |||
@@ -2,7 +2,9 @@ | |||
2 | 2 | ||
3 | #include "precomp.h" | 3 | #include "precomp.h" |
4 | 4 | ||
5 | HRESULT ResetAclsCommand(int argc, LPWSTR argv[]) | 5 | HRESULT ResetAclsCommand( |
6 | __in int argc, | ||
7 | __in_ecount(argc) LPWSTR argv[]) | ||
6 | { | 8 | { |
7 | Unused(argc); | 9 | Unused(argc); |
8 | Unused(argv); | 10 | Unused(argv); |
@@ -24,6 +26,9 @@ HRESULT ResetAclsCommand(int argc, LPWSTR argv[]) | |||
24 | ConsoleExitOnLastError(hr, CONSOLE_COLOR_RED, "failed to initialize ACL"); | 26 | ConsoleExitOnLastError(hr, CONSOLE_COLOR_RED, "failed to initialize ACL"); |
25 | } | 27 | } |
26 | 28 | ||
29 | hr = WixNativeReadStdinPreamble(); | ||
30 | ExitOnFailure(hr, "failed to read stdin preamble before resetting ACLs"); | ||
31 | |||
27 | // Reset the existing security permissions on each provided file. | 32 | // Reset the existing security permissions on each provided file. |
28 | for (;;) | 33 | for (;;) |
29 | { | 34 | { |
diff --git a/src/wix/wixnative/smartcab.cpp b/src/wix/wixnative/smartcab.cpp index 0dff6c94..1483dfe8 100644 --- a/src/wix/wixnative/smartcab.cpp +++ b/src/wix/wixnative/smartcab.cpp | |||
@@ -1,14 +1,15 @@ | |||
1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. | 1 | // Copyright (c) .NET Foundation and contributors. All rights reserved. Licensed under the Microsoft Reciprocal License. See LICENSE.TXT file in the project root for full license information. |
2 | 2 | ||
3 | #include "precomp.h" | 3 | #include "precomp.h" |
4 | #include "fileutil.h" | ||
4 | 5 | ||
5 | static HRESULT CompressFiles(HANDLE hCab); | 6 | static HRESULT CompressFiles(__in HANDLE hCab); |
6 | static void __stdcall CabNamesCallback(LPWSTR wzFirstCabName, LPWSTR wzNewCabName, LPWSTR wzFileToken); | 7 | static void __stdcall CabNamesCallback(__in_z LPWSTR wzFirstCabName, __in_z LPWSTR wzNewCabName, __in_z LPWSTR wzFileToken); |
7 | 8 | ||
8 | 9 | ||
9 | HRESULT SmartCabCommand( | 10 | HRESULT SmartCabCommand( |
10 | __in int argc, | 11 | __in int argc, |
11 | __in LPWSTR argv[] | 12 | __in_ecount(argc) LPWSTR argv[] |
12 | ) | 13 | ) |
13 | { | 14 | { |
14 | HRESULT hr = E_INVALIDARG; | 15 | HRESULT hr = E_INVALIDARG; |
@@ -66,6 +67,9 @@ HRESULT SmartCabCommand( | |||
66 | 67 | ||
67 | if (uiFileCount > 0) | 68 | if (uiFileCount > 0) |
68 | { | 69 | { |
70 | hr = WixNativeReadStdinPreamble(); | ||
71 | ExitOnFailure(hr, "failed to read stdin preamble before smartcabbing"); | ||
72 | |||
69 | hr = CompressFiles(hCab); | 73 | hr = CompressFiles(hCab); |
70 | ExitOnFailure(hr, "failed to compress files into cabinet: %ls", wzCabPath); | 74 | ExitOnFailure(hr, "failed to compress files into cabinet: %ls", wzCabPath); |
71 | } | 75 | } |
@@ -151,9 +155,9 @@ LExit: | |||
151 | // Second argument is name of the new cabinet that would be formed by splitting e.g. "cab1b.cab" | 155 | // Second argument is name of the new cabinet that would be formed by splitting e.g. "cab1b.cab" |
152 | // Third argument is the file token of the first file present in the splitting cabinet | 156 | // Third argument is the file token of the first file present in the splitting cabinet |
153 | static void __stdcall CabNamesCallback( | 157 | static void __stdcall CabNamesCallback( |
154 | __in LPWSTR wzFirstCabName, | 158 | __in_z LPWSTR wzFirstCabName, |
155 | __in LPWSTR wzNewCabName, | 159 | __in_z LPWSTR wzNewCabName, |
156 | __in LPWSTR wzFileToken | 160 | __in_z LPWSTR wzFileToken |
157 | ) | 161 | ) |
158 | { | 162 | { |
159 | ConsoleWriteLine(CONSOLE_COLOR_NORMAL, "%ls\t%ls\t%ls", wzFirstCabName, wzNewCabName, wzFileToken); | 163 | ConsoleWriteLine(CONSOLE_COLOR_NORMAL, "%ls\t%ls\t%ls", wzFirstCabName, wzNewCabName, wzFileToken); |
diff --git a/src/wix/wixnative/wixnative.cpp b/src/wix/wixnative/wixnative.cpp index 7bd8dbca..d1236da1 100644 --- a/src/wix/wixnative/wixnative.cpp +++ b/src/wix/wixnative/wixnative.cpp | |||
@@ -36,3 +36,31 @@ int __cdecl wmain(int argc, LPWSTR argv[]) | |||
36 | ConsoleUninitialize(); | 36 | ConsoleUninitialize(); |
37 | return HRESULT_CODE(hr); | 37 | return HRESULT_CODE(hr); |
38 | } | 38 | } |
39 | |||
40 | HRESULT WixNativeReadStdinPreamble() | ||
41 | { | ||
42 | HRESULT hr = S_OK; | ||
43 | LPWSTR sczLine = NULL; | ||
44 | size_t cchPreamble = 0; | ||
45 | |||
46 | // Read the first line to determine if a byte-order-mark was prepended to stdin. | ||
47 | // A byte-order-mark is not normally expected but has been seen in some CI/CD systems. | ||
48 | // The preable is a single line with ":". | ||
49 | hr = ConsoleReadW(&sczLine); | ||
50 | ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "failed to read preamble from stdin"); | ||
51 | |||
52 | hr = ::StringCchLengthW(sczLine, STRSAFE_MAX_CCH, &cchPreamble); | ||
53 | ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "failed to get length of stdin preamble"); | ||
54 | |||
55 | // Ensure the preamble ends with ":" and ignore anything before that (since it may be a BOM). | ||
56 | if (!cchPreamble || sczLine[cchPreamble - 1] != L':') | ||
57 | { | ||
58 | hr = E_INVALIDDATA; | ||
59 | ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "expected ':' as preamble on first line of stdin"); | ||
60 | } | ||
61 | |||
62 | LExit: | ||
63 | ReleaseStr(sczLine); | ||
64 | |||
65 | return hr; | ||
66 | } | ||