diff options
| author | Rob Mensching <rob@firegiant.com> | 2021-04-10 16:05:23 -0700 |
|---|---|---|
| committer | Rob Mensching <rob@firegiant.com> | 2021-04-12 09:56:15 -0700 |
| commit | 0c2b4cf3a439eda3e19d20fadfc65ddc7d0394c0 (patch) | |
| tree | 825272bd86d365d8f2175fd6fadd9725c8b400ff /src/dutil/fileutil.cpp | |
| parent | ed0ef472c76ac0d2a3d7a138e4f3b7ad950a56bc (diff) | |
| download | wix-0c2b4cf3a439eda3e19d20fadfc65ddc7d0394c0.tar.gz wix-0c2b4cf3a439eda3e19d20fadfc65ddc7d0394c0.tar.bz2 wix-0c2b4cf3a439eda3e19d20fadfc65ddc7d0394c0.zip | |
Integrate fixes that make dutil a little more robust to failure
Diffstat (limited to 'src/dutil/fileutil.cpp')
| -rw-r--r-- | src/dutil/fileutil.cpp | 128 |
1 files changed, 128 insertions, 0 deletions
diff --git a/src/dutil/fileutil.cpp b/src/dutil/fileutil.cpp index c76017de..06a44b45 100644 --- a/src/dutil/fileutil.cpp +++ b/src/dutil/fileutil.cpp | |||
| @@ -1106,6 +1106,134 @@ LExit: | |||
| 1106 | 1106 | ||
| 1107 | 1107 | ||
| 1108 | /******************************************************************* | 1108 | /******************************************************************* |
| 1109 | FileCopyUsingHandlesWithProgress | ||
| 1110 | |||
| 1111 | *******************************************************************/ | ||
| 1112 | extern "C" HRESULT DAPI FileCopyUsingHandlesWithProgress( | ||
| 1113 | __in HANDLE hSource, | ||
| 1114 | __in HANDLE hTarget, | ||
| 1115 | __in DWORD64 cbCopy, | ||
| 1116 | __in_opt LPPROGRESS_ROUTINE lpProgressRoutine, | ||
| 1117 | __in_opt LPVOID lpData, | ||
| 1118 | __in_opt LPBOOL pbCancel, | ||
| 1119 | __out_opt DWORD64* pcbCopied | ||
| 1120 | ) | ||
| 1121 | { | ||
| 1122 | HRESULT hr = S_OK; | ||
| 1123 | BOOL fStop = FALSE; | ||
| 1124 | BOOL fCanceled = FALSE; | ||
| 1125 | DWORD64 cbTotalCopied = 0; | ||
| 1126 | BYTE rgbData[64 * 1024]; | ||
| 1127 | DWORD cbRead = 0; | ||
| 1128 | |||
| 1129 | LARGE_INTEGER liSourceSize = { }; | ||
| 1130 | LARGE_INTEGER liTotalCopied = { }; | ||
| 1131 | LARGE_INTEGER liZero = { }; | ||
| 1132 | DWORD dwResult = 0; | ||
| 1133 | |||
| 1134 | hr = FileSizeByHandle(hSource, &liSourceSize.QuadPart); | ||
| 1135 | FileExitOnFailure(hr, "Failed to get size of source."); | ||
| 1136 | |||
| 1137 | if (0 < cbCopy && cbCopy < (DWORD64)liSourceSize.QuadPart) | ||
| 1138 | { | ||
| 1139 | liSourceSize.QuadPart = cbCopy; | ||
| 1140 | } | ||
| 1141 | |||
| 1142 | dwResult = lpProgressRoutine(liSourceSize, liTotalCopied, liZero, liZero, 0, CALLBACK_STREAM_SWITCH, hSource, hTarget, lpData); | ||
| 1143 | switch (dwResult) | ||
| 1144 | { | ||
| 1145 | case PROGRESS_CONTINUE: | ||
| 1146 | break; | ||
| 1147 | |||
| 1148 | case PROGRESS_CANCEL: | ||
| 1149 | fCanceled = TRUE; | ||
| 1150 | fStop = TRUE; | ||
| 1151 | break; | ||
| 1152 | |||
| 1153 | case PROGRESS_STOP: | ||
| 1154 | fStop = TRUE; | ||
| 1155 | break; | ||
| 1156 | |||
| 1157 | case PROGRESS_QUIET: | ||
| 1158 | lpProgressRoutine = NULL; | ||
| 1159 | break; | ||
| 1160 | } | ||
| 1161 | |||
| 1162 | // Set size of the target file. | ||
| 1163 | ::SetFilePointerEx(hTarget, liSourceSize, NULL, FILE_BEGIN); | ||
| 1164 | |||
| 1165 | if (!::SetEndOfFile(hTarget)) | ||
| 1166 | { | ||
| 1167 | FileExitWithLastError(hr, "Failed to set end of target file."); | ||
| 1168 | } | ||
| 1169 | |||
| 1170 | if (!::SetFilePointerEx(hTarget, liZero, NULL, FILE_BEGIN)) | ||
| 1171 | { | ||
| 1172 | FileExitWithLastError(hr, "Failed to reset target file pointer."); | ||
| 1173 | } | ||
| 1174 | |||
| 1175 | // Copy with progress. | ||
| 1176 | while (!fStop && (0 == cbCopy || cbTotalCopied < cbCopy)) | ||
| 1177 | { | ||
| 1178 | cbRead = static_cast<DWORD>((0 == cbCopy) ? countof(rgbData) : min(countof(rgbData), cbCopy - cbTotalCopied)); | ||
| 1179 | if (!::ReadFile(hSource, rgbData, cbRead, &cbRead, NULL)) | ||
| 1180 | { | ||
| 1181 | FileExitWithLastError(hr, "Failed to read from source."); | ||
| 1182 | } | ||
| 1183 | |||
| 1184 | if (cbRead) | ||
| 1185 | { | ||
| 1186 | hr = FileWriteHandle(hTarget, rgbData, cbRead); | ||
| 1187 | FileExitOnFailure(hr, "Failed to write to target."); | ||
| 1188 | |||
| 1189 | cbTotalCopied += cbRead; | ||
| 1190 | |||
| 1191 | if (lpProgressRoutine) | ||
| 1192 | { | ||
| 1193 | liTotalCopied.QuadPart = cbTotalCopied; | ||
| 1194 | dwResult = lpProgressRoutine(liSourceSize, liTotalCopied, liZero, liZero, 0, CALLBACK_CHUNK_FINISHED, hSource, hTarget, lpData); | ||
| 1195 | switch (dwResult) | ||
| 1196 | { | ||
| 1197 | case PROGRESS_CONTINUE: | ||
| 1198 | break; | ||
| 1199 | |||
| 1200 | case PROGRESS_CANCEL: | ||
| 1201 | fCanceled = TRUE; | ||
| 1202 | fStop = TRUE; | ||
| 1203 | break; | ||
| 1204 | |||
| 1205 | case PROGRESS_STOP: | ||
| 1206 | fStop = TRUE; | ||
| 1207 | break; | ||
| 1208 | |||
| 1209 | case PROGRESS_QUIET: | ||
| 1210 | lpProgressRoutine = NULL; | ||
| 1211 | break; | ||
| 1212 | } | ||
| 1213 | } | ||
| 1214 | } | ||
| 1215 | else | ||
| 1216 | { | ||
| 1217 | fStop = TRUE; | ||
| 1218 | } | ||
| 1219 | } | ||
| 1220 | |||
| 1221 | LExit: | ||
| 1222 | if (pbCancel) | ||
| 1223 | { | ||
| 1224 | *pbCancel = fCanceled; | ||
| 1225 | } | ||
| 1226 | |||
| 1227 | if (pcbCopied) | ||
| 1228 | { | ||
| 1229 | *pcbCopied = cbTotalCopied; | ||
| 1230 | } | ||
| 1231 | |||
| 1232 | return hr; | ||
| 1233 | } | ||
| 1234 | |||
| 1235 | |||
| 1236 | /******************************************************************* | ||
| 1109 | FileEnsureCopy | 1237 | FileEnsureCopy |
| 1110 | 1238 | ||
| 1111 | *******************************************************************/ | 1239 | *******************************************************************/ |
