aboutsummaryrefslogtreecommitdiff
path: root/src/dutil/fileutil.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/dutil/fileutil.cpp')
-rw-r--r--src/dutil/fileutil.cpp128
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*******************************************************************/
1112extern "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
1221LExit:
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*******************************************************************/