feat: Рабочая версия сервиса

master
Nihonium 1 week ago
parent 53cc2a08ce
commit 72bf8d917a

@ -12,7 +12,7 @@ endif()
project ("shell-server") project ("shell-server")
# Добавьте источник в исполняемый файл этого проекта. # Добавьте источник в исполняемый файл этого проекта.
add_executable (shell-server "main.c" "server.c" "server.h" "client.c" "client.h") add_executable (shell-server "main.c" "server.c" "server.h" "client.c" "client.h" "service.c" "service.h")
if (CMAKE_VERSION VERSION_GREATER 3.12) if (CMAKE_VERSION VERSION_GREATER 3.12)
set_property(TARGET shell-server PROPERTY CXX_STANDARD 20) set_property(TARGET shell-server PROPERTY CXX_STANDARD 20)

@ -0,0 +1,135 @@
#include "client.h"
#include "server.h"
#define DEFAULT_BUFLEN 512
SOCKET ConnectSocket = INVALID_SOCKET;
DWORD WINAPI ClientWriteToPipe(LPDWORD dummy);
DWORD WINAPI ClientReadFromPipe(LPDWORD dummy);
VOID StartShellClient(TCHAR *ServerIP) {
WSADATA wsaData;
int iResult;
struct addrinfo* result = NULL, *ptr = NULL, hints;
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed: %d\n", iResult);
return 1;
}
// Create socket for client
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
// Resolve the server address and port
iResult = getaddrinfo(ServerIP, DEFAULT_PORT, &hints, &result);
if (iResult != 0) {
printf("getaddrinfo failed: %d\n", iResult);
WSACleanup();
return 1;
}
// Attempt to connect to the first address returned by the call to getaddrinfo
ptr = result;
// Create a SOCKET for connecting to server
ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype,
ptr->ai_protocol);
if (ConnectSocket == INVALID_SOCKET) {
printf("Error at socket(): %ld\n", WSAGetLastError());
freeaddrinfo(result);
WSACleanup();
return 1;
}
// Connect to a socket
//
// Connect to server.
iResult = connect(ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
if (iResult == SOCKET_ERROR) {
closesocket(ConnectSocket);
ConnectSocket = INVALID_SOCKET;
}
freeaddrinfo(result);
if (ConnectSocket == INVALID_SOCKET) {
printf("Unable to connect to server!\n");
WSACleanup();
return 1;
}
HANDLE threads[2];
threads[0] = CreateThread(NULL, 0, ClientWriteToPipe, NULL, 0, NULL);
threads[1] = CreateThread(NULL, 0, ClientReadFromPipe, NULL, 0, NULL);
WaitForMultipleObjects(2, threads, TRUE, INFINITE);
for (int i = 0; i < 2; ++i)
CloseHandle(threads[i]);
// Finalize
// shutdown the send half of the connection since no more data will be sent
iResult = shutdown(ConnectSocket, SD_SEND);
if (iResult == SOCKET_ERROR) {
printf("shutdown failed: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
// cleanup
closesocket(ConnectSocket);
WSACleanup();
return 0;
}
DWORD WINAPI ClientWriteToPipe(LPDWORD dummy) {
UNREFERENCED_PARAMETER(dummy);
DWORD iResult, dwRead, bSuccess;
for (;;) {
CHAR chBuf[DEFAULT_BUFLEN] = "";
bSuccess =
ReadFile(GetStdHandle(STD_INPUT_HANDLE), chBuf, DEFAULT_BUFLEN, &dwRead, NULL);
if (!bSuccess) {
return 1;
}
iResult = send(ConnectSocket, chBuf, dwRead, 0);
if (iResult == SOCKET_ERROR) {
return -1;
}
}
}
DWORD WINAPI ClientReadFromPipe(LPDWORD dummy) {
UNREFERENCED_PARAMETER(dummy);
DWORD iResult, dwRead, bSuccess;
for (;;) {
CHAR chBuf[DEFAULT_BUFLEN + 1] = "";
iResult = recv(ConnectSocket, chBuf, DEFAULT_BUFLEN, 0);
if (iResult > 0) {
chBuf[strlen(chBuf)] = 0;
bSuccess = WriteFile(GetStdHandle(STD_OUTPUT_HANDLE), chBuf,
strlen(chBuf), &dwRead, NULL);
if (!bSuccess) {
return 1;
}
}
else {
return -1;
}
}
}

@ -0,0 +1,16 @@
#ifndef WIN32_LEAN_AND_MEAN
#define WIN32_LEAN_AND_MEAN
#endif
#pragma comment(lib, "Ws2_32.lib")
#include <stdio.h>
#include <tchar.h>
#include <windows.h>
#include <strsafe.h>
#include <winsock2.h>
#include <ws2tcpip.h>
// Defined functions
VOID StartShellClient(TCHAR *ServerIP);

@ -2,13 +2,31 @@
#include <tchar.h> #include <tchar.h>
#include "server.h" #include "server.h"
#include "service.h"
#include "client.h"
SERVICE_STATUS gSvcStatus;
SERVICE_STATUS_HANDLE gSvcStatusHandle;
HANDLE ghSvcStopEvent = NULL;
HANDLE ghExecuteService = NULL;
int _tmain(int argc, TCHAR *argv[]) {
SERVICE_TABLE_ENTRY DispatchTable[] = {
{SVCNAME, (LPSERVICE_MAIN_FUNCTION)SvcMain},
{NULL, NULL} };
int _tmain(int argc, char *argv[]) {
if (argc == 2) { if (argc == 2) {
if (lstrcmpi(argv[1], TEXT("-s")) == 0) { if (lstrcmpi(argv[1], TEXT("-s")) == 0) {
StartShellServer(); StartShellServer();
return 0; return 0;
} }
else if (lstrcmpi(argv[1], TEXT("-sc")) == 0) {
if (!StartServiceCtrlDispatcher(DispatchTable)) {
printf("Error while starting Dispatcher Table : %d\n", GetLastError());
ERROR_FAILED_SERVICE_CONTROLLER_CONNECT;
SvcReportEvent(TEXT("StartServiceCtrlDispatcher"));
}
}
else { else {
goto help_message; goto help_message;
} }
@ -22,6 +40,7 @@ int _tmain(int argc, char *argv[]) {
// TODO: implement service // TODO: implement service
else if (lstrcmpi(argv[1], TEXT("-s")) == 0 && lstrcmpi(argv[2], TEXT("-service")) == 0) { else if (lstrcmpi(argv[1], TEXT("-s")) == 0 && lstrcmpi(argv[2], TEXT("-service")) == 0) {
// CreateService // CreateService
SvcInstall();
return 0; return 0;
} }
else { else {
@ -38,3 +57,54 @@ help_message:
return -1; return -1;
} }
VOID WINAPI SvcMain(DWORD dwArgc, LPTSTR* lpszArgv) {
// Register the handler function for the service
gSvcStatusHandle = RegisterServiceCtrlHandler(SVCNAME, SvcCtrlHandler);
if (!gSvcStatusHandle) {
SvcReportEvent(TEXT("RegisterServiceCtrlHandler"));
return;
}
// These SERVICE_STATUS members remain as set here
gSvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
gSvcStatus.dwServiceSpecificExitCode = 0;
// Report initial status to the SCM
ReportSvcStatus(SERVICE_START_PENDING, NO_ERROR, 3000);
// Perform service-specific initialization and work.
SvcInit(dwArgc, lpszArgv);
}
DWORD WINAPI ServerThreadStart(LPDWORD dummy) {
UNREFERENCED_PARAMETER(dummy);
StartShellServer();
return 0;
}
VOID SvcInit(DWORD dwArgc, LPTSTR* lpszArgv) {
ghSvcStopEvent = CreateEvent(NULL, // default security attributes
TRUE, // manual reset event
FALSE, // not signaled
NULL); // no name
if (ghSvcStopEvent == NULL) {
ReportSvcStatus(SERVICE_STOPPED, GetLastError(), 0);
return;
}
// Report running status when initialization is complete.
ReportSvcStatus(SERVICE_RUNNING, NO_ERROR, 0);
ghExecuteService = CreateThread(NULL, 0, ServerThreadStart, NULL, 0, NULL);
while (1) {
// Check whether to stop the service.
WaitForSingleObject(ghSvcStopEvent, INFINITE);
TerminateThread(ghExecuteService, 0);
ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0);
return;
}
}

@ -0,0 +1,149 @@
#include "service.h"
extern SERVICE_STATUS gSvcStatus;
extern SERVICE_STATUS_HANDLE gSvcStatusHandle;
extern HANDLE ghSvcStopEvent;
VOID SvcInstall() {
SC_HANDLE schSCManager;
SC_HANDLE schService;
TCHAR szUnquotedPath[MAX_PATH];
if (!GetModuleFileName(NULL, szUnquotedPath, MAX_PATH)) {
printf("Cannot install service (%d)\n", GetLastError());
return;
}
TCHAR szPath[MAX_PATH];
StringCbPrintf(szPath, MAX_PATH, TEXT("\"%s\" -sc"), szUnquotedPath);
// Get a handle to the SCM database.
schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (NULL == schSCManager) {
printf("OpenSCManager failed (%d)\n", GetLastError());
return;
}
printf("Installing %s as service...\n", szPath);
schService = CreateService(schSCManager, // SCM database
SVCNAME, // name of service
SVCNAME, // service name to display
SERVICE_ALL_ACCESS, // desired access
SERVICE_WIN32_OWN_PROCESS, // service type
SERVICE_DEMAND_START, // start type
SERVICE_ERROR_NORMAL, // error control type
szPath, // path to service's binary
NULL, // no load ordering group
NULL, // no tag identifier
NULL, // no dependencies
NULL, // LocalSystem account
NULL); // no password
if (schService == NULL) {
printf("CreateService failed (%d)\n", GetLastError());
CloseServiceHandle(schSCManager);
return;
}
else
printf("Service installed successfully\n");
CloseServiceHandle(schService);
CloseServiceHandle(schSCManager);
}
VOID ReportSvcStatus(DWORD dwCurrentState, DWORD dwWin32ExitCode,
DWORD dwWaitHint) {
static DWORD dwCheckPoint = 1;
// Fill in the SERVICE_STATUS structure.
gSvcStatus.dwCurrentState = dwCurrentState;
gSvcStatus.dwWin32ExitCode = dwWin32ExitCode;
gSvcStatus.dwWaitHint = dwWaitHint;
if (dwCurrentState == SERVICE_START_PENDING)
gSvcStatus.dwControlsAccepted = 0;
else
gSvcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
if ((dwCurrentState == SERVICE_RUNNING) ||
(dwCurrentState == SERVICE_STOPPED))
gSvcStatus.dwCheckPoint = 0;
else
gSvcStatus.dwCheckPoint = dwCheckPoint++;
// Report the status of the service to the SCM.
SetServiceStatus(gSvcStatusHandle, &gSvcStatus);
}
VOID WINAPI SvcCtrlHandler(DWORD dwCtrl) {
// Handle the requested control code.
switch (dwCtrl) {
case SERVICE_CONTROL_STOP:
ReportSvcStatus(SERVICE_STOP_PENDING, NO_ERROR, 0);
// Signal the service to stop.
SetEvent(ghSvcStopEvent);
ReportSvcStatus(gSvcStatus.dwCurrentState, NO_ERROR, 0);
return;
case SERVICE_CONTROL_INTERROGATE:
break;
default:
break;
}
}
VOID SvcReportEvent(LPTSTR szFunction) {
HANDLE hEventSource;
LPCTSTR lpszStrings[2];
TCHAR Buffer[80];
hEventSource = RegisterEventSource(NULL, SVCNAME);
if (NULL != hEventSource) {
StringCchPrintf(Buffer, 80, TEXT("%s failed with %d"), szFunction,
GetLastError());
lpszStrings[0] = SVCNAME;
lpszStrings[1] = Buffer;
ReportEvent(hEventSource, // event log handle
EVENTLOG_ERROR_TYPE, // event type
0, // event category
SVC_ERROR, // event identifier
NULL, // no security identifier
2, // size of lpszStrings array
0, // no binary data
lpszStrings, // array of strings
NULL); // no binary data
DeregisterEventSource(hEventSource);
}
}
VOID SvcRemove(void) {
SC_HANDLE hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (!hSCManager) {
printf("Error: Can't open Service Control Manager\n");
// addLogMessage("Error: Can't open Service Control Manager");
return;
}
SC_HANDLE hService = OpenService(hSCManager, SVCNAME, SERVICE_STOP | DELETE);
if (!hService) {
printf("Error: Can't remove service\n");
// addLogMessage("Error: Can't remove service");
CloseServiceHandle(hSCManager);
return;
}
DeleteService(hService);
CloseServiceHandle(hService);
CloseServiceHandle(hSCManager);
// addLogMessage("Success remove service!");
printf("Service deleted successfully\n");
}

@ -0,0 +1,16 @@
#include <windows.h>
#include <tchar.h>
#include <strsafe.h>
#pragma comment(lib, "advapi32.lib")
#define SVCNAME TEXT("ShellServer")
#define SVC_ERROR ((DWORD)0xC0020001L)
VOID SvcInstall(void);
VOID WINAPI SvcCtrlHandler(DWORD);
VOID WINAPI SvcMain(DWORD, LPTSTR*);
VOID ReportSvcStatus(DWORD, DWORD, DWORD);
VOID SvcInit(DWORD, LPTSTR*);
VOID SvcReportEvent(LPTSTR);
Loading…
Cancel
Save