aboutsummaryrefslogtreecommitdiff
path: root/src/ext/Util/ca/FormatFiles.cpp
diff options
context:
space:
mode:
authorRob Mensching <rob@firegiant.com>2021-05-03 09:55:22 -0700
committerRob Mensching <rob@firegiant.com>2021-05-03 09:55:22 -0700
commitff659159e041bf6c083e6b7fcb9b726065a9dd73 (patch)
treeea95bf3d3e031edcee65de33b9e6954178be669c /src/ext/Util/ca/FormatFiles.cpp
parent8a8a25695351ee542f08886a9d0957c78c6af366 (diff)
downloadwix-ff659159e041bf6c083e6b7fcb9b726065a9dd73.tar.gz
wix-ff659159e041bf6c083e6b7fcb9b726065a9dd73.tar.bz2
wix-ff659159e041bf6c083e6b7fcb9b726065a9dd73.zip
Move Util.wixext into ext
Diffstat (limited to 'src/ext/Util/ca/FormatFiles.cpp')
-rw-r--r--src/ext/Util/ca/FormatFiles.cpp221
1 files changed, 221 insertions, 0 deletions
diff --git a/src/ext/Util/ca/FormatFiles.cpp b/src/ext/Util/ca/FormatFiles.cpp
new file mode 100644
index 00000000..d1533999
--- /dev/null
+++ b/src/ext/Util/ca/FormatFiles.cpp
@@ -0,0 +1,221 @@
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
5const UINT COST_FILEFORMATTING = 2000;
6
7
8//
9// WixSchedFormatFiles - immediate CA to schedule format files CAs
10//
11extern "C" UINT __stdcall WixSchedFormatFiles(
12 __in MSIHANDLE hInstall
13 )
14{
15 HRESULT hr = S_OK;
16 UINT er = ERROR_SUCCESS;
17 PSCZ sczBinaryKey;
18 PSCZ sczFileKey;
19 PSCZ sczComponentKey;
20 PSCZ sczFormattedFile;
21 PSCZ sczFilePath;
22 PMSIHANDLE hView;
23 PMSIHANDLE hRec;
24 PSCZ sczFileContent;
25 PSCZ sczFormattedContent;
26 PSCZ sczExecCustomActionData;
27 PSCZ sczRollbackCustomActionData;
28
29 LPCWSTR wzQuery =
30 L"SELECT `Wix4FormatFile`.`Binary_`, `Wix4FormatFile`.`File_`, `File`.`Component_` "
31 L"FROM `Wix4FormatFile`, `File` "
32 L"WHERE `Wix4FormatFile`.`File_` = `File`.`File`";
33 enum eQuery { eqBinaryKey = 1, eqFileKey, eqComponentKey };
34
35 // initialize
36 hr = WcaInitialize(hInstall, "WixSchedFormatFiles");
37 ExitOnFailure(hr, "Failed to initialize for WixSchedFormatFiles.");
38
39 // query and loop through all the files
40 hr = WcaOpenExecuteView(wzQuery, &hView);
41 ExitOnFailure(hr, "Failed to open view on Wix4FormatFile table");
42
43 DWORD cFiles = 0;
44 while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
45 {
46 ++cFiles;
47
48 hr = WcaGetRecordString(hRec, eqBinaryKey, &sczBinaryKey);
49 ExitOnFailure(hr, "Failed to get Binary table key.");
50
51 hr = WcaGetRecordString(hRec, eqFileKey, &sczFileKey);
52 ExitOnFailure(hr, "Failed to get File table key.");
53
54 hr = WcaGetRecordString(hRec, eqComponentKey, &sczComponentKey);
55 ExitOnFailure(hr, "Failed to get Component table key.");
56
57 // we need to know if the component's being installed, uninstalled, or reinstalled
58 WCA_TODO todo = WcaGetComponentToDo(sczComponentKey);
59 if (WCA_TODO_INSTALL == todo || WCA_TODO_REINSTALL == todo)
60 {
61 // turn the file key into the path to the target file
62 hr = StrAllocFormatted(&sczFormattedFile, L"[#%ls]", sczFileKey);
63 ExitOnFailure(hr, "Failed to format file string for file: %ls", sczFileKey);
64 hr = WcaGetFormattedString(sczFormattedFile, &sczFilePath);
65 ExitOnFailure(hr, "Failed to get path for file: %ls", sczFileKey);
66
67 // extract binary to string
68 WCA_ENCODING encoding = WCA_ENCODING_UNKNOWN;
69 hr = WcaExtractBinaryToString(sczBinaryKey, &sczFileContent, &encoding);
70 ExitOnFailure(hr, "Failed to extract binary: %ls", sczBinaryKey);
71
72 // format string
73 hr = WcaGetFormattedString(sczFileContent, &sczFormattedContent);
74 ExitOnFailure(hr, "Failed to format file content: %ls", sczFileContent);
75
76 // write to deferred custom action data
77 hr = WcaWriteStringToCaData(sczFilePath, &sczExecCustomActionData);
78 ExitOnFailure(hr, "Failed to write deferred custom action data for file: %ls", sczFilePath);
79
80 hr = WcaWriteIntegerToCaData(encoding, &sczExecCustomActionData);
81 ExitOnFailure(hr, "Failed to write deferred custom action data for encoding: %d", encoding);
82
83 hr = WcaWriteStringToCaData(sczFormattedContent, &sczExecCustomActionData);
84 ExitOnFailure(hr, "Failed to write deferred custom action data for file content: %ls", sczFilePath);
85
86 // write to rollback custom action data
87 hr = WcaWriteStringToCaData(sczFilePath, &sczRollbackCustomActionData);
88 ExitOnFailure(hr, "Failed to write rollback custom action data for file: %ls", sczFilePath);
89
90 hr = WcaWriteIntegerToCaData(encoding, &sczRollbackCustomActionData);
91 ExitOnFailure(hr, "Failed to write deferred custom action data for encoding: %d", encoding);
92
93 hr = WcaWriteStringToCaData(sczFileContent, &sczRollbackCustomActionData);
94 ExitOnFailure(hr, "Failed to write rollback custom action data for file content: %ls", sczFilePath);
95 }
96 }
97
98 // reaching the end of the list is actually a good thing, not an error
99 if (E_NOMOREITEMS == hr)
100 {
101 hr = S_OK;
102 }
103 ExitOnFailure(hr, "Failure occurred while processing Wix4FormatFile table");
104
105 // schedule deferred CAs if there's anything to do
106 if (sczRollbackCustomActionData && *sczRollbackCustomActionData)
107 {
108 hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RollbackFormatFiles"), sczRollbackCustomActionData, cFiles * COST_FILEFORMATTING);
109 ExitOnFailure(hr, "Failed to schedule RollbackFormatFiles");
110 }
111
112 if (sczExecCustomActionData && *sczExecCustomActionData)
113 {
114 hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"ExecFormatFiles"), sczExecCustomActionData, cFiles * COST_FILEFORMATTING);
115 ExitOnFailure(hr, "Failed to schedule ExecFormatFiles");
116 }
117
118LExit:
119 return WcaFinalize(er = FAILED(hr) ? ERROR_INSTALL_FAILURE : er);
120}
121
122
123//
124// WixExecFormatFiles - deferred and rollback CAs to write formatted files
125//
126extern "C" UINT __stdcall WixExecFormatFiles(
127 __in MSIHANDLE hInstall
128 )
129{
130 HRESULT hr = S_OK;
131 UINT er = ERROR_SUCCESS;
132 PSCZ sczCustomActionData;
133 LPWSTR pwz = NULL;
134 PSCZ sczFilePath;
135 PSCZ sczFileContent;
136 LPSTR psz = NULL;
137
138 // initialize
139 hr = WcaInitialize(hInstall, "WixExecFormatFiles");
140 ExitOnFailure(hr, "Failed to initialize for WixExecFormatFiles.");
141
142 hr = WcaGetProperty(L"CustomActionData", &sczCustomActionData);
143 ExitOnFailure(hr, "Failed to get CustomActionData.");
144#ifdef _DEBUG
145 WcaLog(LOGMSG_STANDARD, "CustomActionData: %ls", sczCustomActionData);
146#endif
147
148 // loop through all the passed in data
149 pwz = sczCustomActionData;
150 while (pwz && *pwz)
151 {
152 // extract the custom action data
153 hr = WcaReadStringFromCaData(&pwz, &sczFilePath);
154 ExitOnFailure(hr, "Failed to read file path from custom action data");
155
156 WCA_ENCODING encoding = WCA_ENCODING_UNKNOWN;
157 hr = WcaReadIntegerFromCaData(&pwz, reinterpret_cast<int*>(&encoding));
158 ExitOnFailure(hr, "Failed to read encoding from custom action data");
159
160 hr = WcaReadStringFromCaData(&pwz, &sczFileContent);
161 ExitOnFailure(hr, "Failed to read file content from custom action data");
162
163 // re-encode content
164 LPCBYTE pbData = NULL;
165 size_t cbData = 0;
166 switch (encoding)
167 {
168 case WCA_ENCODING_UTF_16:
169 pbData = reinterpret_cast<LPCBYTE>(LPCWSTR(sczFileContent));
170 cbData = lstrlenW(sczFileContent) * sizeof(WCHAR);
171 break;
172
173 case WCA_ENCODING_UTF_8:
174 hr = StrAnsiAllocString(&psz, sczFileContent, 0, CP_UTF8);
175 ExitOnFailure(hr, "Failed to convert Unicode to UTF-8.");
176 pbData = reinterpret_cast<LPCBYTE>(psz);
177
178 hr = ::StringCbLengthA(psz, STRSAFE_MAX_CCH, &cbData);
179 ExitOnFailure(hr, "Failed to count UTF-8 bytes.");
180 break;
181
182 case WCA_ENCODING_ANSI:
183 hr = StrAnsiAllocString(&psz, sczFileContent, 0, CP_ACP);
184 ExitOnFailure(hr, "Failed to convert Unicode to ANSI.");
185 pbData = reinterpret_cast<LPCBYTE>(psz);
186
187 hr = ::StringCbLengthA(psz, STRSAFE_MAX_CCH, &cbData);
188 ExitOnFailure(hr, "Failed to count UTF-8 bytes.");
189 break;
190
191 default:
192 break;
193 }
194
195#ifdef _DEBUG
196 WcaLog(LOGMSG_STANDARD, "File: %ls", sczCustomActionData);
197 WcaLog(LOGMSG_STANDARD, "Content: %ls", sczFileContent);
198#endif
199
200 // write file and preserve modified time
201 FILETIME filetime;
202
203 hr = FileGetTime(sczFilePath, NULL, NULL, &filetime);
204 ExitOnFailure(hr, "Failed to get modified time of file : %ls", sczFilePath);
205
206 hr = FileWrite(sczFilePath, FILE_ATTRIBUTE_NORMAL, pbData, cbData, NULL);
207 ExitOnFailure(hr, "Failed to write file content: %ls", sczFilePath);
208
209 hr = FileSetTime(sczFilePath, NULL, NULL, &filetime);
210 ExitOnFailure(hr, "Failed to set modified time of file : %ls", sczFilePath);
211
212 // Tick the progress bar
213 hr = WcaProgressMessage(COST_FILEFORMATTING, FALSE);
214 ExitOnFailure(hr, "Failed to tick progress bar for file: %ls", sczFilePath);
215 }
216
217LExit:
218 ReleaseStr(psz);
219
220 return WcaFinalize(er = FAILED(hr) ? ERROR_INSTALL_FAILURE : er);
221}