main
cpp 346 lines 10.1 KB
Raw
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 `TouchFile`, `Component_`, `Path`, `Attributes` FROM `Wix4TouchFile`";
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 HRESULT 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 #ifndef _WIN64
27 BOOL fReenableFileSystemRedirection = FALSE;
28
29 if (f64Bit)
30 {
31 hr = WcaDisableWow64FSRedirection();
32 ExitOnFailure(hr, "Failed to disable 64-bit file system redirection to path: '%ls' for: %ls", wzPath, wzId);
33
34 fReenableFileSystemRedirection = TRUE;
35 }
36 #else
37 UNREFERENCED_PARAMETER(wzId);
38 UNREFERENCED_PARAMETER(f64Bit);
39 #endif
40
41 hr = FileSetTime(wzPath, NULL, NULL, pftModified);
42
43 #ifndef _WIN64
44 LExit:
45 if (fReenableFileSystemRedirection)
46 {
47 WcaRevertWow64FSRedirection();
48 }
49 #endif
50
51 return hr;
52 }
53
54
55 static HRESULT AddDataToCustomActionData(
56 __deref_inout_z LPWSTR* psczCustomActionData,
57 __in_z LPCWSTR wzId,
58 __in_z LPCWSTR wzPath,
59 __in int iTouchFileAttributes,
60 __in FILETIME ftModified
61 )
62 {
63 HRESULT hr = S_OK;
64
65 hr = WcaWriteStringToCaData(wzId, psczCustomActionData);
66 ExitOnFailure(hr, "Failed to add touch file identity to custom action data.");
67
68 hr = WcaWriteStringToCaData(wzPath, psczCustomActionData);
69 ExitOnFailure(hr, "Failed to add touch file path to custom action data.");
70
71 hr = WcaWriteIntegerToCaData(iTouchFileAttributes, psczCustomActionData);
72 ExitOnFailure(hr, "Failed to add touch file attributes to custom action data.");
73
74 hr = WcaWriteIntegerToCaData(ftModified.dwHighDateTime, psczCustomActionData);
75 ExitOnFailure(hr, "Failed to add touch file high date/time to custom action data.");
76
77 hr = WcaWriteIntegerToCaData(ftModified.dwLowDateTime, psczCustomActionData);
78 ExitOnFailure(hr, "Failed to add touch file low date/time to custom action data.");
79
80 LExit:
81 return hr;
82 }
83
84
85 static BOOL TryGetExistingFileModifiedTime(
86 __in_z LPCWSTR wzId,
87 __in_z LPCWSTR wzPath,
88 __in BOOL f64Bit,
89 __inout FILETIME* pftModified
90 )
91 {
92 HRESULT hr = S_OK;
93 #ifndef _WIN64
94 BOOL fReenableFileSystemRedirection = FALSE;
95
96 if (f64Bit)
97 {
98 hr = WcaDisableWow64FSRedirection();
99 ExitOnFailure(hr, "Failed to disable 64-bit file system redirection to path: '%ls' for: %ls", wzPath, wzId);
100
101 fReenableFileSystemRedirection = TRUE;
102 }
103 #else
104 UNREFERENCED_PARAMETER(wzId);
105 UNREFERENCED_PARAMETER(f64Bit);
106 #endif
107
108 hr = FileGetTime(wzPath, NULL, NULL, pftModified);
109 if (E_PATHNOTFOUND == hr || E_FILENOTFOUND == hr)
110 {
111 // If the file doesn't exist yet there is nothing to rollback (i.e. file will probably be removed during rollback), so
112 // keep the error code but don't log anything.
113 }
114 else if (FAILED(hr))
115 {
116 WcaLog(LOGMSG_STANDARD, "Cannot access modified timestamp for file: '%ls' due to error: 0x%x. Continuing with out rollback for: %ls", wzPath, hr, wzId);
117 }
118
119 #ifndef _WIN64
120 LExit:
121 if (fReenableFileSystemRedirection)
122 {
123 WcaRevertWow64FSRedirection();
124 }
125 #endif
126
127 return SUCCEEDED(hr);
128 }
129
130
131 static HRESULT ProcessTouchFileTable(
132 __in BOOL fInstalling
133 )
134 {
135 HRESULT hr = S_OK;
136
137 FILETIME ftModified = {};
138
139 PMSIHANDLE hView;
140 PMSIHANDLE hRec;
141
142 LPWSTR sczId = NULL;
143 LPWSTR sczComponent = NULL;
144 int iTouchFileAttributes = 0;
145 LPWSTR sczPath = NULL;
146
147 FILETIME ftRollbackModified = {};
148 LPWSTR sczRollbackData = NULL;
149 LPWSTR sczExecuteData = NULL;
150
151 if (S_OK != WcaTableExists(L"Wix4TouchFile"))
152 {
153 ExitFunction();
154 }
155
156 ::GetSystemTimeAsFileTime(&ftModified);
157
158 hr = WcaOpenExecuteView(vcsTouchFileQuery, &hView);
159 ExitOnFailure(hr, "Failed to open view on Wix4TouchFile table");
160
161 while (S_OK == (hr = WcaFetchRecord(hView, &hRec)))
162 {
163 hr = WcaGetRecordString(hRec, tfqId, &sczId);
164 ExitOnFailure(hr, "Failed to get touch file identity.");
165
166 hr = WcaGetRecordString(hRec, tfqComponent, &sczComponent);
167 ExitOnFailure(hr, "Failed to get touch file component for: %ls", sczId);
168
169 hr = WcaGetRecordInteger(hRec, tfqTouchFileAttributes, &iTouchFileAttributes);
170 ExitOnFailure(hr, "Failed to get touch file attributes for: %ls", sczId);
171
172 WCA_TODO todo = WcaGetComponentToDo(sczComponent);
173
174 BOOL fOnInstall = fInstalling && WCA_TODO_INSTALL == todo && (iTouchFileAttributes & TOUCH_FILE_ATTRIBUTE_ON_INSTALL);
175 BOOL fOnReinstall = fInstalling && WCA_TODO_REINSTALL == todo && (iTouchFileAttributes & TOUCH_FILE_ATTRIBUTE_ON_REINSTALL);
176 BOOL fOnUninstall = !fInstalling && WCA_TODO_UNINSTALL == todo && (iTouchFileAttributes & TOUCH_FILE_ATTRIBUTE_ON_UNINSTALL);
177
178 if (fOnInstall || fOnReinstall || fOnUninstall)
179 {
180 hr = WcaGetRecordFormattedString(hRec, tfqPath, &sczPath);
181 ExitOnFailure(hr, "Failed to get touch file path for: %ls", sczId);
182
183 if (TryGetExistingFileModifiedTime(sczId, sczPath, (iTouchFileAttributes & TOUCH_FILE_ATTRIBUTE_64BIT), &ftRollbackModified))
184 {
185 hr = AddDataToCustomActionData(&sczRollbackData, sczId, sczPath, iTouchFileAttributes, ftRollbackModified);
186 ExitOnFailure(hr, "Failed to add to rollback custom action data for: %ls", sczId);
187 }
188
189 hr = AddDataToCustomActionData(&sczExecuteData, sczId, sczPath, iTouchFileAttributes, ftModified);
190 ExitOnFailure(hr, "Failed to add to execute custom action data for: %ls", sczId);
191 }
192 }
193
194 if (E_NOMOREITEMS == hr)
195 {
196 hr = S_OK;
197 }
198 ExitOnFailure(hr, "Failure occured while processing Wix4TouchFile table");
199
200 if (sczRollbackData)
201 {
202 hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"RollbackTouchFile"), sczRollbackData, 0);
203 ExitOnFailure(hr, "Failed to schedule RollbackTouchFile");
204 }
205
206 if (sczExecuteData)
207 {
208 hr = WcaDoDeferredAction(CUSTOM_ACTION_DECORATION(L"ExecuteTouchFile"), sczExecuteData, 0);
209 ExitOnFailure(hr, "Failed to schedule ExecuteTouchFile");
210 }
211
212 LExit:
213 ReleaseStr(sczExecuteData);
214 ReleaseStr(sczRollbackData);
215 ReleaseStr(sczPath);
216 ReleaseStr(sczComponent);
217 ReleaseStr(sczId);
218
219 return hr;
220 }
221
222
223 extern "C" UINT WINAPI WixTouchFileDuringInstall(
224 __in MSIHANDLE hInstall
225 )
226 {
227 //AssertSz(FALSE, "debug WixTouchFileDuringInstall");
228
229 HRESULT hr = S_OK;
230
231 hr = WcaInitialize(hInstall, "WixTouchFileDuringInstall");
232 ExitOnFailure(hr, "Failed to initialize WixTouchFileDuringInstall.");
233
234 #ifndef _WIN64
235 WcaInitializeWow64();
236 #endif
237
238 hr = ProcessTouchFileTable(TRUE);
239
240 LExit:
241 #ifndef _WIN64
242 WcaFinalizeWow64();
243 #endif
244
245 DWORD er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
246 return WcaFinalize(er);
247 }
248
249
250 extern "C" UINT WINAPI WixTouchFileDuringUninstall(
251 __in MSIHANDLE hInstall
252 )
253 {
254 //AssertSz(FALSE, "debug WixTouchFileDuringUninstall");
255
256 HRESULT hr = S_OK;
257
258 hr = WcaInitialize(hInstall, "WixTouchFileDuringUninstall");
259 ExitOnFailure(hr, "Failed to initialize WixTouchFileDuringUninstall.");
260
261 #ifndef _WIN64
262 WcaInitializeWow64();
263 #endif
264
265 hr = ProcessTouchFileTable(FALSE);
266
267 LExit:
268 #ifndef _WIN64
269 WcaFinalizeWow64();
270 #endif
271
272 DWORD er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
273 return WcaFinalize(er);
274 }
275
276
277 extern "C" UINT WINAPI WixExecuteTouchFile(
278 __in MSIHANDLE hInstall
279 )
280 {
281 HRESULT hr = S_OK;
282
283 LPWSTR sczData = NULL;
284 LPWSTR pwz = NULL;
285
286 LPWSTR sczId = NULL;
287 LPWSTR sczPath = NULL;
288 int iTouchFileAttributes = 0;
289 FILETIME ftModified = {};
290
291 hr = WcaInitialize(hInstall, "WixExecuteTouchFile");
292 ExitOnFailure(hr, "Failed to initialize WixExecuteTouchFile.");
293
294 #ifndef _WIN64
295 WcaInitializeWow64();
296 #endif
297
298 hr = WcaGetProperty(L"CustomActionData", &sczData);
299 ExitOnFailure(hr, "Failed to get custom action data for WixExecuteTouchFile.");
300
301 pwz = sczData;
302
303 while (pwz && *pwz)
304 {
305 hr = WcaReadStringFromCaData(&pwz, &sczId);
306 ExitOnFailure(hr, "Failed to get touch file identity from custom action data.");
307
308 hr = WcaReadStringFromCaData(&pwz, &sczPath);
309 ExitOnFailure(hr, "Failed to get touch file path from custom action data for: %ls", sczId);
310
311 hr = WcaReadIntegerFromCaData(&pwz, &iTouchFileAttributes);
312 ExitOnFailure(hr, "Failed to get touch file attributes from custom action data for: %ls", sczId);
313
314 hr = WcaReadIntegerFromCaData(&pwz, reinterpret_cast<int*>(&ftModified.dwHighDateTime));
315 ExitOnFailure(hr, "Failed to get touch file high date/time from custom action data for: %ls", sczId);
316
317 hr = WcaReadIntegerFromCaData(&pwz, reinterpret_cast<int*>(&ftModified.dwLowDateTime));
318 ExitOnFailure(hr, "Failed to get touch file low date/time from custom action data for: %ls", sczId);
319
320 hr = SetExistingFileModifiedTime(sczId, sczPath, (iTouchFileAttributes & TOUCH_FILE_ATTRIBUTE_64BIT), &ftModified);
321 if (FAILED(hr))
322 {
323 if (iTouchFileAttributes & TOUCH_FILE_ATTRIBUTE_VITAL)
324 {
325 ExitOnFailure(hr, "Failed to touch file: '%ls' for: %ls", sczPath, sczId);
326 }
327 else
328 {
329 WcaLog(LOGMSG_STANDARD, "Could not touch non-vital file: '%ls' for: %ls with error: 0x%x. Continuing...", sczPath, sczId, hr);
330 hr = S_OK;
331 }
332 }
333 }
334
335 LExit:
336 #ifndef _WIN64
337 WcaFinalizeWow64();
338 #endif
339
340 ReleaseStr(sczPath);
341 ReleaseStr(sczId);
342 ReleaseStr(sczData);
343
344 DWORD er = SUCCEEDED(hr) ? ERROR_SUCCESS : ERROR_INSTALL_FAILURE;
345 return WcaFinalize(er);
346 }