| 702 | |
| 703 | #ifdef _WIN32 |
| 704 | bool |
| 705 | is_empty_directory(LPCWSTR path, BOOL bMustReallyBeEmpty, CryptContext *con) |
| 706 | { |
| 707 | bool bret = true; |
| 708 | |
| 709 | WIN32_FIND_DATAW findData; |
| 710 | |
| 711 | HANDLE hFind = INVALID_HANDLE_VALUE; |
| 712 | |
| 713 | DWORD error = 0; |
| 714 | |
| 715 | try { |
| 716 | |
| 717 | wstring enc_path = path; |
| 718 | |
| 719 | const WCHAR *filePath = &enc_path[0]; |
| 720 | |
| 721 | if (!filePath) |
| 722 | throw((int)ERROR_FILE_NOT_FOUND); |
| 723 | |
| 724 | if (enc_path[enc_path.size() - 1] != '\\') |
| 725 | enc_path.push_back('\\'); |
| 726 | |
| 727 | enc_path.push_back('*'); |
| 728 | |
| 729 | filePath = &enc_path[0]; |
| 730 | |
| 731 | hFind = FindFirstFile(filePath, &findData); |
| 732 | |
| 733 | if (hFind == INVALID_HANDLE_VALUE) { |
| 734 | error = GetLastError(); |
| 735 | throw((int)error); |
| 736 | } |
| 737 | |
| 738 | vector<wstring> dummy; |
| 739 | |
| 740 | auto& deletable_files = con ? con->GetDeletableFiles() : dummy; |
| 741 | |
| 742 | auto can_be_deleted = [](const vector<wstring>& deletable_files, LPCWSTR fname) -> bool { |
| 743 | auto count = deletable_files.size(); |
| 744 | for (size_t i = 0; i < count; i++) { |
| 745 | if (lstrcmpi(deletable_files[i].c_str(), fname) == 0) |
| 746 | return true; |
| 747 | } |
| 748 | return false; |
| 749 | }; |
| 750 | |
| 751 | while (hFind != INVALID_HANDLE_VALUE) { |
| 752 | if (wcscmp(findData.cFileName, L"..") != 0 && |
| 753 | wcscmp(findData.cFileName, L".") != 0 && |
| 754 | (bMustReallyBeEmpty || !can_be_deleted(deletable_files, findData.cFileName))) { |
| 755 | throw((int)ERROR_DIR_NOT_EMPTY); |
| 756 | } |
| 757 | if (!FindNextFile(hFind, &findData)) { |
| 758 | break; |
| 759 | } |
| 760 | } |
| 761 | error = GetLastError(); |
no test coverage detected