Patch for detecting that destination files cannot be written prior to asking for password. If any file exists, and can be opened for reading, then a simple message is issued for that file and the operation is canceled, e.g: Output file C:\foo.txt exists already If a file exists, but cannot be opened for reading then the reason is added to the error message. For example: Output file C:\foo.txt exists already: Access is denied. diff -urp AESCrypt_source_v309-ORIG/AESCrypt/AESCryptWorkerThreads.cpp AESCrypt_source_v309/AESCrypt/AESCryptWorkerThreads.cpp --- AESCrypt_source_v309-ORIG/AESCrypt/AESCryptWorkerThreads.cpp 2013-03-09 23:13:54.000000000 -0800 +++ AESCrypt_source_v309/AESCrypt/AESCryptWorkerThreads.cpp 2013-09-06 02:16:14.849193800 -0700 @@ -104,23 +104,17 @@ void AESCryptWorkerThreads::ProcessFiles { PasswdDialog dlg; - // Prompt the user for a password - if (dlg.DoModal(::GetActiveWindow(), (encrypt ? 1 : 0)) == IDOK) - { - if (StartThread(file_list, - dlg.passwd, - encrypt) == false) - { - // We were unable to start a thread, so we must clean up - // the file list. - delete file_list; - } - } - else - { - // The user canceled the operation, so delete the file list - delete file_list; - } + if (CheckOverwriteFiles(file_list, encrypt) && // files are not in the way + dlg.DoModal(::GetActiveWindow(), (encrypt ? 1 : 0)) == IDOK && // prompt for password + StartThread(file_list, dlg.passwd, encrypt)) // start thread + { + // Thread started successfully and now owns file_list + return; + } + + // The operation did not proceed so ownership of the file + // list did not pass to the thread; we must delete it. + delete file_list; } /* @@ -283,6 +277,32 @@ DWORD WINAPI ThreadInit(LPVOID lpParamet } /* + * CheckOverwriteFiles + * + * Returns false if any of the destination files of the given + * file list already exist or cannot be used. + */ +bool AESCryptWorkerThreads::CheckOverwriteFiles( + StringList *file_list, + bool encrypt) +{ + for (StringListIter i = file_list->begin(); i != file_list->end(); i++) { + const String &name = *i; + String dest = encrypt ? name + _T(".aes") : name.substr(0, name.length() - 4); + BufferedFile check_file; + DWORD result_code = check_file.OpenFile(dest.c_str(), false, OPEN_EXISTING); + + if (result_code != ERROR_FILE_NOT_FOUND) { + ::ReportError( _T("Output file ") + dest + _T(" exists already"), + result_code); + return false; + } + } + + return true; +} + +/* * EncryptFiles * * This function is called by the worker thread to encrypt a list of files. diff -urp AESCrypt_source_v309-ORIG/AESCrypt/AESCryptWorkerThreads.h AESCrypt_source_v309/AESCrypt/AESCryptWorkerThreads.h --- AESCrypt_source_v309-ORIG/AESCrypt/AESCryptWorkerThreads.h 2013-03-09 23:13:54.000000000 -0800 +++ AESCrypt_source_v309/AESCrypt/AESCryptWorkerThreads.h 2013-09-06 01:43:02.101147000 -0700 @@ -27,6 +27,9 @@ class AESCryptWorkerThreads inline void DoMessageLoop(); + bool CheckOverwriteFiles( StringList *file_list, + bool encrypt); + void EncryptFiles( StringList *file_list, TCHAR *passwd); diff -urp AESCrypt_source_v309-ORIG/AESCrypt/stdafx.h AESCrypt_source_v309/AESCrypt/stdafx.h --- AESCrypt_source_v309-ORIG/AESCrypt/stdafx.h 2013-03-09 23:13:54.000000000 -0800 +++ AESCrypt_source_v309/AESCrypt/stdafx.h 2013-09-06 01:26:21.891136400 -0700 @@ -41,7 +41,9 @@ // STL #include <list> -typedef std::list< std::basic_string<TCHAR> > StringList; +typedef std::basic_string<TCHAR> String; +typedef std::list< String > StringList; +typedef std::list< String >::iterator StringListIter; // Win32 #include <commctrl.h>