|
|
|
@ -16,115 +16,108 @@ SERVICE_STATUS_HANDLE gSvcStatusHandle; |
|
|
|
|
|
|
|
|
|
VOID WINAPI ServiceCtrlHandler(DWORD dwCtrl) |
|
|
|
|
{ |
|
|
|
|
// Handle the requested control code.
|
|
|
|
|
// Handle the requested control code.
|
|
|
|
|
|
|
|
|
|
switch(dwCtrl) |
|
|
|
|
switch (dwCtrl) |
|
|
|
|
{ |
|
|
|
|
case SERVICE_CONTROL_STOP: |
|
|
|
|
case SERVICE_CONTROL_SHUTDOWN: |
|
|
|
|
case SERVICE_CONTROL_STOP: |
|
|
|
|
case SERVICE_CONTROL_SHUTDOWN: |
|
|
|
|
|
|
|
|
|
ServiceShutdown = TRUE; |
|
|
|
|
ReportServiceStatus(SERVICE_STOP_PENDING, NO_ERROR, 0); |
|
|
|
|
ServiceShutdown = TRUE; |
|
|
|
|
ReportServiceStatus(SERVICE_STOP_PENDING, NO_ERROR, 0); |
|
|
|
|
|
|
|
|
|
// Remove PID file and free ressources
|
|
|
|
|
cleanup(); |
|
|
|
|
# ifdef USE_MSRPC |
|
|
|
|
ReportServiceStatus(SERVICE_STOPPED, NO_ERROR, 0); |
|
|
|
|
# endif // !USE_MSRPC
|
|
|
|
|
return; |
|
|
|
|
// Remove PID file and free ressources
|
|
|
|
|
cleanup(); |
|
|
|
|
# if __CYGWIN__ || defined(USE_MSRPC) |
|
|
|
|
ReportServiceStatus(SERVICE_STOPPED, NO_ERROR, 0); |
|
|
|
|
# endif // __CYGWIN__
|
|
|
|
|
|
|
|
|
|
default: |
|
|
|
|
break; |
|
|
|
|
default: |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
static VOID WINAPI ServiceMain(const int argc_unused, CARGV argv_unused) |
|
|
|
|
{ |
|
|
|
|
// Register the handler function for the service
|
|
|
|
|
|
|
|
|
|
gSvcStatusHandle = RegisterServiceCtrlHandler( |
|
|
|
|
NT_SERVICE_NAME, |
|
|
|
|
ServiceCtrlHandler |
|
|
|
|
); |
|
|
|
|
// Register the handler function for the service
|
|
|
|
|
|
|
|
|
|
if(!gSvcStatusHandle) |
|
|
|
|
{ |
|
|
|
|
//ServiceReportEvent(RegisterServiceCtrlHandler);
|
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
if (!((gSvcStatusHandle = RegisterServiceCtrlHandler(NT_SERVICE_NAME, ServiceCtrlHandler)))) |
|
|
|
|
{ |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// These SERVICE_STATUS members remain as set here
|
|
|
|
|
// These SERVICE_STATUS members remain as set here
|
|
|
|
|
|
|
|
|
|
gSvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; |
|
|
|
|
gSvcStatus.dwServiceSpecificExitCode = 0; |
|
|
|
|
gSvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; |
|
|
|
|
gSvcStatus.dwServiceSpecificExitCode = 0; |
|
|
|
|
|
|
|
|
|
// Run the actual program
|
|
|
|
|
ReportServiceStatus(SERVICE_STOPPED, newmain(), 3000); |
|
|
|
|
// Run the actual program
|
|
|
|
|
ReportServiceStatus(SERVICE_STOPPED, newmain(), 3000); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
SERVICE_TABLE_ENTRY NTServiceDispatchTable[] = { |
|
|
|
|
{ |
|
|
|
|
(LPSTR)NT_SERVICE_NAME, |
|
|
|
|
(LPSERVICE_MAIN_FUNCTION) ServiceMain |
|
|
|
|
}, |
|
|
|
|
{ |
|
|
|
|
NULL, |
|
|
|
|
NULL |
|
|
|
|
} |
|
|
|
|
{ |
|
|
|
|
(LPSTR)NT_SERVICE_NAME, |
|
|
|
|
(LPSERVICE_MAIN_FUNCTION)ServiceMain |
|
|
|
|
}, |
|
|
|
|
{ |
|
|
|
|
NULL, |
|
|
|
|
NULL |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
VOID ReportServiceStatus(const DWORD dwCurrentState, const DWORD dwWin32ExitCode, const DWORD dwWaitHint) |
|
|
|
|
{ |
|
|
|
|
static DWORD dwCheckPoint = 1; |
|
|
|
|
static DWORD dwCheckPoint = 1; |
|
|
|
|
|
|
|
|
|
// Fill in the SERVICE_STATUS structure.
|
|
|
|
|
// Fill in the SERVICE_STATUS structure.
|
|
|
|
|
|
|
|
|
|
gSvcStatus.dwCurrentState = dwCurrentState; |
|
|
|
|
gSvcStatus.dwWin32ExitCode = dwWin32ExitCode; |
|
|
|
|
gSvcStatus.dwWaitHint = dwWaitHint; |
|
|
|
|
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_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++; |
|
|
|
|
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); |
|
|
|
|
// Report the status of the service to the SCM.
|
|
|
|
|
SetServiceStatus(gSvcStatusHandle, &gSvcStatus); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/*VOID ServiceReportEvent(char *szFunction)
|
|
|
|
|
{ |
|
|
|
|
HANDLE hEventSource; |
|
|
|
|
const char *eventStrings[2]; |
|
|
|
|
TCHAR Buffer[80]; |
|
|
|
|
|
|
|
|
|
hEventSource = RegisterEventSource(NULL, NT_SERVICE_NAME); |
|
|
|
|
|
|
|
|
|
if (hEventSource) |
|
|
|
|
{ |
|
|
|
|
snprintf(Buffer, 80, "%s failed with %d", szFunction, GetLastError()); |
|
|
|
|
|
|
|
|
|
eventStrings[0] = NT_SERVICE_NAME; |
|
|
|
|
eventStrings[1] = Buffer; |
|
|
|
|
|
|
|
|
|
ReportEvent(hEventSource, // event log handle
|
|
|
|
|
EVENTLOG_ERROR_TYPE, // event type
|
|
|
|
|
0, // event category
|
|
|
|
|
00, // event identifier
|
|
|
|
|
NULL, // no security identifier
|
|
|
|
|
2, // size of lpszStrings array
|
|
|
|
|
0, // no binary data
|
|
|
|
|
eventStrings, // array of strings
|
|
|
|
|
NULL); // no binary data
|
|
|
|
|
|
|
|
|
|
DeregisterEventSource(hEventSource); |
|
|
|
|
} |
|
|
|
|
HANDLE hEventSource; |
|
|
|
|
const char *eventStrings[2]; |
|
|
|
|
TCHAR Buffer[80]; |
|
|
|
|
|
|
|
|
|
hEventSource = RegisterEventSource(NULL, NT_SERVICE_NAME); |
|
|
|
|
|
|
|
|
|
if (hEventSource) |
|
|
|
|
{ |
|
|
|
|
snprintf(Buffer, 80, "%s failed with %d", szFunction, GetLastError()); |
|
|
|
|
|
|
|
|
|
eventStrings[0] = NT_SERVICE_NAME; |
|
|
|
|
eventStrings[1] = Buffer; |
|
|
|
|
|
|
|
|
|
ReportEvent(hEventSource, // event log handle
|
|
|
|
|
EVENTLOG_ERROR_TYPE, // event type
|
|
|
|
|
0, // event category
|
|
|
|
|
00, // event identifier
|
|
|
|
|
NULL, // no security identifier
|
|
|
|
|
2, // size of lpszStrings array
|
|
|
|
|
0, // no binary data
|
|
|
|
|
eventStrings, // array of strings
|
|
|
|
|
NULL); // no binary data
|
|
|
|
|
|
|
|
|
|
DeregisterEventSource(hEventSource); |
|
|
|
|
} |
|
|
|
|
}*/ |
|
|
|
|
|
|
|
|
|
//Returns 0=Error, 1=Success, 2=Doesn't exist
|
|
|
|
@ -146,12 +139,12 @@ static uint_fast8_t OpenAndRemoveService(DWORD *dwPreviousState, SC_HANDLE *schS |
|
|
|
|
closeManager = TRUE; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
*schSCManager = OpenSCManager( |
|
|
|
|
NULL, // local computer
|
|
|
|
|
NULL, // ServicesActive database
|
|
|
|
|
SC_MANAGER_ALL_ACCESS); // full access rights
|
|
|
|
|
*schSCManager = OpenSCManager( |
|
|
|
|
NULL, // local computer
|
|
|
|
|
NULL, // ServicesActive database
|
|
|
|
|
SC_MANAGER_ALL_ACCESS); // full access rights
|
|
|
|
|
|
|
|
|
|
if (!*schSCManager) return 0; |
|
|
|
|
if (!*schSCManager) return 0; |
|
|
|
|
|
|
|
|
|
if (!((installedService = OpenService(*schSCManager, NT_SERVICE_NAME, SERVICE_ALL_ACCESS)))) |
|
|
|
|
{ |
|
|
|
@ -182,86 +175,86 @@ static uint_fast8_t OpenAndRemoveService(DWORD *dwPreviousState, SC_HANDLE *schS |
|
|
|
|
|
|
|
|
|
static VOID ServiceInstaller(const char *restrict ServiceUser, const char *const ServicePassword) |
|
|
|
|
{ |
|
|
|
|
SC_HANDLE schSCManager; |
|
|
|
|
SC_HANDLE schService; |
|
|
|
|
char szPath[MAX_PATH] = "\""; |
|
|
|
|
|
|
|
|
|
if (!GetModuleFileName(NULL, szPath + sizeof(char), MAX_PATH - 1)) |
|
|
|
|
{ |
|
|
|
|
errorout("Cannot install service (%d)\n", (uint32_t)GetLastError()); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
strcat(szPath,"\""); |
|
|
|
|
|
|
|
|
|
int i; |
|
|
|
|
for (i = 1; i < global_argc; i ++) |
|
|
|
|
{ |
|
|
|
|
// Strip unneccessary parameters, especially the password
|
|
|
|
|
if (!strcmp(global_argv[i], "-s")) continue; |
|
|
|
|
|
|
|
|
|
if (!strcmp(global_argv[i], "-W") || |
|
|
|
|
!strcmp(global_argv[i], "-U")) |
|
|
|
|
{ |
|
|
|
|
i++; |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
strcat(szPath, " "); |
|
|
|
|
|
|
|
|
|
if (strchr(global_argv[i], ' ')) |
|
|
|
|
{ |
|
|
|
|
strcat(szPath, "\""); |
|
|
|
|
strcat(szPath, global_argv[i]); |
|
|
|
|
strcat(szPath, "\""); |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
strcat(szPath, global_argv[i]); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Get a handle to the SCM database.
|
|
|
|
|
SC_HANDLE schSCManager; |
|
|
|
|
SC_HANDLE schService; |
|
|
|
|
char szPath[MAX_PATH] = "\""; |
|
|
|
|
|
|
|
|
|
if (!GetModuleFileName(NULL, szPath + sizeof(char), MAX_PATH - 1)) |
|
|
|
|
{ |
|
|
|
|
errorout("Cannot install service (%d)\n", (uint32_t)GetLastError()); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
strcat(szPath, "\""); |
|
|
|
|
|
|
|
|
|
int i; |
|
|
|
|
for (i = 1; i < global_argc; i++) |
|
|
|
|
{ |
|
|
|
|
// Strip unneccessary parameters, especially the password
|
|
|
|
|
if (!strcmp(global_argv[i], "-s")) continue; |
|
|
|
|
|
|
|
|
|
if (!strcmp(global_argv[i], "-W") || |
|
|
|
|
!strcmp(global_argv[i], "-U")) |
|
|
|
|
{ |
|
|
|
|
i++; |
|
|
|
|
continue; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
strcat(szPath, " "); |
|
|
|
|
|
|
|
|
|
if (strchr(global_argv[i], ' ')) |
|
|
|
|
{ |
|
|
|
|
strcat(szPath, "\""); |
|
|
|
|
strcat(szPath, global_argv[i]); |
|
|
|
|
strcat(szPath, "\""); |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
strcat(szPath, global_argv[i]); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Get a handle to the SCM database.
|
|
|
|
|
|
|
|
|
|
SERVICE_STATUS status; |
|
|
|
|
DWORD dwPreviousState; |
|
|
|
|
|
|
|
|
|
if (!OpenAndRemoveService(&dwPreviousState, &schSCManager)) |
|
|
|
|
{ |
|
|
|
|
errorout("Service removal failed (%d)\n", (uint32_t)GetLastError()); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
if (!OpenAndRemoveService(&dwPreviousState, &schSCManager)) |
|
|
|
|
{ |
|
|
|
|
errorout("Service removal failed (%d)\n", (uint32_t)GetLastError()); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
char *tempUser = NULL; |
|
|
|
|
|
|
|
|
|
if (ServiceUser) |
|
|
|
|
{ |
|
|
|
|
// Shortcuts for some well known users
|
|
|
|
|
if (!strcasecmp(ServiceUser, "/l")) ServiceUser="NT AUTHORITY\\LocalService"; |
|
|
|
|
if (!strcasecmp(ServiceUser, "/n")) ServiceUser="NT AUTHORITY\\NetworkService"; |
|
|
|
|
|
|
|
|
|
// Allow Local Users without .\ , e.g. "johndoe" instead of ".\johndoe"
|
|
|
|
|
if (!strchr(ServiceUser, '\\')) |
|
|
|
|
{ |
|
|
|
|
tempUser = (char*)vlmcsd_malloc(strlen(ServiceUser) + 3); |
|
|
|
|
strcpy(tempUser, ".\\"); |
|
|
|
|
strcat(tempUser, ServiceUser); |
|
|
|
|
ServiceUser = tempUser; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
{ |
|
|
|
|
// Shortcuts for some well known users
|
|
|
|
|
if (!strcasecmp(ServiceUser, "/l")) ServiceUser = "NT AUTHORITY\\LocalService"; |
|
|
|
|
if (!strcasecmp(ServiceUser, "/n")) ServiceUser = "NT AUTHORITY\\NetworkService"; |
|
|
|
|
|
|
|
|
|
// Allow Local Users without .\ , e.g. "johndoe" instead of ".\johndoe"
|
|
|
|
|
if (!strchr(ServiceUser, '\\')) |
|
|
|
|
{ |
|
|
|
|
tempUser = (char*)vlmcsd_malloc(strlen(ServiceUser) + 3); |
|
|
|
|
strcpy(tempUser, ".\\"); |
|
|
|
|
strcat(tempUser, ServiceUser); |
|
|
|
|
ServiceUser = tempUser; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
schService = CreateService( |
|
|
|
|
schSCManager, // SCM database
|
|
|
|
|
NT_SERVICE_NAME, // name of service
|
|
|
|
|
NT_SERVICE_DISPLAY_NAME, // service name to display
|
|
|
|
|
SERVICE_ALL_ACCESS, // desired access
|
|
|
|
|
SERVICE_WIN32_OWN_PROCESS, // service type
|
|
|
|
|
SERVICE_AUTO_START, // start type
|
|
|
|
|
SERVICE_ERROR_NORMAL, // error control type
|
|
|
|
|
szPath, // path to service's binary
|
|
|
|
|
NULL, // no load ordering group
|
|
|
|
|
NULL, // no tag identifier
|
|
|
|
|
"tcpip\0", // depends on TCP/IP
|
|
|
|
|
ServiceUser, // LocalSystem account
|
|
|
|
|
ServicePassword); // no password
|
|
|
|
|
schSCManager, // SCM database
|
|
|
|
|
NT_SERVICE_NAME, // name of service
|
|
|
|
|
NT_SERVICE_DISPLAY_NAME, // service name to display
|
|
|
|
|
SERVICE_ALL_ACCESS, // desired access
|
|
|
|
|
SERVICE_WIN32_OWN_PROCESS, // service type
|
|
|
|
|
SERVICE_AUTO_START, // start type
|
|
|
|
|
SERVICE_ERROR_NORMAL, // error control type
|
|
|
|
|
szPath, // path to service's binary
|
|
|
|
|
NULL, // no load ordering group
|
|
|
|
|
NULL, // no tag identifier
|
|
|
|
|
"tcpip\0", // depends on TCP/IP
|
|
|
|
|
ServiceUser, // LocalSystem account
|
|
|
|
|
ServicePassword); // no password
|
|
|
|
|
|
|
|
|
|
# if __clang__ && (__CYGWIN__ || __MINGW64__ ) |
|
|
|
|
// Workaround for clang not understanding some GCC asm syntax used in <w32api/psdk_inc/intrin-impl.h>
|
|
|
|
@ -271,43 +264,43 @@ static VOID ServiceInstaller(const char *restrict ServiceUser, const char *const |
|
|
|
|
# endif |
|
|
|
|
if (tempUser) free(tempUser); |
|
|
|
|
|
|
|
|
|
if (schService == NULL) |
|
|
|
|
{ |
|
|
|
|
errorout("CreateService failed (%u)\n", (uint32_t)GetLastError()); |
|
|
|
|
CloseServiceHandle(schSCManager); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
errorout("Service installed successfully\n"); |
|
|
|
|
|
|
|
|
|
if (dwPreviousState == SERVICE_RUNNING) |
|
|
|
|
{ |
|
|
|
|
printf("Restarting " NT_SERVICE_NAME " service => "); |
|
|
|
|
status.dwCurrentState = SERVICE_STOPPED; |
|
|
|
|
|
|
|
|
|
if (StartService(schService, 0, NULL)) |
|
|
|
|
{ |
|
|
|
|
for (i = 0; i < 10; i++) |
|
|
|
|
{ |
|
|
|
|
if (!QueryServiceStatus(schService, &status) || status.dwCurrentState != SERVICE_START_PENDING) break; |
|
|
|
|
Sleep(100); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (status.dwCurrentState == SERVICE_RUNNING) |
|
|
|
|
printf("Success\n"); |
|
|
|
|
else if (status.dwCurrentState == SERVICE_START_PENDING) |
|
|
|
|
printf("Not ready within a second\n"); |
|
|
|
|
else |
|
|
|
|
errorout("Error\n"); |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
errorout("Error %u\n", (uint32_t)GetLastError()); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
CloseServiceHandle(schService); |
|
|
|
|
CloseServiceHandle(schSCManager); |
|
|
|
|
if (schService == NULL) |
|
|
|
|
{ |
|
|
|
|
errorout("CreateService failed (%u)\n", (uint32_t)GetLastError()); |
|
|
|
|
CloseServiceHandle(schSCManager); |
|
|
|
|
return; |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
{ |
|
|
|
|
errorout("Service installed successfully\n"); |
|
|
|
|
|
|
|
|
|
if (dwPreviousState == SERVICE_RUNNING) |
|
|
|
|
{ |
|
|
|
|
printf("Restarting " NT_SERVICE_NAME " service => "); |
|
|
|
|
status.dwCurrentState = SERVICE_STOPPED; |
|
|
|
|
|
|
|
|
|
if (StartService(schService, 0, NULL)) |
|
|
|
|
{ |
|
|
|
|
for (i = 0; i < 10; i++) |
|
|
|
|
{ |
|
|
|
|
if (!QueryServiceStatus(schService, &status) || status.dwCurrentState != SERVICE_START_PENDING) break; |
|
|
|
|
Sleep(100); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (status.dwCurrentState == SERVICE_RUNNING) |
|
|
|
|
printf("Success\n"); |
|
|
|
|
else if (status.dwCurrentState == SERVICE_START_PENDING) |
|
|
|
|
printf("Not ready within a second\n"); |
|
|
|
|
else |
|
|
|
|
errorout("Error\n"); |
|
|
|
|
} |
|
|
|
|
else |
|
|
|
|
errorout("Error %u\n", (uint32_t)GetLastError()); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
CloseServiceHandle(schService); |
|
|
|
|
CloseServiceHandle(schSCManager); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
int NtServiceInstallation(const int_fast8_t installService, const char *restrict ServiceUser, const char *const ServicePassword) |
|
|
|
@ -322,7 +315,7 @@ int NtServiceInstallation(const int_fast8_t installService, const char *restrict |
|
|
|
|
|
|
|
|
|
if (installService == 2) // Remove
|
|
|
|
|
{ |
|
|
|
|
switch(OpenAndRemoveService(NULL, NULL)) |
|
|
|
|
switch (OpenAndRemoveService(NULL, NULL)) |
|
|
|
|
{ |
|
|
|
|
case 0: |
|
|
|
|
errorout("Error removing service %s\n", NT_SERVICE_NAME); |
|
|
|
|