aboutsummaryrefslogtreecommitdiff
path: root/src/ca/TouchFile.cpp
diff options
context:
space:
mode:
authorSean Hall <r.sean.hall@gmail.com>2018-12-15 21:46:30 -0600
committerGitHub <noreply@github.com>2018-12-15 21:46:30 -0600
commitf7020c0d16baf2b960e7123e233e20c519f6a340 (patch)
treed2cd464ee15b2b3f304ff780c531b39bb292d331 /src/ca/TouchFile.cpp
parent6ed8d107e6edf16956c778bda3573f8d7a7690fc (diff)
downloadwix-f7020c0d16baf2b960e7123e233e20c519f6a340.tar.gz
wix-f7020c0d16baf2b960e7123e233e20c519f6a340.tar.bz2
wix-f7020c0d16baf2b960e7123e233e20c519f6a340.zip
Import implementation of UtilCA from old repo's WixCA/scasched/scaexec. (#3)
Diffstat (limited to 'src/ca/TouchFile.cpp')
-rw-r--r--src/ca/TouchFile.cpp308
1 files changed, 308 insertions, 0 deletions
diff --git a/src/ca/TouchFile.cpp b/src/ca/TouchFile.cpp
new file mode 100644
index 00000000..1c40a3eb
--- /dev/null
+++ b/src/ca/TouchFile.cpp
@@ -0,0 +1,308 @@
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
5LPCWSTR vcsTouchFileQuery = L"SELECT `WixTouchFile`, `Component_`, `Path`, `Attributes` FROM `WixTouchFile`";
6enum TOUCH_FILE_QUERY { tfqId = 1, tfqComponent, tfqPath, tfqTouchFileAttributes };
7
8enum TOUCH_FILE_ATTRIBUTE
9{
10 TOUCH_FILE_ATTRIBUTE_ON_INSTALL = 0x01,
11 TOUCH_FILE_ATTRIBUTE_ON_REINSTALL = 0x02,
12 TOUCH_FILE_ATTRIBUTE_ON_UNINSTALL = 0x04,
13 TOUCH_FILE_ATTRIBUTE_64BIT = 0x10,
14 TOUCH_FILE_ATTRIBUTE_VITAL = 0x20
15};
16
17
18static BOOL SetExistingFileModifiedTime(
19 __in_z LPCWSTR wzId,
20 __in_z LPCWSTR wzPath,
21 __in BOOL f64Bit,
22 __in FILETIME* pftModified
23 )
24{
25 HRESULT hr = S_OK;
26 BOOL fReenableFileSystemRedirection = FALSE;
27
28 if (f64Bit)
29 {
30 hr = WcaDisableWow64FSRedirection();
31 ExitOnFailure(hr, "Failed to disable 64-bit file system redirection to path: '%ls' for: %ls", wzPath, wzId);
32
33 fReenableFileSystemRedirection = TRUE;
34 }
35
36 hr = FileSetTime(wzPath, NULL, NULL, pftModified);
37
38LExit:
39 if (fReenableFileSystemRedirection)
40 {
41 WcaRevertWow64FSRedirection();
42 }
43
44 return SUCCEEDED(hr);
45}
46
47
48static HRESULT AddDataToCustomActionData(
49 __deref_inout_z LPWSTR* psczCustomActionData,
50 __in_z LPCWSTR wzId,
51 __in_z LPCWSTR wzPath,
52 __in int iTouchFileAttributes,
53 __in FILETIME ftModified
54 )
55{
56 HRESULT hr = S_OK;
57
58 hr = WcaWriteStringToCaData(wzId, psczCustomActionData);
59 ExitOnFailure(hr, "Failed to add touch file identity to custom action data.");
60
61 hr = WcaWriteStringToCaData(wzPath, psczCustomActionData);
62 ExitOnFailure(hr, "Failed to add touch file path to custom action data.");
63
64 hr = WcaWriteIntegerToCaData(iTouchFileAttributes, psczCustomActionData);
65 ExitOnFailure(hr, "Failed to add touch file attributes to custom action data.");
66
67 hr = WcaWriteIntegerToCaData(ftModified.dwHighDateTime, psczCustomActionData);
68 ExitOnFailure(hr, "Failed to add touch file high date/time to custom action data.");
69
70 hr = WcaWriteIntegerToCaData(ftModified.dwLowDateTime, psczCustomActionData);
71 ExitOnFailure(hr, "Failed to add touch file low date/time to custom action data.");
72
73LExit:
74 return hr;
75}
76
77
78static BOOL TryGetExistingFileModifiedTime(
79 __in_z LPCWSTR wzId,
80 __in_z LPCWSTR wzPath,
81 __in BOOL f64Bit,
82 __inout FILETIME* pftModified
83 )
84{
85 HRESULT hr = S_OK;
86 BOOL fReenableFileSystemRedirection = FALSE;
87
88 if (f64Bit)
89 {
90 hr = WcaDisableWow64FSRedirection();
91 ExitOnFailure(hr, "Failed to disable 64-bit file system redirection to path: '%ls' for: %ls", wzPath, wzId);
92
93 fReenableFileSystemRedirection = TRUE;
94 }
95
96 hr = FileGetTime(wzPath, NULL, NULL, pftModified);
97 if (E_PATHNOTFOUND == hr || E_FILENOTFOUND == hr)
98 {
99 // If the file doesn't exist yet there is nothing to rollback (i.e. file will probably be removed during rollback), so
100 // keep the error code but don't log anything.
101 }
102 else if (FAILED(hr))
103 {
104 WcaLog(LOGMSG_STANDARD, "Cannot access modified timestamp for file: '%ls' due to error: 0x%x. Continuing with out rollback for: %ls", wzPath, hr, wzId);
105 }
106
107LExit:
108 if (fReenableFileSystemRedirection)
109 {
110 WcaRevertWow64FSRedirection();
111 }
112
113 return SUCCEEDED(hr);
114}
115
116
117static HRESULT ProcessTouchFileTable(
118 __in BOOL fInstalling
119 )
120{
121 HRESULT hr = S_OK;
122
123 FILETIME ftModified = {};
124
125 PMSIHANDLE hView;
126 PMSIHANDLE hRec;
127
128 LPWSTR sczId = NULL;
129 LPWSTR sczComponent = NULL;
130 int iTouchFileAttributes = 0;
131 LPWSTR sczPath = NULL;
132
133 FILETIME ftRollbackModified = {};
134 LPWSTR sczRollbackData = NULL;
135 LPWSTR sczExecuteData = NULL;
136
137 if (S_OK != WcaTableExists(L"WixTouchFile"))
138 {
139 ExitFunction();
140 }
141
142 ::GetSystemTimeAsFileTime(&ftModified);
143
144 hr = WcaOpenExecuteView(vcsTouchFileQuery, &hView);
145 ExitOnFailure(hr, "Failed to open view on WixTouchFile table");
146
147 while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
148 {
149 hr = WcaGetRecordString(hRec, tfqId, &sczId);
150 ExitOnFailure(hr, "Failed to get touch file identity.");
151
152 hr = WcaGetRecordString(hRec, tfqComponent, &sczComponent);
153 ExitOnFailure(hr, "Failed to get touch file component for: %ls", sczId);
154
155 hr = WcaGetRecordInteger(hRec, tfqTouchFileAttributes, &iTouchFileAttributes);
156 ExitOnFailure(hr, "Failed to get touch file attributes for: %ls", sczId);
157
158 WCA_TODO todo = WcaGetComponentToDo(sczComponent);
159
160 BOOL fOnInstall = fInstalling && WCA_TODO_INSTALL == todo && (iTouchFileAttributes & TOUCH_FILE_ATTRIBUTE_ON_INSTALL);
161 BOOL fOnReinstall = fInstalling && WCA_TODO_REINSTALL == todo && (iTouchFileAttributes & TOUCH_FILE_ATTRIBUTE_ON_REINSTALL);
162 BOOL fOnUninstall = !fInstalling && WCA_TODO_UNINSTALL == todo && (iTouchFileAttributes & TOUCH_FILE_ATTRIBUTE_ON_UNINSTALL);
163
164 if (fOnInstall || fOnReinstall || fOnUninstall)
165 {
166 hr = WcaGetRecordFormattedString(hRec, tfqPath, &sczPath);
167 ExitOnFailure(hr, "Failed to get touch file path for: %ls", sczId);
168
169 if (TryGetExistingFileModifiedTime(sczId, sczPath, (iTouchFileAttributes & TOUCH_FILE_ATTRIBUTE_64BIT), &ftRollbackModified))
170 {
171 hr = AddDataToCustomActionData(&sczRollbackData, sczId, sczPath, iTouchFileAttributes, ftRollbackModified);
172 ExitOnFailure(hr, "Failed to add to rollback custom action data for: %ls", sczId);
173 }
174
175 hr = AddDataToCustomActionData(&sczExecuteData, sczId, sczPath, iTouchFileAttributes, ftModified);
176 ExitOnFailure(hr, "Failed to add to execute custom action data for: %ls", sczId);
177 }
178 }
179
180 if (E_NOMOREITEMS == hr)
181 {
182 hr = S_OK;
183 }
184 ExitOnFailure(hr, "Failure occured while processing WixTouchFile table");
185
186 if (sczRollbackData)
187 {
188 hr = WcaDoDeferredAction(L"WixRollbackTouchFile", sczRollbackData, 0);
189 ExitOnFailure(hr, "Failed to schedule WixRollbackTouchFile");
190 }
191
192 if (sczExecuteData)
193 {
194 hr = WcaDoDeferredAction(L"WixExecuteTouchFile", sczExecuteData, 0);
195 ExitOnFailure(hr, "Failed to schedule WixExecuteTouchFile");
196 }
197
198LExit:
199 ReleaseStr(sczExecuteData);
200 ReleaseStr(sczRollbackData);
201 ReleaseStr(sczPath);
202 ReleaseStr(sczComponent);
203 ReleaseStr(sczId);
204
205 return hr;
206}
207
208
209extern "C" UINT WINAPI WixTouchFileDuringInstall(
210 __in MSIHANDLE hInstall
211 )
212{
213 //AssertSz(FALSE, "debug WixTouchFileDuringInstall");
214
215 HRESULT hr = S_OK;
216
217 hr = WcaInitialize(hInstall, "WixTouchFileDuringInstall");
218 ExitOnFailure(hr, "Failed to initialize WixTouchFileDuringInstall.");
219
220 hr = ProcessTouchFileTable(TRUE);
221
222LExit:
223 DWORD er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
224 return WcaFinalize(er);
225}
226
227
228extern "C" UINT WINAPI WixTouchFileDuringUninstall(
229 __in MSIHANDLE hInstall
230 )
231{
232 //AssertSz(FALSE, "debug WixTouchFileDuringUninstall");
233
234 HRESULT hr = S_OK;
235
236 hr = WcaInitialize(hInstall, "WixTouchFileDuringUninstall");
237 ExitOnFailure(hr, "Failed to initialize WixTouchFileDuringUninstall.");
238
239 hr = ProcessTouchFileTable(FALSE);
240
241LExit:
242 DWORD er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
243 return WcaFinalize(er);
244}
245
246
247extern "C" UINT WINAPI WixExecuteTouchFile(
248 __in MSIHANDLE hInstall
249 )
250{
251 HRESULT hr = S_OK;
252
253 LPWSTR sczData = NULL;
254 LPWSTR pwz = NULL;
255
256 LPWSTR sczId = NULL;
257 LPWSTR sczPath = NULL;
258 int iTouchFileAttributes = 0;
259 FILETIME ftModified = {};
260
261 hr = WcaInitialize(hInstall, "WixExecuteTouchFile");
262 ExitOnFailure(hr, "Failed to initialize WixExecuteTouchFile.");
263
264 hr = WcaGetProperty(L"CustomActionData", &sczData);
265 ExitOnFailure(hr, "Failed to get custom action data for WixExecuteTouchFile.");
266
267 pwz = sczData;
268
269 while (pwz && *pwz)
270 {
271 hr = WcaReadStringFromCaData(&pwz, &sczId);
272 ExitOnFailure(hr, "Failed to get touch file identity from custom action data.");
273
274 hr = WcaReadStringFromCaData(&pwz, &sczPath);
275 ExitOnFailure(hr, "Failed to get touch file path from custom action data for: %ls", sczId);
276
277 hr = WcaReadIntegerFromCaData(&pwz, &iTouchFileAttributes);
278 ExitOnFailure(hr, "Failed to get touch file attributes from custom action data for: %ls", sczId);
279
280 hr = WcaReadIntegerFromCaData(&pwz, reinterpret_cast<int*>(&ftModified.dwHighDateTime));
281 ExitOnFailure(hr, "Failed to get touch file high date/time from custom action data for: %ls", sczId);
282
283 hr = WcaReadIntegerFromCaData(&pwz, reinterpret_cast<int*>(&ftModified.dwLowDateTime));
284 ExitOnFailure(hr, "Failed to get touch file low date/time from custom action data for: %ls", sczId);
285
286 hr = SetExistingFileModifiedTime(sczId, sczPath, (iTouchFileAttributes & TOUCH_FILE_ATTRIBUTE_64BIT), &ftModified);
287 if (FAILED(hr))
288 {
289 if (iTouchFileAttributes & TOUCH_FILE_ATTRIBUTE_VITAL)
290 {
291 ExitOnFailure(hr, "Failed to touch file: '%ls' for: %ls", &sczPath, sczId);
292 }
293 else
294 {
295 WcaLog(LOGMSG_STANDARD, "Could not touch non-vital file: '%ls' for: %ls with error: 0x%x. Continuing...", sczPath, sczId, hr);
296 hr = S_OK;
297 }
298 }
299 }
300
301LExit:
302 ReleaseStr(sczPath);
303 ReleaseStr(sczId);
304 ReleaseStr(sczData);
305
306 DWORD er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
307 return WcaFinalize(er);
308}