////////////////////////////////////////////////////////////////////////// Util_CopyFile() (moves files too) Returns the number of files that could not be copied or moved due to error. //////////////////////////////////////////////////////////////////////////
| 1535 | // Returns the number of files that could not be copied or moved due to error. |
| 1536 | /////////////////////////////////////////////////////////////////////////////// |
| 1537 | int Line::Util_CopyFile(LPCTSTR szInputSource, LPCTSTR szInputDest, bool bOverwrite, bool bMove, DWORD &aLastError) |
| 1538 | { |
| 1539 | TCHAR szSource[T_MAX_PATH]; |
| 1540 | TCHAR szDest[T_MAX_PATH]; |
| 1541 | TCHAR szDestPattern[MAX_PATH]; |
| 1542 | |
| 1543 | // Get local version of our source/dest with full path names, strip trailing \s |
| 1544 | // and normalize the path separator (replace / with \). |
| 1545 | Util_GetFullPathName(szInputSource, szSource, _countof(szSource)); |
| 1546 | Util_GetFullPathName(szInputDest, szDest, _countof(szDest)); |
| 1547 | |
| 1548 | // If the source or dest is a directory then add *.* to the end |
| 1549 | if (Util_IsDir(szSource)) |
| 1550 | _tcscat(szSource, _T("\\*.*")); |
| 1551 | if (Util_IsDir(szDest)) |
| 1552 | _tcscat(szDest, _T("\\*.*")); |
| 1553 | |
| 1554 | WIN32_FIND_DATA findData; |
| 1555 | HANDLE hSearch = FindFirstFile(szSource, &findData); |
| 1556 | if (hSearch == INVALID_HANDLE_VALUE) |
| 1557 | { |
| 1558 | aLastError = GetLastError(); // Set even in this case since FindFirstFile can fail due to actual errors, such as an invalid path. |
| 1559 | return StrChrAny(const_cast<LPTSTR>(szInputSource), _T("?*")) ? 0 : 1; // Indicate failure only if there were no wildcards. |
| 1560 | } |
| 1561 | aLastError = 0; // Set default. Overridden only when a failure occurs. |
| 1562 | |
| 1563 | // Otherwise, loop through all the matching files. |
| 1564 | |
| 1565 | // Locate the filename/pattern, which will be overwritten on each iteration. |
| 1566 | LPTSTR source_append_pos = _tcsrchr(szSource, '\\') + 1; |
| 1567 | LPTSTR dest_append_pos = _tcsrchr(szDest, '\\') + 1; |
| 1568 | size_t space_remaining = _countof(szSource) - (source_append_pos - szSource) - 1; |
| 1569 | |
| 1570 | // Copy destination filename or pattern, since it will be overwritten. |
| 1571 | tcslcpy(szDestPattern, dest_append_pos, _countof(szDestPattern)); |
| 1572 | |
| 1573 | int failure_count = 0; |
| 1574 | LONG_OPERATION_INIT |
| 1575 | |
| 1576 | do |
| 1577 | { |
| 1578 | // Since other script threads can interrupt during LONG_OPERATION_UPDATE, it's important that |
| 1579 | // this function and those that call it not refer to sArgDeref[] and sArgVar[] anytime after an |
| 1580 | // interruption becomes possible. This is because an interrupting thread usually changes the |
| 1581 | // values to something inappropriate for this thread. |
| 1582 | LONG_OPERATION_UPDATE |
| 1583 | |
| 1584 | // Make sure the returned handle is a file and not a directory before we |
| 1585 | // try and do copy type things on it! |
| 1586 | if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) // dwFileAttributes should never be invalid (0xFFFFFFFF) in this case. |
| 1587 | continue; |
| 1588 | |
| 1589 | if (_tcslen(findData.cFileName) > space_remaining) // v1.0.45.03: Basic check in case of files whose full spec is over 260 characters long. |
| 1590 | { |
| 1591 | aLastError = ERROR_BUFFER_OVERFLOW; // MSDN: "The file name is too long." |
| 1592 | ++failure_count; |
| 1593 | continue; |
| 1594 | } |
nothing calls this directly
no test coverage detected