Example #1
0
void CThread::DelFiles(CString sFolder)
{
	if ((GetFileAttributes(sFolder.C()) & FILE_ATTRIBUTE_DIRECTORY) == 0)
	{
		DeleteFile(sFolder.C());
		return;
	}

	HANDLE hFind = NULL;
	WIN32_FIND_DATA dFind;

	CString sFindFolder = sFolder + TEXT("\\*");
	if ((hFind = FindFirstFile(sFindFolder.C(), &dFind)) != INVALID_HANDLE_VALUE)
	{
		do
		{
			if (lstrcmp(dFind.cFileName, TEXT(".")) == 0 ||
				lstrcmp(dFind.cFileName, TEXT("..")) == 0)
				continue;

			DelFiles(sFolder + TEXT("\\") + dFind.cFileName);
		} while (FindNextFile(hFind, &dFind) != 0);

		FindClose(hFind);
	}

	RemoveDirectory(sFolder.C());
	return;
}
Example #2
0
DWORD CThread::FilesInFolder(CString scFolder)
{
	HANDLE hFind = NULL;
	WIN32_FIND_DATA dFind;

	DWORD res = 0;

	// Ищем все файлы\папки в переданной папке
	CString sFolder = scFolder + TEXT("\\*");
	if ((hFind = FindFirstFile(sFolder.C(), &dFind)) != INVALID_HANDLE_VALUE)
	{
		do
		{
			// Если прервали выполнение - выход из цикла
			if (IsTerminated()) break;

			// Пропускаем специальные папки '.' и '..'
			if (lstrcmp(dFind.cFileName, TEXT(".")) == 0 ||
				lstrcmp(dFind.cFileName, TEXT("..")) == 0)
				continue;

			if ((dFind.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == 0)
				res++;

		} while (FindNextFile(hFind, &dFind) != 0);

		FindClose(hFind);
	}

	return res;
}
Example #3
0
bool COptionsWnd::ArchOnLoadPreset()
{
	// Показываем окно со списком пресетов
	if (DialogBoxParam(Instance, MAKEINTRESOURCE(IDD_LOAD_ARCH_PRESET), GetParent(m_hArchiveSheet),
		StaticLoadPresetDlgProc, (LPARAM) this) == IDOK)
	{
		// выбрали какой-то пресет - очистим информацию о пред. архиаторе
		SendDlgItemMessage(m_hArchiveSheet, IDC_PARAMS, LB_RESETCONTENT, 0, 0);

		TPStrList* pArchiver = m_ArchivePresets[m_bSelPreset];

		// получаем имя и путь к файлу архиватора и раскрываем возможные макросы
		CString sEXE = (*pArchiver)[1];
		DoEnvironmentSubst(sEXE.Buf(), MAX_PATH);

		SetDlgItemText(m_hArchiveSheet, IDC_ARCHIVER_EXE, sEXE.C());
		SetDlgItemText(m_hArchiveSheet, IDC_COMMAND_LINE, (*pArchiver)[2]->C());

		// добавим в список параметров параметры из выбранного пресета
		for (BYTE i = 3; i < pArchiver->Size(); i += 2)
		{
			TStrPair* pStrPair = new TStrPair;
			pStrPair->First = (*pArchiver)[i];
			pStrPair->Second = (*pArchiver)[i + 1]; 

			CString sParamValue = FormatC(TEXT("%%%s%% = %s"), pStrPair->First.C(), pStrPair->Second.C());

			int ind = SendDlgItemMessage(m_hArchiveSheet, IDC_PARAMS, LB_ADDSTRING, 0, (LPARAM) sParamValue.C());
			SendDlgItemMessage(m_hArchiveSheet, IDC_PARAMS, LB_SETITEMDATA, ind, (LPARAM) pStrPair);
		}
	}

	return true;
}
Example #4
0
bool CThread::MaskMatch(CString sStr, CString sMask)
{
	sStr.ToLower();

	LPTSTR cp = 0;
	LPTSTR mp = 0;

	LPTSTR s = new TCHAR[sStr.Length() + 1];
	LPTSTR mask = new TCHAR[sMask.Length() + 1];

	lstrcpy(s, sStr.C());
	lstrcpy(mask, sMask.C());

	for (; *s&& *mask != TEXT('*'); mask++, s++)
		if (*mask != *s && *mask != TEXT('?')) return false;

	for (;;)
	{
		if (!*s)
		{
			while (*mask == TEXT('*')) mask++;
			return !*mask;
		}

		if (*mask == TEXT('*'))
		{
			if (!*++mask) return true;
			
			mp = mask;
			cp=s+1;
			continue;
		}

		if (*mask == *s || *mask == TEXT('?'))
		{
			mask++, s++;
			continue;
		}

		mask = mp; s = cp++;
	}
}
Example #5
0
void COptionsWnd::PresetsOnInit()
{
	m_ArchivePresets.Clear();

	// Загружаем пресеты из файла
	CMemSetTextFile* pArchivers = new CMemSetTextFile(TEXT("Archivers.ini"));

	// читаем каждую секцию, в которой записаны параметры конкретного архиватора
	for (BYTE i = 0; i < pArchivers->GetSectionsCount(); i++)
	{
		// название архиватора == название секции
		CString sSect = pArchivers->GetSection(i);

		if (sSect.Empty()) continue;

		// список с параметрами данного архиватора
		TPStrList* pArchiver = new TPStrList;
		pArchiver->Add(new CString(sSect));

		// читаем путь к файлу архиватора и командную строку
		pArchiver->Add(new CString(pArchivers->GetString(sSect.C(), TEXT("program exe"))));
		pArchiver->Add(new CString(pArchivers->GetString(sSect.C(), TEXT("command line"))));

		// читаем оставшиеся в данной секции записи - "параметр-значение"
		for (BYTE p = 2; p < pArchivers->GetSectionValuesCount(sSect.C()); p++)
		{
			CString sKey = pArchivers->GetKey(sSect.C(), p);

			pArchiver->Add(new CString(sKey));
			pArchiver->Add(new CString(pArchivers->GetString(sSect.C(), sKey.C())));
		}

		// добавляем в список пресетов новый архиватор
		m_ArchivePresets.Add(pArchiver);

		// и добавим в список пресетов
		SendDlgItemMessage(m_hPresets, IDC_PRESETS, LB_ADDSTRING, 0, (LPARAM) (*pArchiver)[0]->C());
	}

	delete pArchivers;
}
Example #6
0
void COptionsWnd::ArchOnEditChange()
{
	int ind = SendDlgItemMessage(m_hArchiveSheet, IDC_PARAMS, LB_GETCURSEL, 0, 0);

	if (ind != LB_ERR)
	{
		TStrPair* pStrPair = (TStrPair*) SendDlgItemMessage(m_hArchiveSheet, IDC_PARAMS, LB_GETITEMDATA, ind, 0);
		SendDlgItemMessage(m_hArchiveSheet, IDC_PARAMS, LB_SETITEMDATA, ind, (LPARAM) NULL);

		// Обновим информацию в listview когда вводят новый параметр\значение
		pStrPair->First = GetDlgItemStr(m_hArchiveSheet, IDC_PARAM);
		pStrPair->Second = GetDlgItemStr(m_hArchiveSheet, IDC_VALUE);

		SendDlgItemMessage(m_hArchiveSheet, IDC_PARAMS, LB_DELETESTRING, ind, 0);
		CString s = FormatC(TEXT("%%%s%% = %s"), pStrPair->First.C(), pStrPair->Second.C());
		SendDlgItemMessage(m_hArchiveSheet, IDC_PARAMS, LB_INSERTSTRING, ind, (LPARAM) s.C());

		SendDlgItemMessage(m_hArchiveSheet, IDC_PARAMS, LB_SETITEMDATA, ind, (LPARAM) pStrPair);
		SendDlgItemMessage(m_hArchiveSheet, IDC_PARAMS, LB_SETCURSEL, ind, 0);
	}
}
Example #7
0
void CThread::DoPrescan(CString scFolder)
{
	m_bLevel++;

	HANDLE hFind = NULL;
	WIN32_FIND_DATA dFind;

	// Ищем все файлы\папки в переданной папке
	CString sFolder = scFolder + TEXT("\\*");
	if ((hFind = FindFirstFile(sFolder.C(), &dFind)) != INVALID_HANDLE_VALUE)
	{
		do
		{
			// Если прервали выполнение - выход из цикла
			if (IsTerminated()) break;

			// Пропускаем специальные папки '.' и '..'
			if (lstrcmp(dFind.cFileName, TEXT(".")) == 0 ||
				lstrcmp(dFind.cFileName, TEXT("..")) == 0)
				continue;

			if ((dFind.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
			{
				m_dwPrescanFolders++;

				// Продолжим предсканирование если не превысилы вложенность папок
				if (m_bLevel < PRESCAN_LEVELS - 1)
					DoPrescan(scFolder + TEXT("\\") + dFind.cFileName);
			}

		} while (FindNextFile(hFind, &dFind) != 0);

		FindClose(hFind);
	}

	m_bLevel--;
}
Example #8
0
bool COptionsWnd::GeneralOnChooseSound()
{
	TCHAR cFileName[MAX_PATH] = {0};

	// Получаем имя муз. файла
	CString sSoundPath = GetDlgItemStr(m_hGeneralSheet, IDC_SOUND);
	TCHAR cSoundPath[MAX_PATH];
	
	if (sSoundPath.Empty())
	{
		// если поле ввода с именем файла пустое - записываем туда папку c:\%windir%\Media
		lstrcpy(cSoundPath, TEXT("%WINDIR%\\Media"));
		DoEnvironmentSubst(cSoundPath, MAX_PATH);	// раскроем макрос 'windir'
	}
	else
		lstrcpy(cSoundPath, sSoundPath.C());

	// Настроим диалог открытия файла на wav файлы
	OPENFILENAME ofn = {0};
	ofn.lStructSize = sizeof(ofn);
	ofn.hwndOwner = GetParent(m_hGeneralSheet);
	ofn.lpstrInitialDir = cSoundPath;
	ofn.lpstrFilter = TEXT("WAV файлы (*.wav)\0*.wav\0");
	ofn.lpstrFile = cFileName;
	ofn.nMaxFile = MAX_PATH;
	ofn.Flags = OFN_ENABLESIZING | OFN_NOCHANGEDIR;

	// Показываем окно для выбором имени муз. файла
	if (GetOpenFileName(&ofn))
	{
		// запишем выбранный файл в поле ввода
		SetDlgItemText(m_hGeneralSheet, IDC_SOUND, cFileName);
	}

	return true;
}
Example #9
0
DWORD WINAPI CThread::ThreadProc(LPVOID lpParameter)
{
	UpdateInfo(true);

	// Скопируем имена папок в новые переменные что бы не затереть исходные значения
	m_sSrcFolder = m_TaskInfo.sSrcFolder;
	m_sDestFolder = m_TaskInfo.sDestFolder;

	DelSlash(m_sSrcFolder);

	// Отформатируем имя папки назначения (раскроем макросы)
	CString sFormatedGenName = FormatDateTime(m_TaskInfo.sDestGenName.C());

	// Сформируем окончательное имя папки назначения
	m_sDestFolder += sFormatedGenName;
	DelSlash(m_sDestFolder);

	// Начало лога - запишем информацию о выполняемой задаче
	AddLog(TEXT("[i] Начало выполнения задачи, параметры:\r\n"));
	AddLog(TEXT("========================================\r\n"));
	AddLog(TEXT("[i] Задача: %s\r\n"), m_TaskInfo.sName.C());
	AddLog(TEXT("[i] Исходная папка: %s\r\n"), m_TaskInfo.sSrcFolder.C());
	AddLog(TEXT("[i] Папка назначения: %s\r\n"), (m_TaskInfo.sDestFolder + m_TaskInfo.sDestGenName).C());
	AddLog(TEXT("[i] Папка назначения: %s\r\n"), m_sDestFolder.C());
	AddLog(TEXT("[i] Включать файлы: %s\r\n"), m_TaskInfo.sIncludeMask.C());
	AddLog(TEXT("[i] Исключать файлы: %s\r\n"), m_TaskInfo.sExcludeMask.C());
    AddLog(TEXT("========================================\r\n"));

	// Если выполнение задачи не прервали - продолжаем
	if (!IsTerminated())
	{
		// Проверяем что бы папка назначения не была подпапкой исходной папки
		if (IsSubFolder(m_TaskInfo.sSrcFolder, m_sDestFolder))
		{
			AddLog(TEXT("[!] Папка назначения является подпапкой исходной папки\r\n"));
			AddLog(TEXT("[x] Невозможно продолжить выполнение задачи\r\n"));
		}
		// Проверка что папка назначения существует (или успешно создана)
		else if (!CheckDestFolder())
		{
			AddLog(TEXT("[!] Не могу создать папку назначения (%s)\r\n"), m_TaskInfo.sDestFolder.C());
			AddLog(TEXT("[x] Невозможно продолжить выполнение задачи\r\n"));
		}
		else
		{
			if (m_TaskInfo.bDoArchive)
			{
				// Получим временное (и уникальное) имя файла во временной папке
				TCHAR cTempPath[MAX_PATH];
				// получим временную папку
				GetTempPath(MAX_PATH, cTempPath);
				// получим уникальное имя для времнного файла, так же система создаст этот файл
				GetTempFileName(cTempPath, TEXT("smb"), 0, (LPTSTR) m_sFileList.Buf());

				if (!PathFileExists(m_sFileList.C()))
				{
					AddLog(TEXT("[!] Не могу создать файл-список (%s)\r\n"), m_sFileList.C());
					AddLog(TEXT("[!] Задача будет выполнена без архивирования\r\n"));
				}
			}

			// Сделаем предв. сканирование исходной папки
			m_bLevel = 0;
			m_dwPrescanFolders = 1;

			// Если работа с подпапками - предсканируем их
			if (m_TaskInfo.bSubFolders)
			{
				DoPrescan(m_sSrcFolder);

				// Узнаем сколько процентов занимает каждая "предсканированная" папка
				m_fPercentInc = (float) 100 / m_dwPrescanFolders;
			}
			// иначе просто подсчитаем кол-во файлов в исходной папке
			else
			{
				DWORD dwFiles = FilesInFolder(m_sSrcFolder);
				m_fPercentInc = (float) 100 / dwFiles;
			}

			UpdateInfo(true);

			MakeList(m_TaskInfo.sIncludeMask, m_aIncludeList);
			MakeList(m_TaskInfo.sExcludeMask, m_aExcludeList);

			// Создадим объект, в который будем записывать файл-лист для архиватора
			m_pFileList = new CMemTextFile();

			// Запускаем копирование файлов
			m_bLevel = 0;
			m_fPercents = 0;
			DoSubFolders(m_sSrcFolder, m_sDestFolder);

			// Сохраним файл-лист из памяти на диск
			m_pFileList->SaveFile(m_sFileList.C());
			delete m_pFileList;

			// Это последний вызов updateinfo, пускай получатели сообщения знают об этом
			m_TaskProgress.bLastInfo = true;
			UpdateInfo(true);

			// если задача не прервана - выполняем архивацию, если надо
			if (!IsTerminated() && m_TaskInfo.bDoArchive)
			{
				if (!PathFileExists(m_sArchiverEXE.C()))
				{
					AddLog(TEXT("[!] Не найден файл архиватора\r\n"));
					AddLog(TEXT("[x] Отмена запуска архиватора\r\n"));
				}											 
				else if (PathFileExists(m_sFileList.C()))
				{
					CString sArch = FormatC(TEXT("\"%s\" %s"), m_sArchiverEXE.C(), ParseArchiverCmdLine().C());
					AddLog(TEXT("[i] Вызов архиватора: %s\r\n"), sArch.C());

					PROCESS_INFORMATION pi = {0};

					STARTUPINFO si = {0};
					si.cb = sizeof(si);

					TCHAR cmd[MAX_PATH];
					lstrcpy(cmd, sArch.C());

					// Создаём процесс - запускаем архиватор
					if (CreateProcess(NULL, cmd, NULL, NULL, FALSE, 0, NULL, NULL, &si, &pi))
					{
						// И ждём пока он не завершит работу
						WaitForSingleObject(pi.hProcess, INFINITE);

						DWORD dwExitCode;
						GetExitCodeProcess(pi.hProcess, &dwExitCode);

						CloseHandle(pi.hProcess);
						CloseHandle(pi.hThread);
    
						AddLog(TEXT("[i] Архиватор завершил работу с кодом %d\r\n"), dwExitCode);

						// Если указано - удалим скопированный файлы (их имена занесены в список)
						if (m_TaskInfo.bArchDelFiles)
						{
							for (int i = 0; i < m_lFileList.Size(); i++)
                                DelFiles(m_lFileList[i]);
						}
					}
					else
						AddLog(TEXT("[!] Ошибка при вызове архиватора\r\n"));
				}

				// Удалим файл-список для архиватора
				DeleteFile(m_sFileList.C());
			}

			AddLog(TEXT("========================================\r\n"));
			if (IsTerminated())
				AddLog(TEXT("[i] Выполнение задачи прервано\r\n"));
			else
				AddLog(TEXT("[i] Выполнение задачи завершено\r\n"));
		}
	}

	// пошлём сообщения всем подписавшимся слушателям что работа завершена
	for (int i = 0; i < m_ProgressListenrs.Size(); i++)
		PostMessage(m_ProgressListenrs[i], RegisterWindowMessage(ThreadDoneMessage), 0, 0);

	return 0;
}
Example #10
0
CString CThread::ParseArchiverCmdLine()
{
	WORD wPos = 0;
	WORD wResPos = 0;
	WORD wLen = m_sArchiverCmdLine.Length();

	TCHAR res[MAX_PATH] = {0};

	while (wPos < wLen)
	{
		if (m_sArchiverCmdLine[wPos] != TEXT('%'))
		{
			res[wResPos] = m_sArchiverCmdLine[wPos];
			wPos++;
			wResPos++;
		}
		else if (m_sArchiverCmdLine[wPos] == TEXT('%') && 
			wPos + 1 < wLen && m_sArchiverCmdLine[wPos + 1] == TEXT('%'))
		{
			// Двойной процент ('%%') считаем за один, не макрос
			res[wResPos] = TEXT('%');
			wPos += 2;
			wResPos++;
		}
		else if (m_sArchiverCmdLine[wPos] == TEXT('%'))
		{
			CString sMacro;

			wPos++;
			WORD wMacroStart = wPos;

			while (wPos < wLen)
			{
				if (m_sArchiverCmdLine[wPos] != TEXT('%'))
					wPos++;
                else if (m_sArchiverCmdLine[wPos] == TEXT('%'))
				{	   
					sMacro = m_sArchiverCmdLine.SubStr(wMacroStart, wPos - wMacroStart).ToLowerNew();
					CString sMacroValue;

					while (true)
					{
						if ((sMacro[0] >= TEXT('a') && sMacro[0] <= TEXT('z')) || (sMacro[0] >= TEXT('A') && sMacro[0] <= TEXT('Z')))
						{
							break;
						}
						else
						{
							sMacroValue += sMacro[0];
							sMacro.Delete(0, 1);
						}
					}							

					if (sMacro == TEXT("compress"))
					{
						CString sCompress = FormatC(TEXT("compress%d"), m_TaskInfo.bArchCompress);
						sMacroValue += GetMacroValue(sCompress);

						lstrcat(res, sMacroValue.C());
						wResPos = lstrlen(res);
						wPos++;
					}
					else if (sMacro == TEXT("sfx") && m_TaskInfo.bArchSFX)
					{
						sMacroValue += GetMacroValue(TEXT("sfx"));

						lstrcat(res, sMacroValue.C());
						wResPos = lstrlen(res);
						wPos++;
					}
					else if (sMacro == TEXT("lock") && m_TaskInfo.bArchLock)
					{
						sMacroValue += GetMacroValue(TEXT("lock"));

						lstrcat(res, sMacroValue.C());
						wResPos = lstrlen(res);
						wPos++;
					}
					else if (sMacro == TEXT("taskcmd"))
					{
						sMacroValue += m_TaskInfo.sArchTaskCmd;

						lstrcat(res, sMacroValue.C());
						wResPos = lstrlen(res);
						wPos++;
					}
					else if (sMacro == TEXT("filelist"))
					{
						sMacroValue += TEXT("\"");
						sMacroValue += m_sFileList;
						sMacroValue += TEXT("\"");

						lstrcat(res, sMacroValue.C());
						wResPos = lstrlen(res);
						wPos++;
					}
					else if (sMacro == TEXT("archive"))
					{
						sMacroValue += TEXT("\"");
						sMacroValue += m_sDestFolder;
						sMacroValue += TEXT("\"");

						lstrcat(res, sMacroValue.C());
						wResPos = lstrlen(res);
						wPos++;
					}
					else 
						wPos++;

					break;
				}
			}
		}
	}

	return res;
}
Example #11
0
void CThread::DoSubFolders(CString sFolder, CString sBackupFolder)
{
	m_bLevel++;	// очередной раз вошли рекурсивно в себя

	HANDLE hFind = NULL;
	WIN32_FIND_DATA dFind;

	CString strFolder = sFolder + TEXT("\\*");

	bool bError = false;
	DWORD dwFiles = 0;		// кол-во файлов в текущей папке
	DWORD dwFolders = 0;	// кол-во папок в текущей папке

	// Папки куда копировать файлы несуществует, попробуем создать
	if (!PathFileExists(sBackupFolder.C()))
	{
		// создать папку не вышло, ошибка
		if (CreateDirectory(sBackupFolder.C(), NULL) == FALSE)
		{
			AddLog(TEXT("[!] Не могу создать папку \'%s\'! Пропуск папки %s\r\n"), sBackupFolder.C(), sFolder.C());
			bError = true;
		}
	}

	// Не работаем дальше на текущем уровне вложенности если произошла ошибка - нельзя создать папку назначения
	if ((!bError) && (hFind = FindFirstFile(strFolder.C(), &dFind)) != INVALID_HANDLE_VALUE)
	{
		do
		{
			if (IsTerminated()) break;

			// Skip '.' and '..' folders
			if (lstrcmp(dFind.cFileName, TEXT(".")) == 0 ||
				lstrcmp(dFind.cFileName, TEXT("..")) == 0)
				continue;

			// Работаем с папкой
			if ((dFind.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0)
			{
				if (!m_TaskInfo.bSubFolders) continue;

				// Добавим папку в файл-список
				if (m_bLevel == 1)
				{
					m_pFileList->SetLine(CString(sBackupFolder + TEXT("\\") + dFind.cFileName).C());	
					m_lFileList.Add(sBackupFolder + TEXT("\\") + dFind.cFileName);
				}

				// Формируем имя след. папки для обработки (вложенной)
				CString strNewFolder = sFolder + TEXT("\\") + dFind.cFileName;
				CString sNewBackupFolder = sBackupFolder + TEXT("\\") + dFind.cFileName;

				// Обработали ещё одну папку на текущем уровне вложенности
				dwFolders++;

				// Вызываемся рекурсивно - обрабатываем вложенную папку
				DoSubFolders(strNewFolder, sNewBackupFolder);
			}
			// Работаем с файлом
			else
			{
				// Увеличим кол-во обработанных файлов
				m_TaskProgress.dwProceedFiles++;

				// Сперва проверим удовлетворяет ли имя файла с "маской исключения"
				if (MaskListMath(CString(dFind.cFileName), m_aExcludeList))
					// если да - увеличим число пропущенных файлов
					m_TaskProgress.dwExcludedFiles++;
				// иначе, если имя файла удовлетворяет "маске включения" - работаем с ним
				else if (MaskListMath(CString(dFind.cFileName), m_aIncludeList))
				{
					// Формируем полные имена файлов - откуда и куда копировать
					CString sFileCopyFrom = sFolder + TEXT("\\") + dFind.cFileName;
					CString sFileCopyTo = sBackupFolder + TEXT("\\") + dFind.cFileName;

					// Если файл уже есть в папке назначения - удалим его (как будто он старый)
					if (PathFileExists(sFileCopyTo.C()))
						DeleteFile(sFileCopyTo.C());

					// Скопируем файл из исходной папки в папку назначения
					if (!CopyFile(sFileCopyFrom.C(), sFileCopyTo.C(), TRUE))
					{
						// ошибка при копировании
						m_TaskProgress.dwErrors++;
						AddLog(TEXT("[!] Ошибка при копировании файла \'%s\'!\r\n"), sFileCopyFrom.C());
					}
					else
					{
						HANDLE hFile = CreateFile(sFileCopyFrom.C(), GENERIC_READ, 0, NULL, OPEN_EXISTING, NULL, NULL);
						if (hFile != INVALID_HANDLE_VALUE)
						{
							m_TaskProgress.i64FinishedBytes += GetFileSize(hFile, NULL);
							CloseHandle(hFile);
						}

						// Добавим файл в файл-список, если он скопировался успешно
						if (m_bLevel == 1)
						{
							m_pFileList->SetLine(CString(sBackupFolder + TEXT("\\") + dFind.cFileName).C());
							m_lFileList.Add(sBackupFolder + TEXT("\\") + dFind.cFileName);
						}
					}

					// Обработали ещё один файл - увеличим счётчики
					m_TaskProgress.dwIncludedFiles++;
                    dwFiles++;
				}
				// иначе, если имя файла не удовлетворяет ни одной из масок - записываем его как необработанный
				else
					m_TaskProgress.dwExcludedFiles++;

				// Обработали файл - увеличим процент выполнения
				if (!m_TaskInfo.bSubFolders)
					m_fPercents += m_fPercentInc;

				UpdateInfo();
			}

		} while (FindNextFile(hFind, &dFind) != 0);

		FindClose(hFind);
	}

	// Если нет ошибки и уровень вложенности менее заданного числа - добавим в лог эту папку
	if (!bError && m_bLevel <= 2)
		AddLog(TEXT("[i] Папка \'%s\' обработана; файлов: %d, папок: %d\r\n"), sFolder.C(), dwFiles, dwFolders);

	// Посчитаем процент выполнения задачи
	if (m_TaskInfo.bSubFolders && m_bLevel <= PRESCAN_LEVELS)
		m_fPercents += m_fPercentInc;

	// Обработали очередную папку
	m_TaskProgress.dwProceedFolders++;
	UpdateInfo();

	// поднимаемся на уровень выше
	m_bLevel--;
}