diff options
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 | *******************************************************************/ |