UCHEBA/5 СЕМ/БСИТ/2 ЛАБА/service.c

526 lines
18 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include <Windows.h>
#include <stdio.h>
#include <tchar.h>
#include <locale.h>
#include <zip.h>
#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; // Успешное выполнение
}