diff options
| author | Rob Mensching <rob@firegiant.com> | 2021-05-03 09:55:22 -0700 |
|---|---|---|
| committer | Rob Mensching <rob@firegiant.com> | 2021-05-03 09:55:22 -0700 |
| commit | ff659159e041bf6c083e6b7fcb9b726065a9dd73 (patch) | |
| tree | ea95bf3d3e031edcee65de33b9e6954178be669c /src/ext/Util/ca/FormatFiles.cpp | |
| parent | 8a8a25695351ee542f08886a9d0957c78c6af366 (diff) | |
| download | wix-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.cpp | 221 |
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 | |||
| 5 | const UINT COST_FILEFORMATTING = 2000; | ||
| 6 | |||
| 7 | |||
| 8 | // | ||
| 9 | // WixSchedFormatFiles - immediate CA to schedule format files CAs | ||
| 10 | // | ||
| 11 | extern "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 | |||
| 118 | LExit: | ||
| 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 | // | ||
| 126 | extern "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 | |||
| 217 | LExit: | ||
| 218 | ReleaseStr(psz); | ||
| 219 | |||
| 220 | return WcaFinalize(er = FAILED(hr) ? ERROR_INSTALL_FAILURE : er); | ||
| 221 | } | ||
