| 1250 | } |
| 1251 | |
| 1252 | SC::Result SC::FileSystem::Operations::Internal::copyDirectoryRecursive(const wchar_t* source, |
| 1253 | const wchar_t* destination, |
| 1254 | FileSystemCopyFlags flags) |
| 1255 | { |
| 1256 | // Create destination directory if it doesn't exist |
| 1257 | if (::CreateDirectoryW(destination, nullptr) == FALSE) |
| 1258 | { |
| 1259 | if (::GetLastError() != ERROR_ALREADY_EXISTS) |
| 1260 | { |
| 1261 | return Result::Error("copyDirectoryRecursive: Failed to create destination directory"); |
| 1262 | } |
| 1263 | } |
| 1264 | |
| 1265 | // Prepare search pattern |
| 1266 | wchar_t searchPattern[StringPath::MaxPath + 6 + 1] = {}; |
| 1267 | if (::swprintf_s(searchPattern, StringPath::MaxPath + 6 + 1, L"%s\\*", source) == -1) |
| 1268 | { |
| 1269 | return Result::Error("copyDirectoryRecursive: Path too long"); |
| 1270 | } |
| 1271 | |
| 1272 | WIN32_FIND_DATAW findData; |
| 1273 | |
| 1274 | HANDLE hFind = ::FindFirstFileW(searchPattern, &findData); |
| 1275 | if (hFind == INVALID_HANDLE_VALUE) |
| 1276 | { |
| 1277 | return Result::Error("copyDirectoryRecursive: Failed to enumerate directory"); |
| 1278 | } |
| 1279 | auto deferClose = MakeDeferred([&]() { ::FindClose(hFind); }); |
| 1280 | |
| 1281 | do |
| 1282 | { |
| 1283 | // Skip . and .. entries |
| 1284 | if (::wcscmp(findData.cFileName, L".") == 0 || ::wcscmp(findData.cFileName, L"..") == 0) |
| 1285 | continue; |
| 1286 | |
| 1287 | // Build full paths |
| 1288 | wchar_t sourcePath[StringPath::MaxPath + 6 + 1] = {}; |
| 1289 | wchar_t destPath[StringPath::MaxPath + 6 + 1] = {}; |
| 1290 | if (::swprintf_s(sourcePath, StringPath::MaxPath + 6 + 1, L"%s\\%s", source, findData.cFileName) == -1 || |
| 1291 | ::swprintf_s(destPath, StringPath::MaxPath + 6 + 1, L"%s\\%s", destination, findData.cFileName) == -1) |
| 1292 | { |
| 1293 | return Result::Error("copyDirectoryRecursive: Path too long"); |
| 1294 | } |
| 1295 | |
| 1296 | if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) |
| 1297 | { |
| 1298 | // Recursively copy subdirectory |
| 1299 | SC_TRY(copyDirectoryRecursive(sourcePath, destPath, flags)); |
| 1300 | } |
| 1301 | else |
| 1302 | { |
| 1303 | // Copy file |
| 1304 | DWORD copyFlags = COPY_FILE_FAIL_IF_EXISTS; |
| 1305 | if (flags.overwrite) |
| 1306 | copyFlags &= ~COPY_FILE_FAIL_IF_EXISTS; |
| 1307 | |
| 1308 | if (::CopyFileExW(sourcePath, destPath, nullptr, nullptr, nullptr, copyFlags) == FALSE) |
| 1309 | { |
nothing calls this directly
no test coverage detected