aboutsummaryrefslogtreecommitdiff
path: root/src/wixnative/smartcab.cpp
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/wixnative/smartcab.cpp157
1 files changed, 157 insertions, 0 deletions
diff --git a/src/wixnative/smartcab.cpp b/src/wixnative/smartcab.cpp
new file mode 100644
index 00000000..da9087a3
--- /dev/null
+++ b/src/wixnative/smartcab.cpp
@@ -0,0 +1,157 @@
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
3#include "precomp.h"
4
5static HRESULT CompressFiles(HANDLE hCab);
6static void __stdcall CabNamesCallback(LPWSTR wzFirstCabName, LPWSTR wzNewCabName, LPWSTR wzFileToken);
7
8
9HRESULT SmartCabCommand(
10 __in int argc,
11 __in LPWSTR argv[]
12)
13{
14 HRESULT hr = E_INVALIDARG;
15 LPCWSTR wzCabPath = NULL;
16 LPCWSTR wzCabName = NULL;
17 LPWSTR sczCabDir = NULL;
18 UINT uiFileCount = 0;
19 UINT uiMaxSize = 0;
20 UINT uiMaxThresh = 0;
21 COMPRESSION_TYPE ct = COMPRESSION_TYPE_NONE;
22 HANDLE hCab = NULL;
23
24 if (argc < 1)
25 {
26 ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Must specify: outCabPath [compressionType] [fileCount] [maxSizePerCabInMB [maxThreshold]]");
27 }
28 else
29 {
30 wzCabPath = argv[0];
31 wzCabName = PathFile(wzCabPath);
32
33 hr = PathGetDirectory(wzCabPath, &sczCabDir);
34 ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Could not parse directory from path: %ls", wzCabPath);
35
36 if (argc > 1)
37 {
38 UINT uiCompressionType;
39 hr = StrStringToUInt32(argv[1], 0, &uiCompressionType);
40 ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Could not parse compression type as number: %ls", argv[1]);
41
42 ct = (uiCompressionType > 4) ? COMPRESSION_TYPE_HIGH : static_cast<COMPRESSION_TYPE>(uiCompressionType);
43 }
44
45 if (argc > 2)
46 {
47 hr = StrStringToUInt32(argv[2], 0, &uiFileCount);
48 ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Could not parse file count as number: %ls", argv[2]);
49 }
50
51 if (argc > 3)
52 {
53 hr = StrStringToUInt32(argv[3], 0, &uiMaxSize);
54 ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Could not parse max size as number: %ls", argv[3]);
55 }
56
57 if (argc > 4)
58 {
59 hr = StrStringToUInt32(argv[4], 0, &uiMaxThresh);
60 ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "Could not parse max threshold as number: %ls", argv[4]);
61 }
62 }
63
64 hr = CabCBegin(wzCabName, sczCabDir, uiFileCount, uiMaxSize, uiMaxThresh, ct, &hCab);
65 ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "failed to initialize cabinet: %ls", wzCabPath);
66
67 hr = CompressFiles(hCab);
68 ExitOnFailure(hr, "failed to compress files into cabinet: %ls", wzCabPath);
69
70 hr = CabCFinish(hCab, CabNamesCallback);
71 hCab = NULL; // once finish is called, the handle is invalid.
72 ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "failed to compress cabinet: %ls", wzCabPath);
73
74
75LExit:
76 if (hCab)
77 {
78 CabCCancel(hCab);
79 }
80 ReleaseStr(sczCabDir);
81
82 return hr;
83}
84
85
86static HRESULT CompressFiles(
87 __in HANDLE hCab
88)
89{
90 HRESULT hr = S_OK;
91 LPWSTR sczLine = NULL;
92 LPWSTR* rgsczSplit = NULL;
93 UINT cSplit = 0;
94 MSIFILEHASHINFO hashInfo = { sizeof(MSIFILEHASHINFO) };
95
96 for (;;)
97 {
98 hr = ConsoleReadW(&sczLine);
99 ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "failed to read smartcab line from stdin");
100
101 if (!*sczLine)
102 {
103 break;
104 }
105
106 hr = StrSplitAllocArray(&rgsczSplit, &cSplit, sczLine, L"\t");
107 ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "failed to split smartcab line from stdin: %ls", sczLine);
108
109 if (cSplit != 2 && cSplit != 6)
110 {
111 hr = E_INVALIDARG;
112 ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "failed to split smartcab line into hash x 4, token, source file: %ls", sczLine);
113 }
114
115 LPCWSTR wzFilePath = rgsczSplit[0];
116 LPCWSTR wzToken = rgsczSplit[1];
117 PMSIFILEHASHINFO pHashInfo = NULL;
118
119 if (cSplit == 6)
120 {
121 for (int i = 0; i < 4; ++i)
122 {
123 LPCWSTR wzHash = rgsczSplit[i + 2];
124
125 hr = StrStringToInt32(wzHash, 0, reinterpret_cast<INT*>(hashInfo.dwData + i));
126 ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "failed to parse hash: %ls for file: %ls", wzHash, wzFilePath);
127 }
128
129 pHashInfo = &hashInfo;
130 }
131
132 hr = CabCAddFile(wzFilePath, wzToken, pHashInfo, hCab);
133 ConsoleExitOnFailure(hr, CONSOLE_COLOR_RED, "failed to add file: %ls", wzFilePath);
134
135 ReleaseNullStrArray(rgsczSplit, cSplit);
136 }
137
138LExit:
139 ReleaseNullStrArray(rgsczSplit, cSplit);
140 ReleaseStr(sczLine);
141
142 return hr;
143}
144
145
146// Callback from PFNFCIGETNEXTCABINET CabCGetNextCabinet method
147// First argument is the name of splitting cabinet without extension e.g. "cab1"
148// Second argument is name of the new cabinet that would be formed by splitting e.g. "cab1b.cab"
149// Third argument is the file token of the first file present in the splitting cabinet
150static void __stdcall CabNamesCallback(
151 __in LPWSTR wzFirstCabName,
152 __in LPWSTR wzNewCabName,
153 __in LPWSTR wzFileToken
154)
155{
156 ConsoleWriteLine(CONSOLE_COLOR_NORMAL, "%ls\t%ls\t%ls", wzFirstCabName, wzNewCabName, wzFileToken);
157}