#include #include #include #include #include #define MMAX_PATH MAX_PATH // название сервиса #define serviceName _T("aaaa_ARCHIVER") // путь к конфигу #define configFile _T("C:/Users/user/Desktop/LIBZIP_ARCHIEVER_SERVICE/config.txt") // путь к файлу с логами #define logfileName _T("C:/Users/user/Desktop/LIBZIP_ARCHIEVER_SERVICE/log.txt") // путь к исполняемому файлу #define Path _T("C:/Users/user/Desktop/LIBZIP_ARCHIEVER_SERVICE/x64/Debug/test_libzip_library.exe") // функции для архивирования int isMatch(wchar_t* str, wchar_t* pattern); void consoleEncodingNormalize(void); void zipDir(wchar_t* zipDirPath, wchar_t* zipDirArchive, wchar_t** masks); void _zipDir(wchar_t* directory, zip_t* zipArchive, wchar_t* baseDirectory, wchar_t** masks); int readConfig(const wchar_t* filename, wchar_t* zipDirPath, wchar_t* zipDirArchive, wchar_t** masks); // функции для работы сервиса void ServiceMain(DWORD argc, LPTSTR* argv); void ControlHandler(DWORD request); int addLogMessage(wchar_t* str, int code); int installService(); int removeService(); int startService(); int initService(); enum ERRORS { ALLOC_COLS_ERR = -20, ALLOC_ROWS_ERR, CONF_READ_ERR }; #define MMAX_ROWS 20 // максимальное кол-во масок #define COLS MMAX_PATH SERVICE_STATUS serviceStatus; SERVICE_STATUS_HANDLE hStatus; LPTSTR servicePath = Path; HANDLE hServiceEvent; int _tmain(int argc, _TCHAR* argv[]) { consoleEncodingNormalize(); if (argc - 1 == 0) { SERVICE_TABLE_ENTRY ServiceTable[] = { {(LPWSTR)serviceName, (LPSERVICE_MAIN_FUNCTION)ServiceMain}, {NULL, NULL} }; if (!StartServiceCtrlDispatcher(ServiceTable)) { addLogMessage(L"Error: StartServiceCtrlDispatcher", GetLastError()); } } else if (wcscmp(argv[argc - 1], _T("stop")) == 0) { // осталось stopService(); } else if (wcscmp(argv[argc - 1], _T("install")) == 0) { installService(); } else if (wcscmp(argv[argc - 1], _T("remove")) == 0) { removeService(); } else if (wcscmp(argv[argc - 1], _T("start")) == 0) { startService(); } } void ServiceMain(DWORD argc, LPTSTR* argv) { addLogMessage(L"\nЯ в ServiceMain", 1); int error; int i = 0; serviceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; serviceStatus.dwCurrentState = SERVICE_START_PENDING; serviceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN; serviceStatus.dwWin32ExitCode = 0; serviceStatus.dwServiceSpecificExitCode = 0; serviceStatus.dwCheckPoint = 0; serviceStatus.dwWaitHint = 0; hStatus = RegisterServiceCtrlHandler(serviceName, (LPHANDLER_FUNCTION)ControlHandler); if (hStatus == (SERVICE_STATUS_HANDLE)0) { return; } error = initService(); if (error) { serviceStatus.dwCurrentState = SERVICE_STOPPED; serviceStatus.dwWin32ExitCode = -1; SetServiceStatus(hStatus, &serviceStatus); return; } serviceStatus.dwCurrentState = SERVICE_RUNNING; SetServiceStatus(hStatus, &serviceStatus); wchar_t zipDirPath[MMAX_PATH]; wchar_t zipDirArchive[MMAX_PATH]; wchar_t** masks; // аллокация памяти под маски if ((masks = (wchar_t**)calloc(MMAX_ROWS, sizeof(wchar_t*))) != NULL) { for (int i = 0; i < MMAX_ROWS; i++) { if ((masks[i] = (wchar_t*)calloc(COLS, sizeof(wchar_t))) == NULL) { exit(ALLOC_COLS_ERR); } } } else { exit(ALLOC_ROWS_ERR); } if (readConfig(configFile, zipDirPath, zipDirArchive, masks) == 0) { exit(CONF_READ_ERR); } addLogMessage(zipDirPath, 228); addLogMessage(zipDirArchive, 228); while (serviceStatus.dwCurrentState == SERVICE_RUNNING) { addLogMessage(L"Работает", 0); zipDir(zipDirPath, zipDirArchive, masks); // addLogMessage(L"Vishel iz zipDir", 228); Sleep(5000); i++; } // mem clear for (int i = 0; i < MMAX_ROWS; i++) { free((void*)masks[i]); } free((void*)masks); return; } int getConfigData(FILE* file, wchar_t* p) { addLogMessage(L"[ЧЕКПОИНТ] Я в getConfigData", 0); wchar_t buffer[MMAX_PATH] = { 0 }; if (fgetws(buffer, MMAX_PATH, file) != NULL) { addLogMessage(L"[ЧЕКПОИНТ] getConfigData", 0); addLogMessage(buffer, 0); addLogMessage(L"\n", 0); wchar_t* t = wcschr(buffer, L' '); if (t) { wcscpy_s(p, MMAX_PATH, t + 1); size_t len = wcslen(p); if (len > 0 && p[len - 1] == L'\n') { p[len - 1] = L'\0'; } } return 1; } else { addLogMessage(L"[ОШИБКА] fgetws(buffer, MMAX_PATH, file) == NULL", 0); return 0; } } // // Функция для чтения конфигурационного файла int readConfig( const wchar_t* filename, wchar_t* zipDirPath, wchar_t* zipDirArchive, wchar_t** masks) { FILE* file; _wfopen_s(&file, filename, L"r, ccs=UTF-8"); // Используем кодировку UTF-8 чтобы русские слова корректно читать if (file == NULL) { return 0; // Изменено на false } getConfigData(file, zipDirPath); getConfigData(file, zipDirArchive); int i = -1; while (getConfigData(file, masks[++i]) && (i < MMAX_ROWS)); // маски считываем пока они есть. построчно fclose(file); return 1; } // // бэкап директории по пути к ней void zipDir(wchar_t* zipDirPath, wchar_t* zipDirArchive, wchar_t** masks) { // Создаем ZIP-архив addLogMessage(L"zashel v zipDir", 228); char cArchivePath[MMAX_PATH] = { 0 }; wchar_t archivePath[MMAX_PATH] = { 0 }; // формирование полного пути к архиву addLogMessage(L"Перед формированием пути", 228); errno_t err; addLogMessage(zipDirArchive, 1); err = wcsncpy_s(archivePath, MMAX_PATH, zipDirArchive, wcslen(zipDirArchive)); if (err != 0) { // Обработка ошибки addLogMessage(L"wcsncpy_s error:", err); return; // или exit(1); } err = wcscat_s(archivePath, MMAX_PATH, wcsrchr(zipDirPath, TEXT('/'))); if (err != 0) { // Обработка ошибки addLogMessage(L"wcscat_s error:", err); return; // или exit(1); } err = wcscat_s(archivePath, MMAX_PATH, L".zip"); if (err != 0) { // Обработка ошибки addLogMessage(L"wcscat_s error:", err); return; // или exit(1); } addLogMessage(L"sformiroval put", 228); //_tprintf(TEXT("[ПОЛНЫЙ ПУТЬ К АРХИВУ] %s\n"), archivePath); WideCharToMultiByte(CP_UTF8, 0, archivePath, -1, cArchivePath, MMAX_PATH, NULL, NULL); // Проверка на существование архива zip_t* zipArchive = zip_open(cArchivePath, ZIP_CREATE, &err); if (!zipArchive) { //_tprintf(L"Не удалось открыть ZIP файл\n"); addLogMessage(L"ne udalos otkrit zipfile", 228); return; } addLogMessage(L"zipfile sozdan, zahodim v _zipDir", 228); //_tprintf(L"ZIP файл был создан по пути: %s\n", archivePath); _zipDir(zipDirPath, zipArchive, zipDirPath, masks); zip_close(zipArchive); } void _zipDir(wchar_t* directory, zip_t* zipArchive, wchar_t* baseDirectory, wchar_t** masks) { WIN32_FIND_DATA FindFileData; HANDLE hFind; // Формируем строку для поиска файлов и директорий wchar_t searchPath[MMAX_PATH] = { 0 }; //_snwprintf_s(searchPath, MMAX_PATH, TEXT("%s/*.*"), directory); wcscat_s(searchPath, MMAX_PATH, directory); wcscat_s(searchPath, MMAX_PATH, L"/*.*"); //_tprintf(L"searchPath = %s\n", searchPath); hFind = FindFirstFile(searchPath, &FindFileData); if (hFind == INVALID_HANDLE_VALUE) { //printf("FindFirstFile вернулось с ошибкой: (%d)\n", GetLastError()); return; } else { do { // Игнорируем папки "." и ".." if (_tcscmp(FindFileData.cFileName, TEXT(".")) != 0 && _tcscmp(FindFileData.cFileName, TEXT("..")) != 0) { wchar_t filePath[MMAX_PATH] = { 0 }; //_snwprintf_s(filePath, MMAX_PATH, TEXT("%s/%s"), directory, FindFileData.cFileName); wcscat_s(filePath, MMAX_PATH, directory); wcscat_s(filePath, MMAX_PATH, L"/"); wcscat_s(filePath, MMAX_PATH, FindFileData.cFileName); if (FindFileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { //_tprintf(TEXT("[ДИРЕКТОРИЯ] %s\n"), FindFileData.cFileName); // Рекурсивный вызов для поддиректории _zipDir(filePath, zipArchive, baseDirectory, masks); } else { //_tprintf(TEXT("[ФАЙЛ] %s\n"), FindFileData.cFileName); // проверка на совпадения по маскам for (int i = 0; i < MMAX_ROWS; ++i) { if (masks[i][0] && isMatch(FindFileData.cFileName, masks[i])) { // есть совпадение с i-й маской break; // выходим из цикла во внешний код } // иначе если дальше нет масок // (нулевый первый символ маски означает что там память, заполненная нулями) else if (!masks[i][0]) { goto CONTINUE; // continue для внешнего цикла do } // иначе смотрим след маску } char cfilePath[MMAX_PATH], cfileName[MMAX_PATH]; // Преобразую юникодный путь в обычный байтовый, т.к. libzip`ные ф-ии требуют char* WideCharToMultiByte(CP_UTF8, 0, filePath, -1, cfilePath, MMAX_PATH, NULL, NULL); // Получаем относительный путь для сохранения структуры директории в архиве wchar_t relativePath[MMAX_PATH]; _snwprintf_s(relativePath, MMAX_PATH, TEXT("%s"), filePath + wcslen(baseDirectory) + 1); WideCharToMultiByte(CP_UTF8, 0, relativePath, -1, cfileName, MMAX_PATH, NULL, NULL); // Добавляем файл в архив zip_source_t* source = zip_source_file(zipArchive, cfilePath, 0, 0); if (source == NULL || zip_file_add(zipArchive, cfileName, source, ZIP_FL_OVERWRITE) < 0) { //printf("Ошибка добавления файла %ls в архив: %s\n", filePath, zip_strerror(zipArchive)); if (source) { zip_source_free(source); } } } } CONTINUE:; } while (FindNextFile(hFind, &FindFileData) != 0); FindClose(hFind); } } void consoleEncodingNormalize(void) { // ОС вернет свою кодировку и она будет установлена для консоли setlocale(LC_ALL, "ru_RU.UTF-8"); } int isMatch(wchar_t* str, wchar_t* pattern) { const wchar_t* s = str; const wchar_t* p = pattern; const wchar_t* star = NULL; const wchar_t* ss = NULL; while (*s) { if (*p == '?' || *p == *s) { // Символ совпадает или паттерн - ? s++; p++; } else if (*p == '*') { // Найден * в паттерне star = p++; ss = s; } else if (star) { // Предыдущий * совпадает с одним символом p = star + 1; s = ++ss; } else { return 0; } } // Проверка оставшихся символов в паттерне while (*p == '*') { p++; } return *p == '\0'; } // int installService() { SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE); if (!hSCManager) { addLogMessage(L"Error: Can't open Service Control Manager", GetLastError()); return -1; } SC_HANDLE hService = CreateService( hSCManager, serviceName, serviceName, SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START, SERVICE_ERROR_NORMAL, servicePath, NULL, NULL, NULL, NULL, NULL ); if (!hService) { int err = GetLastError(); switch (err) { case ERROR_ACCESS_DENIED: addLogMessage(L"Error: ERROR_ACCESS_DENIED", err); break; case ERROR_CIRCULAR_DEPENDENCY: addLogMessage(L"Error: ERROR_CIRCULAR_DEPENDENCY", err); break; case ERROR_DUPLICATE_SERVICE_NAME: addLogMessage(L"Error: ERROR_DUPLICATE_SERVICE_NAME", err); break; case ERROR_INVALID_HANDLE: addLogMessage(L"Error: ERROR_INVALID_HANDLE", err); break; case ERROR_INVALID_NAME: addLogMessage(L"Error: ERROR_INVALID_NAME", err); break; case ERROR_INVALID_PARAMETER: addLogMessage(L"Error: ERROR_INVALID_PARAMETER", err); break; case ERROR_INVALID_SERVICE_ACCOUNT: addLogMessage(L"Error: ERROR_INVALID_SERVICE_ACCOUNT", err); break; case ERROR_SERVICE_EXISTS: addLogMessage(L"Error: ERROR_SERVICE_EXISTS", err); break; default: addLogMessage(L"Error: Undefined", err); } CloseServiceHandle(hSCManager); return -1; } CloseServiceHandle(hService); CloseServiceHandle(hSCManager); addLogMessage(L"Success install service!", 0); return 0; } int removeService() { SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); if (!hSCManager) { addLogMessage(L"Error: Can't open Service Control Manager", GetLastError()); return -1; } SC_HANDLE hService = OpenService(hSCManager, serviceName, SERVICE_STOP | DELETE); if (!hService) { addLogMessage(L"Error: Can't remove service", GetLastError()); CloseServiceHandle(hSCManager); return -1; } DeleteService(hService); CloseServiceHandle(hService); CloseServiceHandle(hSCManager); addLogMessage(L"Success remove service!", 0); return 0; } int startService() { SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE); SC_HANDLE hService = OpenService(hSCManager, serviceName, SERVICE_START); if (!StartService(hService, 0, NULL)) { CloseServiceHandle(hSCManager); addLogMessage(L"Error: Can't start service", GetLastError()); return -1; } CloseServiceHandle(hService); CloseServiceHandle(hSCManager); return 0; } int stopService() { SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE); SC_HANDLE hService = OpenService(hSCManager, serviceName, SERVICE_STOP); SERVICE_STATUS ss; if (!ControlService(hService, SERVICE_CONTROL_STOP, &ss)) { CloseServiceHandle(hSCManager); addLogMessage(L"Невозможно остановить сервис", 0); return -1; } addLogMessage(L"Сервис успешно остановлен", 0); CloseServiceHandle(hService); CloseServiceHandle(hSCManager); return 0; } int initService() { int result = addLogMessage(L"Service started!", 0); return result; } void ControlHandler(DWORD request) { switch (request) { case SERVICE_CONTROL_STOP: addLogMessage(L"Stopped.", 0); serviceStatus.dwWin32ExitCode = 0; serviceStatus.dwCurrentState = SERVICE_STOPPED; SetServiceStatus(hStatus, &serviceStatus); return; case SERVICE_CONTROL_SHUTDOWN: addLogMessage(L"Shutdown.", 0); serviceStatus.dwWin32ExitCode = 0; serviceStatus.dwCurrentState = SERVICE_STOPPED; SetServiceStatus(hStatus, &serviceStatus); return; default: break; } SetServiceStatus(hStatus, &serviceStatus); return; } // только на английском сообщения сюда передавать int addLogMessage(wchar_t* str, int code) { errno_t err; FILE* log; // Открываем файл для добавления (append) с кодировкой UTF-8 if ((err = _wfopen_s(&log, logfileName, L"a, ccs=UTF-8")) != 0) { return -1; // Ошибка при открытии файла } if (log == NULL) return -1; // Записываем сообщение в лог fwprintf(log, L"[code: %d] %s\n", code, str); // Используем fwprintf для записи wstring fclose(log); return 0; // Успешное выполнение }