aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRob Mensching <rob@firegiant.com>2021-12-02 19:57:44 -0800
committerRob Mensching <rob@firegiant.com>2021-12-03 07:48:37 -0800
commitfd5138896d596a6f3226a5c9438e456d4c8c2068 (patch)
treecb9c87dd0f8d36aaeff4a5bf882238018c043fcd /src
parent2c01f5fa3ac1e7be66b86561f32d2d1c220d7a8f (diff)
downloadwix-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.cs13
-rw-r--r--src/wix/WixToolset.Core.Native/WixNativeExe.cs4
-rw-r--r--src/wix/wixnative/extractcab.cpp8
-rw-r--r--src/wix/wixnative/precomp.h10
-rw-r--r--src/wix/wixnative/resetacls.cpp7
-rw-r--r--src/wix/wixnative/smartcab.cpp16
-rw-r--r--src/wix/wixnative/wixnative.cpp28
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
5static HRESULT ProgressCallback(BOOL fBeginFile, LPCWSTR wzFileId, LPVOID pvContext); 5static HRESULT ProgressCallback(__in BOOL fBeginFile, __in_z LPCWSTR wzFileId, __in_opt LPVOID pvContext);
6 6
7 7
8HRESULT ExtractCabCommand( 8HRESULT 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
38static HRESULT ProgressCallback( 38static 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
16HRESULT SmartCabCommand(int argc, LPWSTR argv[]); 17HRESULT WixNativeReadStdinPreamble();
17HRESULT ResetAclsCommand(int argc, LPWSTR argv[]); 18HRESULT SmartCabCommand(__in int argc, __in_ecount(argc) LPWSTR argv[]);
18HRESULT EnumCabCommand(int argc, LPWSTR argv[]); 19HRESULT ResetAclsCommand(__in int argc, __in_ecount(argc) LPWSTR argv[]);
19HRESULT ExtractCabCommand(int argc, LPWSTR argv[]); 20HRESULT EnumCabCommand(__in int argc, __in_ecount(argc) LPWSTR argv[]);
21HRESULT 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
5HRESULT ResetAclsCommand(int argc, LPWSTR argv[]) 5HRESULT 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
5static HRESULT CompressFiles(HANDLE hCab); 6static HRESULT CompressFiles(__in HANDLE hCab);
6static void __stdcall CabNamesCallback(LPWSTR wzFirstCabName, LPWSTR wzNewCabName, LPWSTR wzFileToken); 7static void __stdcall CabNamesCallback(__in_z LPWSTR wzFirstCabName, __in_z LPWSTR wzNewCabName, __in_z LPWSTR wzFileToken);
7 8
8 9
9HRESULT SmartCabCommand( 10HRESULT 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
153static void __stdcall CabNamesCallback( 157static 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
40HRESULT 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
62LExit:
63 ReleaseStr(sczLine);
64
65 return hr;
66}