diff options
author | Sean Hall <r.sean.hall@gmail.com> | 2018-12-15 21:46:30 -0600 |
---|---|---|
committer | GitHub <noreply@github.com> | 2018-12-15 21:46:30 -0600 |
commit | f7020c0d16baf2b960e7123e233e20c519f6a340 (patch) | |
tree | d2cd464ee15b2b3f304ff780c531b39bb292d331 /src/ca/TouchFile.cpp | |
parent | 6ed8d107e6edf16956c778bda3573f8d7a7690fc (diff) | |
download | wix-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.cpp | 308 |
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 | |||
5 | LPCWSTR vcsTouchFileQuery = L"SELECT `WixTouchFile`, `Component_`, `Path`, `Attributes` FROM `WixTouchFile`"; | ||
6 | enum TOUCH_FILE_QUERY { tfqId = 1, tfqComponent, tfqPath, tfqTouchFileAttributes }; | ||
7 | |||
8 | enum 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 | |||
18 | static 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 | |||
38 | LExit: | ||
39 | if (fReenableFileSystemRedirection) | ||
40 | { | ||
41 | WcaRevertWow64FSRedirection(); | ||
42 | } | ||
43 | |||
44 | return SUCCEEDED(hr); | ||
45 | } | ||
46 | |||
47 | |||
48 | static 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 | |||
73 | LExit: | ||
74 | return hr; | ||
75 | } | ||
76 | |||
77 | |||
78 | static 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 | |||
107 | LExit: | ||
108 | if (fReenableFileSystemRedirection) | ||
109 | { | ||
110 | WcaRevertWow64FSRedirection(); | ||
111 | } | ||
112 | |||
113 | return SUCCEEDED(hr); | ||
114 | } | ||
115 | |||
116 | |||
117 | static 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 | |||
198 | LExit: | ||
199 | ReleaseStr(sczExecuteData); | ||
200 | ReleaseStr(sczRollbackData); | ||
201 | ReleaseStr(sczPath); | ||
202 | ReleaseStr(sczComponent); | ||
203 | ReleaseStr(sczId); | ||
204 | |||
205 | return hr; | ||
206 | } | ||
207 | |||
208 | |||
209 | extern "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 | |||
222 | LExit: | ||
223 | DWORD er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; | ||
224 | return WcaFinalize(er); | ||
225 | } | ||
226 | |||
227 | |||
228 | extern "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 | |||
241 | LExit: | ||
242 | DWORD er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE; | ||
243 | return WcaFinalize(er); | ||
244 | } | ||
245 | |||
246 | |||
247 | extern "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 | |||
301 | LExit: | ||
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 | } | ||