1
0
mirror of https://gitlab.xiph.org/xiph/icecast-server.git synced 2024-12-04 14:46:30 -05:00
icecast-server/win32/icecastService.cpp

262 lines
6.7 KiB
C++
Raw Normal View History

#include <windows.h>
#include <stdio.h>
#include <direct.h>
extern "C" {
#include "thread/thread.h"
#include "avl/avl.h"
#include "log/log.h"
#include "global.h"
#include "httpp/httpp.h"
#include "net/sock.h"
#include "connection.h"
#include "refbuf.h"
#include "client.h"
#include "stats.h"
}
// Issues to be wary of. Careful of the runtime you use, I've had printf and similar routines
// crash because of this on apparently valid strings. some weird thing related to checking for
// multiple byte characters. DeleteService only marks a service for deletion, and the docs
// are unclear on the cases that lead to purging however a reboot should do it.
SERVICE_STATUS ServiceStatus;
SERVICE_STATUS_HANDLE hStatus;
void ServiceMain(int argc, char** argv);
void ControlHandler(DWORD request);
int InitService();
extern "C" int mainService(int argc, char **argv);
int InitService()
{
int result = 0;
return(result);
}
void installService (const char *path)
{
if (path) {
char fullPath[8096*2] = "\"";
int len = GetModuleFileName (NULL, fullPath+1, sizeof (fullPath)-1);
_snprintf(fullPath+len+1, sizeof (fullPath)-len, "\" \"%s\"", path);
SC_HANDLE manager = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS );
if (manager == NULL)
{
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL
);
printf ("OpenSCManager: %s\n", (LPCTSTR)lpMsgBuf);
LocalFree( lpMsgBuf );
return;
}
SC_HANDLE service = CreateService(
manager,
PACKAGE_STRING,
PACKAGE_STRING " Streaming Media Server",
GENERIC_READ | GENERIC_EXECUTE,
SERVICE_WIN32_OWN_PROCESS,
SERVICE_AUTO_START,
SERVICE_ERROR_IGNORE,
fullPath,
NULL,
NULL,
NULL,
NULL,
NULL
);
if (service == NULL)
{
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL
);
printf ("CreateService: %s\n", (LPCTSTR)lpMsgBuf);
LocalFree( lpMsgBuf );
CloseServiceHandle (manager);
return;
}
printf("Service Installed\n");
CloseServiceHandle (service);
CloseServiceHandle (manager);
}
}
void removeService()
{
SC_HANDLE manager = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS );
if (manager == NULL)
{
LPVOID lpMsgBuf;
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL
);
printf ("OpenSCManager: %s\n", (LPCTSTR)lpMsgBuf);
LocalFree( lpMsgBuf );
return;
}
SC_HANDLE service = OpenService (manager, PACKAGE_STRING, DELETE);
if (service) {
DeleteService(service);
printf("Service Removed\n");
CloseServiceHandle (service);
}
else
printf("Service not found\n");
CloseServiceHandle (manager);
}
void ControlHandler(DWORD request)
{
switch(request) {
case SERVICE_CONTROL_STOP:
global.running = ICE_HALTING;
ServiceStatus.dwWin32ExitCode = 0;
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus (hStatus, &ServiceStatus);
return;
case SERVICE_CONTROL_SHUTDOWN:
global.running = ICE_HALTING;
ServiceStatus.dwWin32ExitCode = 0;
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
SetServiceStatus (hStatus, &ServiceStatus);
return;
default:
break;
}
// Report current status
SetServiceStatus (hStatus, &ServiceStatus);
return;
}
void ServiceMain(int argc, char** argv)
{
int error;
ServiceStatus.dwServiceType = SERVICE_WIN32;
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(PACKAGE_STRING, (LPHANDLER_FUNCTION)ControlHandler);
if (hStatus == (SERVICE_STATUS_HANDLE)0) {
// Registering Control Handler failed
return;
}
// Initialize Service
error = InitService();
if (error) {
// Initialization failed
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
ServiceStatus.dwWin32ExitCode = -1;
SetServiceStatus(hStatus, &ServiceStatus);
return;
}
// We report the running status to SCM.
ServiceStatus.dwCurrentState = SERVICE_RUNNING;
SetServiceStatus (hStatus, &ServiceStatus);
/* Here we do the work */
int argc2 = 3;
char* argv2 [4];
argv2 [0] = argv[0];
argv2 [1] = "-c";
if (argc < 2)
argv2 [2] = "icecast.xml";
else
argv2 [2] = argv[1];
argv2[3] = NULL;
int ret = mainService(argc2, (char **)argv2);
ServiceStatus.dwCurrentState = SERVICE_STOPPED;
ServiceStatus.dwWin32ExitCode = -1;
SetServiceStatus(hStatus, &ServiceStatus);
return;
}
int main(int argc, char **argv)
{
if (argc < 2)
{
printf ("Usage:\n %s remove\n %s install path\n", argv[0], argv[0]);
return 0;
}
if (!strcmp(argv[1], "install"))
{
if (argc > 2)
{
printf ("Installing service from %s\n", argv[2]);
installService(argv[2]);
}
else
printf ("install requires a path arg as well\n");
Sleep (2000);
return 0;
}
if (!strcmp(argv[1], "remove") || !strcmp(argv[1], "uninstall"))
{
printf ("removing service\n");
removeService();
Sleep (2000);
return 0;
}
if (_chdir(argv[1]) < 0)
{
printf ("unable to change to directory %s\n", argv[1]);
Sleep (2000);
return 0;
}
SERVICE_TABLE_ENTRY ServiceTable[2];
ServiceTable[0].lpServiceName = PACKAGE_STRING;
ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain;
ServiceTable[1].lpServiceName = NULL;
ServiceTable[1].lpServiceProc = NULL;
// Start the control dispatcher thread for our service
StartServiceCtrlDispatcher(ServiceTable);
return 0;
}