Windows C service not writing to file in PreShutdown event - c

I am working on a Windows Service written in C code.
In the service initialization code I have registered to a SERVICE_ACCEPT_PRESHUTDOWN event like this:
gSvcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PRESHUTDOWN;
In the service control handler I have writen the logic to write to a file in the SERVICE_CONTROL_PRESHUTDOWN event like this:
DWORD WINAPI SvcCtrlHandler(DWORD dwCtrl, DWORD eventType, void *eventData, void *context)
{
if (dwCtrl == SERVICE_CONTROL_STOP)
{
gSvcStatus.dwWin32ExitCode = 0;
gSvcStatus.dwCurrentState = SERVICE_STOPPED;
}
else if (dwCtrl == SERVICE_CONTROL_PRESHUTDOWN)
{
char sentence[] = "Hello World";
FILE *fptr;
fptr = fopen("C:\\test\\program.txt", "w");
if (fptr == NULL) {
printf("Error!");
}
else
{
fprintf(fptr, "%s", sentence);
fclose(fptr);
}
gSvcStatus.dwWin32ExitCode = 0;
gSvcStatus.dwCurrentState = SERVICE_STOPPED;
}
SetServiceStatus(g_ServiceStatusHandle, &gSvcStatus);
return NO_ERROR;
}
But after reboot, I am not able to see the file program.txt in test folder. Need help in fixing this issue.
What else I have tried:
I also tried writing to event Viewer using the SvcReportEvent function:
//
// Purpose:
// Logs messages to the event log
//
// Parameters:
// szFunction - name of function that failed
//
// Return value:
// None
//
// Remarks:
// The service must have an entry in the Application event log.
//
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);
}
}
Change done to SvcCtrlHandler function:
DWORD WINAPI SvcCtrlHandler(DWORD dwCtrl, DWORD eventType, void *eventData, void *context)
{
if (dwCtrl == SERVICE_CONTROL_STOP)
{
SvcReportEvent((LPTSTR)TEXT("In function SvcCtrlHandler in condition SERVICE_CONTROL_STOP"));
gSvcStatus.dwWin32ExitCode = 0;
gSvcStatus.dwCurrentState = SERVICE_STOPPED;
}
else if (dwCtrl == SERVICE_CONTROL_PRESHUTDOWN)
{
SvcReportEvent((LPTSTR)TEXT("In function SvcCtrlHandler in condition SERVICE_CONTROL_PRESHUTDOWN"));
gSvcStatus.dwWin32ExitCode = 0;
gSvcStatus.dwCurrentState = SERVICE_STOPPED;
}
SetServiceStatus(g_ServiceStatusHandle, &gSvcStatus);
return NO_ERROR;
}
Observation:
When I restart my computer, there is no Eventviewer log written
When I manually stop the service, a log is written into event viewer:
In function SvcCtrlHandler in condition SERVICE_CONTROL_STOP
Note: Link I referred while writing the service: https://learn.microsoft.com/en-us/windows/win32/services/the-complete-service-sample?redirectedfrom=MSDN

Posting the answer that solved my problem
#include <windows.h>
#include <WinBase.h>
#include <tchar.h>
#include <strsafe.h>
#define SVC_ERROR ((DWORD)0xC0020001L)
SERVICE_STATUS gSvcStatus = { 0 };
SERVICE_STATUS_HANDLE g_ServiceStatusHandle = NULL;
HANDLE g_ServiceStopEvent = INVALID_HANDLE_VALUE;
VOID WINAPI ServiceMain(DWORD argc, LPTSTR *argv);
DWORD WINAPI SvcCtrlHandler(DWORD dwCtrl, DWORD eventType, void *eventData, void *context);
DWORD WINAPI ServiceWorkerThread(LPVOID lpParam);
#define SVCNAME _T("SampleService")
//
// Purpose:
// Logs messages to the event log
//
// Parameters:
// szFunction - name of function that failed
//
// Return value:
// None
//
// Remarks:
// The service must have an entry in the Application event log.
//
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_INFORMATION_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);
}
}
int _tmain(int argc, TCHAR *argv[])
{
SvcReportEvent(_T("My Sample Service: Main: Entry"));
SERVICE_TABLE_ENTRY ServiceTable[] =
{
{SVCNAME, (LPSERVICE_MAIN_FUNCTION)ServiceMain},
{NULL, NULL}
};
if (StartServiceCtrlDispatcher(ServiceTable) == FALSE)
{
SvcReportEvent(_T("My Sample Service: Main: StartServiceCtrlDispatcher returned error"));
return GetLastError();
}
SvcReportEvent(_T("My Sample Service: Main: Exit"));
return 0;
}
VOID WINAPI ServiceMain(DWORD argc, LPTSTR *argv)
{
DWORD Status = E_FAIL;
SvcReportEvent(_T("My Sample Service: ServiceMain: Entry"));
g_ServiceStatusHandle = RegisterServiceCtrlHandlerEx(
SVCNAME,
SvcCtrlHandler,
NULL);
if (g_ServiceStatusHandle == NULL)
{
SvcReportEvent(_T("My Sample Service: ServiceMain: RegisterServiceCtrlHandler returned error"));
goto EXIT;
}
// Tell the service controller we are starting
ZeroMemory(&gSvcStatus, sizeof(gSvcStatus));
gSvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
gSvcStatus.dwControlsAccepted = 0;
gSvcStatus.dwCurrentState = SERVICE_START_PENDING;
gSvcStatus.dwWin32ExitCode = 0;
gSvcStatus.dwServiceSpecificExitCode = 0;
gSvcStatus.dwCheckPoint = 0;
if (SetServiceStatus(g_ServiceStatusHandle, &gSvcStatus) == FALSE)
{
SvcReportEvent(_T("My Sample Service: ServiceMain: SetServiceStatus returned error"));
}
/*
* Perform tasks neccesary to start the service here
*/
SvcReportEvent(_T("My Sample Service: ServiceMain: Performing Service Start Operations"));
// Create stop event to wait on later.
g_ServiceStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (g_ServiceStopEvent == NULL)
{
SvcReportEvent(_T("My Sample Service: ServiceMain: CreateEvent(g_ServiceStopEvent) returned error"));
gSvcStatus.dwControlsAccepted = 0;
gSvcStatus.dwCurrentState = SERVICE_STOPPED;
gSvcStatus.dwWin32ExitCode = GetLastError();
gSvcStatus.dwCheckPoint = 1;
if (SetServiceStatus(g_ServiceStatusHandle, &gSvcStatus) == FALSE)
{
SvcReportEvent(_T("My Sample Service: ServiceMain: SetServiceStatus returned error"));
}
goto EXIT;
}
// Tell the service controller we are started
gSvcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PRESHUTDOWN;
gSvcStatus.dwCurrentState = SERVICE_RUNNING;
gSvcStatus.dwWin32ExitCode = 0;
gSvcStatus.dwCheckPoint = 0;
if (SetServiceStatus(g_ServiceStatusHandle, &gSvcStatus) == FALSE)
{
SvcReportEvent(_T("My Sample Service: ServiceMain: SetServiceStatus returned error"));
}
// Start the thread that will perform the main task of the service
HANDLE hThread = CreateThread(NULL, 0, ServiceWorkerThread, NULL, 0, NULL);
SvcReportEvent(_T("My Sample Service: ServiceMain: Waiting for Worker Thread to complete"));
// Wait until our worker thread exits effectively signaling that the service needs to stop
WaitForSingleObject(hThread, INFINITE);
SvcReportEvent(_T("My Sample Service: ServiceMain: Worker Thread Stop Event signaled"));
/*
* Perform any cleanup tasks
*/
SvcReportEvent(_T("My Sample Service: ServiceMain: Performing Cleanup Operations"));
CloseHandle(g_ServiceStopEvent);
gSvcStatus.dwControlsAccepted = 0;
gSvcStatus.dwCurrentState = SERVICE_STOPPED;
gSvcStatus.dwWin32ExitCode = 0;
gSvcStatus.dwCheckPoint = 3;
if (SetServiceStatus(g_ServiceStatusHandle, &gSvcStatus) == FALSE)
{
SvcReportEvent(_T("My Sample Service: ServiceMain: SetServiceStatus returned error"));
}
EXIT:
SvcReportEvent(_T("My Sample Service: ServiceMain: Exit"));
return;
}
DWORD WINAPI SvcCtrlHandler(DWORD dwCtrl, DWORD eventType, void *eventData, void *context)
{
if (dwCtrl == SERVICE_CONTROL_STOP)
{
SvcReportEvent((LPTSTR)TEXT("In function SvcCtrlHandler in condition SERVICE_CONTROL_STOP"));
gSvcStatus.dwWin32ExitCode = 0;
gSvcStatus.dwCurrentState = SERVICE_STOPPED;
}
else if (dwCtrl == SERVICE_CONTROL_PRESHUTDOWN)
{
SvcReportEvent((LPTSTR)TEXT("In function SvcCtrlHandler in condition SERVICE_CONTROL_PRESHUTDOWN"));
gSvcStatus.dwWin32ExitCode = 0;
gSvcStatus.dwCurrentState = SERVICE_STOPPED;
}
SetServiceStatus(g_ServiceStatusHandle, &gSvcStatus);
return NO_ERROR;
}
DWORD WINAPI ServiceWorkerThread(LPVOID lpParam)
{
SvcReportEvent(_T("My Sample Service: ServiceWorkerThread: Entry"));
// Periodically check if the service has been requested to stop
while (WaitForSingleObject(g_ServiceStopEvent, 0) != WAIT_OBJECT_0)
{
/*
* Perform main service function here
*/
// Simulate some work by sleeping
for (size_t i = 0; i < 1000000; i++)
{
char sentence[] = "Hello World";
FILE *fptr;
fptr = fopen("C:\\test\\program.txt", "a");
if (fptr == NULL)
{
printf("Error!");
}
else
{
fprintf(fptr, "%s", sentence);
fclose(fptr);
}
Sleep(3000);
}
}
SvcReportEvent(_T("My Sample Service: ServiceWorkerThread: Exit"));
return ERROR_SUCCESS;
}

Related

Detect if system is about to restart or shutdown in Windows Service C program

I want to know if it is possible to detect whether the system is shutting down or about to restart from Windows Service code.
In my Windows service:
If system is going to restart, I want to perform some actions.
If system is going to shutdown, I don't need to run any actions.
I am familiar with using Windows Pre-Shutown flag used for performing critical actiosn before shutdown. But I don't know any mechanism to know if system is about to restart or shutodwn.
The code to detect preshutdown event can be as follows:
#include <windows.h>
#include <WinBase.h>
#include <tchar.h>
#include <strsafe.h>
#define SVC_ERROR ((DWORD)0xC0020001L)
SERVICE_STATUS gSvcStatus = { 0 };
SERVICE_STATUS_HANDLE g_ServiceStatusHandle = NULL;
HANDLE g_ServiceStopEvent = INVALID_HANDLE_VALUE;
VOID WINAPI ServiceMain(DWORD argc, LPTSTR *argv);
DWORD WINAPI SvcCtrlHandler(DWORD dwCtrl, DWORD eventType, void *eventData, void *context);
DWORD WINAPI ServiceWorkerThread(LPVOID lpParam);
#define SVCNAME _T("SampleService")
//
// Purpose:
// Logs messages to the event log
//
// Parameters:
// szFunction - name of function that failed
//
// Return value:
// None
//
// Remarks:
// The service must have an entry in the Application event log.
//
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_INFORMATION_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);
}
}
int _tmain(int argc, TCHAR *argv[])
{
SvcReportEvent(_T("My Sample Service: Main: Entry"));
SERVICE_TABLE_ENTRY ServiceTable[] =
{
{SVCNAME, (LPSERVICE_MAIN_FUNCTION)ServiceMain},
{NULL, NULL}
};
if (StartServiceCtrlDispatcher(ServiceTable) == FALSE)
{
SvcReportEvent(_T("My Sample Service: Main: StartServiceCtrlDispatcher returned error"));
return GetLastError();
}
SvcReportEvent(_T("My Sample Service: Main: Exit"));
return 0;
}
VOID WINAPI ServiceMain(DWORD argc, LPTSTR *argv)
{
DWORD Status = E_FAIL;
SvcReportEvent(_T("My Sample Service: ServiceMain: Entry"));
g_ServiceStatusHandle = RegisterServiceCtrlHandlerEx(
SVCNAME,
SvcCtrlHandler,
NULL);
if (g_ServiceStatusHandle == NULL)
{
SvcReportEvent(_T("My Sample Service: ServiceMain: RegisterServiceCtrlHandler returned error"));
goto EXIT;
}
// Tell the service controller we are starting
ZeroMemory(&gSvcStatus, sizeof(gSvcStatus));
gSvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
gSvcStatus.dwControlsAccepted = 0;
gSvcStatus.dwCurrentState = SERVICE_START_PENDING;
gSvcStatus.dwWin32ExitCode = 0;
gSvcStatus.dwServiceSpecificExitCode = 0;
gSvcStatus.dwCheckPoint = 0;
if (SetServiceStatus(g_ServiceStatusHandle, &gSvcStatus) == FALSE)
{
SvcReportEvent(_T("My Sample Service: ServiceMain: SetServiceStatus returned error"));
}
/*
* Perform tasks neccesary to start the service here
*/
SvcReportEvent(_T("My Sample Service: ServiceMain: Performing Service Start Operations"));
// Create stop event to wait on later.
g_ServiceStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
if (g_ServiceStopEvent == NULL)
{
SvcReportEvent(_T("My Sample Service: ServiceMain: CreateEvent(g_ServiceStopEvent) returned error"));
gSvcStatus.dwControlsAccepted = 0;
gSvcStatus.dwCurrentState = SERVICE_STOPPED;
gSvcStatus.dwWin32ExitCode = GetLastError();
gSvcStatus.dwCheckPoint = 1;
if (SetServiceStatus(g_ServiceStatusHandle, &gSvcStatus) == FALSE)
{
SvcReportEvent(_T("My Sample Service: ServiceMain: SetServiceStatus returned error"));
}
goto EXIT;
}
// Tell the service controller we are started
gSvcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PRESHUTDOWN;
gSvcStatus.dwCurrentState = SERVICE_RUNNING;
gSvcStatus.dwWin32ExitCode = 0;
gSvcStatus.dwCheckPoint = 0;
if (SetServiceStatus(g_ServiceStatusHandle, &gSvcStatus) == FALSE)
{
SvcReportEvent(_T("My Sample Service: ServiceMain: SetServiceStatus returned error"));
}
// Start the thread that will perform the main task of the service
HANDLE hThread = CreateThread(NULL, 0, ServiceWorkerThread, NULL, 0, NULL);
SvcReportEvent(_T("My Sample Service: ServiceMain: Waiting for Worker Thread to complete"));
// Wait until our worker thread exits effectively signaling that the service needs to stop
WaitForSingleObject(hThread, INFINITE);
SvcReportEvent(_T("My Sample Service: ServiceMain: Worker Thread Stop Event signaled"));
/*
* Perform any cleanup tasks
*/
SvcReportEvent(_T("My Sample Service: ServiceMain: Performing Cleanup Operations"));
CloseHandle(g_ServiceStopEvent);
gSvcStatus.dwControlsAccepted = 0;
gSvcStatus.dwCurrentState = SERVICE_STOPPED;
gSvcStatus.dwWin32ExitCode = 0;
gSvcStatus.dwCheckPoint = 3;
if (SetServiceStatus(g_ServiceStatusHandle, &gSvcStatus) == FALSE)
{
SvcReportEvent(_T("My Sample Service: ServiceMain: SetServiceStatus returned error"));
}
EXIT:
SvcReportEvent(_T("My Sample Service: ServiceMain: Exit"));
return;
}
DWORD WINAPI SvcCtrlHandler(DWORD dwCtrl, DWORD eventType, void *eventData, void *context)
{
if (dwCtrl == SERVICE_CONTROL_STOP)
{
SvcReportEvent((LPTSTR)TEXT("In function SvcCtrlHandler in condition SERVICE_CONTROL_STOP"));
gSvcStatus.dwWin32ExitCode = 0;
gSvcStatus.dwCurrentState = SERVICE_STOPPED;
}
else if (dwCtrl == SERVICE_CONTROL_PRESHUTDOWN)
{
SvcReportEvent((LPTSTR)TEXT("In function SvcCtrlHandler in condition SERVICE_CONTROL_PRESHUTDOWN"));
gSvcStatus.dwWin32ExitCode = 0;
gSvcStatus.dwCurrentState = SERVICE_STOPPED;
}
SetServiceStatus(g_ServiceStatusHandle, &gSvcStatus);
return NO_ERROR;
}
DWORD WINAPI ServiceWorkerThread(LPVOID lpParam)
{
SvcReportEvent(_T("My Sample Service: ServiceWorkerThread: Entry"));
// Periodically check if the service has been requested to stop
while (WaitForSingleObject(g_ServiceStopEvent, 0) != WAIT_OBJECT_0)
{
/*
* Perform main service function here
*/
// Simulate some work by sleeping
for (size_t i = 0; i < 1000000; i++)
{
char sentence[] = "Hello World";
FILE *fptr;
fptr = fopen("C:\\test\\program.txt", "a");
if (fptr == NULL)
{
printf("Error!");
}
else
{
fprintf(fptr, "%s", sentence);
fclose(fptr);
}
Sleep(3000);
}
}
SvcReportEvent(_T("My Sample Service: ServiceWorkerThread: Exit"));
return ERROR_SUCCESS;
}
I need help form Stack overflow community to modify this code so that I can perform different actions before restart & shutdown while stopping service.
Note: It will not help me to detect restart or shutdown after system comes up. It has to be know before the system restart / shutdown itself.

In C, a cURL call anywhere, even when not executed, crashes the service

I am building a small windows service which uses cURL for a small web call.
I can link cURL without issue, but if any curl_* functions are in the code - even if none are ever called - the code crashes:
Program received signal SIGSEGV, Segmentation fault.
0x00007ff8bb75f9f8 in StartServiceCtrlDispatcherW () from C:\WINDOWS\System32\sechost.dll
Here is the offending function - commenting out just the lines calling curl_* functions stops the issue:
void phone_home(identity id, char* agent_filename, char* action)
{
CURL *curl;
CURLcode res;
char service_url[MAX_PATH_LEN], username[MAX_PATH_LEN];
curl_global_init(CURL_GLOBAL_DEFAULT);
curl = curl_easy_init();
get_username(username, MAX_PATH_LEN);
sprintf(service_url, "%s/%s?identity=%lu&user=%s&agent=%s", LISTENER_HOST, action, id, username, agent_filename);
if(curl) {
curl_easy_setopt(curl, CURLOPT_URL, service_url);
#ifdef SKIP_PEER_VERIFICATION
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L);
#endif
#ifdef SKIP_HOSTNAME_VERIFICATION
curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L);
#endif
/* Perform the request, res will get the return code */
res = curl_easy_perform(curl);
/* Check for errors */
if(res != CURLE_OK)
fprintf(stderr, "curl_easy_perform() failed: %s\n", curl_easy_strerror(res));
/* always cleanup */
curl_easy_cleanup(curl);
}
curl_global_cleanup();
}
And here is the SvcInit function that never calls that function!
VOID SvcInit( DWORD dwArgc, LPTSTR *lpszArgv)
{
int id;
identity last_id = 0;
ghSvcStopEvent = CreateEvent(
NULL, /* default security attributes */
TRUE, /* manual reset event */
FALSE, /* not signaled */
NULL); /* no name */
if ( ghSvcStopEvent == NULL)
{
ReportSvcStatus( SERVICE_STOPPED, NO_ERROR, 0 );
return;
}
ReportSvcStatus( SERVICE_RUNNING, NO_ERROR, 0 );
while(1)
{
WaitForSingleObject(ghSvcStopEvent, INFINITE);
ReportSvcStatus( SERVICE_STOPPED, NO_ERROR, 0 );
if ((id = scan_for_devices())) {
if (id != last_id) {
last_id = id;
printf("Found marked device 0x%lX!\n", id);
//phone_home(id, "", ACTION_USBINSERT);
}
} else {
last_id = 0;
}
Sleep(5000);
}
}
And the rest of the service definition code:
#include <windows.h>
#include <tchar.h>
#include <strsafe.h>
#include "include/identities.h"
#include "include/identity_agent.h"
#define SVCNAME TEXT("Test")
#define SVCSHOW TEXT("Test Agent")
#define SVCDESC TEXT("Test")
SERVICE_STATUS gSvcStatus;
SERVICE_STATUS_HANDLE gSvcStatusHandle;
HANDLE ghSvcStopEvent = NULL;
VOID WINAPI SvcCtrlHandler( DWORD );
VOID WINAPI SvcMain( DWORD, LPTSTR * );
VOID ReportSvcStatus( DWORD, DWORD, DWORD );
VOID SvcInit( DWORD, LPTSTR * );
VOID SvcReportEvent( LPTSTR );
int __cdecl _tmain(int argc, TCHAR *argv[])
{
SERVICE_TABLE_ENTRY DispatchTable[] =
{
{ SVCNAME, (LPSERVICE_MAIN_FUNCTION) SvcMain },
{ NULL, NULL }
};
if (!StartServiceCtrlDispatcher( DispatchTable ))
{
SvcReportEvent(TEXT("StartServiceCtrlDispatcher"));
}
return 0;
}
VOID WINAPI SvcMain( DWORD dwArgc, LPTSTR *lpszArgv )
{
/* Register the handler function for the service */
gSvcStatusHandle = RegisterServiceCtrlHandler(
SVCNAME,
SvcCtrlHandler);
if( !gSvcStatusHandle )
{
SvcReportEvent(TEXT("RegisterServiceCtrlHandler"));
return;
}
gSvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
gSvcStatus.dwServiceSpecificExitCode = 0;
ReportSvcStatus( SERVICE_START_PENDING, NO_ERROR, 3000 );
SvcInit( dwArgc, lpszArgv );
}
VOID SvcInit( DWORD dwArgc, LPTSTR *lpszArgv)
{
int id;
identity last_id = 0;
ghSvcStopEvent = CreateEvent(
NULL, /* default security attributes */
TRUE, /* manual reset event */
FALSE, /* not signaled */
NULL); /* no name */
if ( ghSvcStopEvent == NULL)
{
ReportSvcStatus( SERVICE_STOPPED, NO_ERROR, 0 );
return;
}
ReportSvcStatus( SERVICE_RUNNING, NO_ERROR, 0 );
while(1)
{
WaitForSingleObject(ghSvcStopEvent, INFINITE);
ReportSvcStatus( SERVICE_STOPPED, NO_ERROR, 0 );
if ((id = scan_for_devices())) {
if (id != last_id) {
last_id = id;
printf("Found marked device 0x%lX!\n", id);
//phone_home(id, "", ACTION_USBINSERT);
}
} else {
last_id = 0;
}
Sleep(5000);
}
}
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,
EVENTLOG_ERROR_TYPE, /* event type */
0, /* event category */
/*SVC_ERROR*/0, /* 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);
}
}
I am compiling with gcc -o bin/identity_service identity_agent.c identities.c -lcurl
As it turns out, I had not linked cURL statically, so it was looking for the cURL DLLs - which were in the mingw bin directory.... which was in my USER's path....... which services running under system cannot see
I linked curl statically with -DCURL_STATICLIB and all is right with the world

monitor session change event in c

I try to build a service that monitor user sessions activity. currently focusing on logon and lock of user.
i am using http://msdn.microsoft.com/en-us/library/bb540475(v=VS.85).aspx example
my code :
#include <windows.h>
#include <tchar.h>
#include <strsafe.h>
#pragma comment(lib, "advapi32.lib")
#define SVCNAME TEXT("SvcName")
#define SVC_ERROR 4
SERVICE_STATUS gSvcStatus;
SERVICE_STATUS_HANDLE gSvcStatusHandle;
HANDLE ghSvcStopEvent = NULL;
VOID SvcInstall(void);
DWORD WINAPI SvcCtrlHandler(DWORD , DWORD , LPVOID , LPVOID );
VOID WINAPI SvcMain(DWORD, LPTSTR *);
VOID ReportSvcStatus(DWORD, DWORD, DWORD);
VOID SvcInit(DWORD, LPTSTR *);
VOID SvcReportEvent(LPTSTR);
void __cdecl _tmain(int argc, TCHAR *argv[])
{
if (lstrcmpi(argv[1], TEXT("install")) == 0)
{
SvcInstall();
return;
}
SERVICE_TABLE_ENTRY DispatchTable[] =
{
{ SVCNAME, (LPSERVICE_MAIN_FUNCTION)SvcMain },
{ NULL, NULL }
};
if (!StartServiceCtrlDispatcher(DispatchTable))
{
SvcReportEvent(TEXT("StartServiceCtrlDispatcher"));
}
}
VOID SvcInstall()
{
SC_HANDLE schSCManager;
SC_HANDLE schService;
TCHAR szPath[MAX_PATH];
if (!GetModuleFileName(NULL, szPath, MAX_PATH))
{
printf("Cannot install service (%d)\n", GetLastError());
return;
}
schSCManager = OpenSCManager(
NULL, // local computer
NULL, // ServicesActive database
SC_MANAGER_ALL_ACCESS); // full access rights
if (NULL == schSCManager)
{
printf("OpenSCManager failed (%d)\n", GetLastError());
return;
}
// Create the service
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_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
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 WINAPI SvcMain(DWORD dwArgc, LPTSTR *lpszArgv)
{
gSvcStatusHandle = RegisterServiceCtrlHandler(SVCNAME,SvcCtrlHandler,NULL);
OutputDebugString(L"\n***SVCMAIN");
if (!gSvcStatusHandle)
{
SvcReportEvent(TEXT("RegisterServiceCtrlHandler"));
return;
}
gSvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
gSvcStatus.dwServiceSpecificExitCode = 0;
ReportSvcStatus(SERVICE_START_PENDING, NO_ERROR, 3000);
SvcInit(dwArgc, lpszArgv);
}
VOID SvcInit(DWORD dwArgc, LPTSTR *lpszArgv)
{
FILE *f = fopen("c:\\test\\file.txt", "a");
OutputDebugString(L"\n***SVCINIT");
fprintf(f, "init\n");
fclose(f);
ghSvcStopEvent = CreateEvent(
NULL, // default security attributes
TRUE, // manual reset event
FALSE, // not signaled
NULL); // no name
if (ghSvcStopEvent == NULL)
{
ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0);
return;
}
ReportSvcStatus(SERVICE_RUNNING, NO_ERROR, 0);
while (WaitForSingleObject(ghSvcStopEvent, 3000) != WAIT_OBJECT_0){
OutputDebugString(L"\n***BEEP");
f = fopen("c:\\test\\file.txt", "a");
fprintf(f, "beep\n");
fclose(f);
Beep(1000, 100);
}
ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0);
}
VOID ReportSvcStatus(DWORD dwCurrentState,
DWORD dwWin32ExitCode,
DWORD dwWaitHint)
{
static DWORD dwCheckPoint = 1;
DWORD my_error = 0;
// Fill in the SERVICE_STATUS structure.
gSvcStatus.dwCurrentState = dwCurrentState;
gSvcStatus.dwWin32ExitCode = dwWin32ExitCode;
gSvcStatus.dwWaitHint = dwWaitHint;
gSvcStatus.dwControlsAccepted = SERVICE_ACCEPT_SESSIONCHANGE | 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);
my_error = GetLastError();
FILE *f = fopen("c:\\test\\file.txt", "a");
fprintf(f, "last error %d \n",my_error);
fprintf(f, "\n***controls accepted %d ***\n", gSvcStatus.dwControlsAccepted);
fclose(f);
}
DWORD WINAPI SvcCtrlHandler(DWORD dwControl, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext)
{
DWORD dwErrorCode = NO_ERROR;
FILE *f = fopen("c:\\test\\file.txt", "a");
// Handle the requested control code.
fprintf(f, "dwCtrl is = %d \n", dwControl);
fclose(f);
switch (dwControl)
{
case SERVICE_CONTROL_TIMECHANGE:
f = fopen("c:\\test\\file.txt", "a");
fprintf(f, "time\n");
fclose(f);
OutputDebugString(L"\n****GOT time!!!\n\n");
SetEvent(ghSvcStopEvent);
ReportSvcStatus(gSvcStatus.dwCurrentState, NO_ERROR, 0);
break;
case SERVICE_CONTROL_SESSIONCHANGE:
f = fopen("c:\\test\\file.txt", "a");
fprintf(f, "session\n");
fclose(f);
OutputDebugString(L"\n****GOT Session!\n\n");
SetEvent(ghSvcStopEvent);
ReportSvcStatus(gSvcStatus.dwCurrentState, NO_ERROR, 0);
break;
case SERVICE_CONTROL_STOP:
OutputDebugString(L"\n****GOT STOP!\n\n");
f = fopen("c:\\test\\file.txt", "a");
fprintf(f, "stop\n");
fclose(f);
ReportSvcStatus(SERVICE_STOP_PENDING, NO_ERROR, 0);
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);
}
}
any ideas why i am not getting any "case SERVICE_CONTROL_SESSIONCHANGE" and only stop?
in my log file i see the beep log and controls accepted - 129 (stop + session change)
this is my log file content :
last error 0
***controls accepted 129 ***
init
last error 0
***controls accepted 129 ***
beep
beep
beep
beep
beep
gSvcStatusHandle = RegisterServiceCtrlHandler(SVCNAME,SvcCtrlHandler,NULL);
should be :
gSvcStatusHandle = RegisterServiceCtrlHandlerEx(SVCNAME,SvcCtrlHandler,NULL);

Windows Service implementation - Error 1053: The service did not respond to start or control request in a timely fashion

I am trying to make a small Windows service in C but get stuck on where is the issue. Once I start it in Windows services, I recieve error:
"Windows could not start the MyService service on local computer.
Error 1053: The service did not respond to start or control request in a timely fashion."
#include <unistd.h>
#include <winsock2.h>
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include "log.h"
#define SERVICE "MyService"
#define SERVICE_UNKNOW 0x00000000
#define SERVICE_REFRESH 0xFFFFFFFF
SERVICE_STATUS_HANDLE serviceHandle;
void ServiceUpdateStatus(SERVICE_STATUS_HANDLE serviceHandle, DWORD newState)
{
static SERVICE_STATUS serviceStatus;
if (newState == SERVICE_UNKNOW)
{
serviceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
serviceStatus.dwWin32ExitCode = NO_ERROR;
serviceStatus.dwServiceSpecificExitCode = NO_ERROR;
serviceStatus.dwCheckPoint = 0;
serviceStatus.dwWaitHint = 0;
newState = SERVICE_STOPPED;
}
switch(newState)
{
case SERVICE_START_PENDING:
serviceStatus.dwCurrentState = SERVICE_START_PENDING;
serviceStatus.dwControlsAccepted = 0;
SetServiceStatus(serviceHandle, &serviceStatus);
add_log("Service start pending");
break;
case SERVICE_RUNNING:
serviceStatus.dwCurrentState = SERVICE_RUNNING;
serviceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP|SERVICE_ACCEPT_SHUTDOWN;
SetServiceStatus(serviceHandle, &serviceStatus);
add_log("Service running");
break;
case SERVICE_STOP_PENDING:
serviceStatus.dwCurrentState = SERVICE_STOP_PENDING;
serviceStatus.dwControlsAccepted = 0;
SetServiceStatus(serviceHandle, &serviceStatus);
add_log("Service stop pending");
break;
case SERVICE_STOPPED:
serviceStatus.dwCurrentState = SERVICE_STOPPED;
serviceStatus.dwControlsAccepted = 0;
SetServiceStatus(serviceHandle, &serviceStatus);
add_log("Service stopped");
break;
case SERVICE_REFRESH:
SetServiceStatus(serviceHandle, &serviceStatus);
break;
}
}
void WINAPI ServiceControlHandler(DWORD controlCode)
{
switch (controlCode)
{
case SERVICE_CONTROL_PAUSE:
case SERVICE_CONTROL_CONTINUE:
case SERVICE_CONTROL_INTERROGATE:
break;
case SERVICE_CONTROL_SHUTDOWN:
case SERVICE_CONTROL_STOP:
/* stop service */
ServiceUpdateStatus(serviceHandle, SERVICE_STOP_PENDING);
make_ServiceMainThread_to_return();
WSACleanup();
/* stopped */
ServiceUpdateStatus(serviceHandle, SERVICE_STOPPED);
break;
}
ServiceUpdateStatus(serviceHandle, SERVICE_REFRESH);
}
DWORD ServiceMainThread(LPVOID parameters)
{
do_something_and_never_return();
return EXIT_SUCCESS;
}
VOID WINAPI ServiceMain(DWORD argc, char *argv[])
{
WSADATA wsa;
HANDLE mainThread;
serviceHandle = RegisterServiceCtrlHandler(SERVICE, ServiceControlHandler);
if(!serviceHandle)
{
add_log("Error: RegisterServiceCtrlHandler, error %u", (unsigned int)GetLastError());
return;
}
/* init service */
ServiceUpdateStatus(serviceHandle, SERVICE_START_PENDING);
if (WSAStartup(MAKEWORD(2,2), &wsa) != 0)
{
add_log("Error: WSAStartup, error %u", (unsigned int)GetLastError());
return;
}
mainThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)&ServiceMainThread, NULL, 0, NULL);
if (mainThread == NULL)
{
ServiceUpdateStatus(serviceHandle, SERVICE_STOPPED);
add_log("Error: Unable to create service thread, error %u", (unsigned int)GetLastError());
return;
}
add_log("Service main thread: %u", (unsigned int)mainThread);
CloseHandle(mainThread);
/* run service */
ServiceUpdateStatus(serviceHandle, SERVICE_RUNNING);
}
void LaunchService()
{
SERVICE_TABLE_ENTRY ServiceTable[2];
ServiceTable[0].lpServiceName = SERVICE;
ServiceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)ServiceMain;
ServiceTable[1].lpServiceName = NULL;
ServiceTable[1].lpServiceProc = NULL;
if (!StartServiceCtrlDispatcher(ServiceTable))
{
add_log("Error: StartServiceCtrlDispatcher, error %u", (unsigned int)GetLastError());
}
}
void InstallService()
{
SC_HANDLE scManager;
char path[MAX_PATH+1];
scManager = OpenSCManager(0, 0, SC_MANAGER_CREATE_SERVICE );
if (scManager)
{
if (GetModuleFileName( 0, path, sizeof(path)) > 0)
{
SC_HANDLE service;
service = CreateService(scManager, SERVICE, SERVICE, SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
SERVICE_AUTO_START, SERVICE_ERROR_IGNORE, path, 0, 0, 0, 0, 0 );
if (service)
CloseServiceHandle(service);
}
CloseServiceHandle(scManager);
}
}
void UninstallService()
{
SC_HANDLE scManager;
SC_HANDLE scService;
SERVICE_STATUS serviceStatus;
scManager = OpenSCManager( 0, 0, SC_MANAGER_CONNECT );
if (scManager)
{
scService = OpenService(scManager, SERVICE, SERVICE_QUERY_STATUS|DELETE);
if (scService)
{
if (QueryServiceStatus(scService, &serviceStatus))
{
if (serviceStatus.dwCurrentState == SERVICE_STOPPED)
DeleteService(scService);
}
CloseServiceHandle(scService);
}
CloseServiceHandle(scService);
}
}
int main(int argc, char *argv[])
{
if(strcmpi(argv[1], "install") == 0)
{
InstallService();
return EXIT_SUCCESS;
}
else if(strcmpi(argv[1], "uninstall") == 0)
{
UninstallService();
return EXIT_SUCCESS;
}
LaunchService();
return EXIT_SUCCESS;
}
Any ideas maybe?
Thanks in advance,
I found the issue.
During *_PENDING operation, we must specify the dwWaitHint field.
SetServiceStatus was reporting an error due to this and never updating the service status.
My corrected function ServiceUpdateStatus:
#define SERVICE_REFRESH 0xFFFFFFFF
// ...
void ServiceUpdateStatus(DWORD newState)
{
static SERVICE_STATUS serviceStatus;
serviceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
serviceStatus.dwWin32ExitCode = NO_ERROR;
serviceStatus.dwServiceSpecificExitCode = NO_ERROR;
switch(newState)
{
case SERVICE_START_PENDING:
serviceStatus.dwControlsAccepted = 0;
serviceStatus.dwCheckPoint = 1;
serviceStatus.dwWaitHint = 1000;
serviceStatus.dwCurrentState = SERVICE_START_PENDING;
add_log("Service start pending");
break;
case SERVICE_RUNNING:
serviceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP|SERVICE_ACCEPT_SHUTDOWN;
serviceStatus.dwCheckPoint = 0;
serviceStatus.dwCurrentState = SERVICE_RUNNING;
add_log("Service running");
break;
case SERVICE_STOP_PENDING:
serviceStatus.dwControlsAccepted = 0;
serviceStatus.dwCheckPoint = 1;
serviceStatus.dwWaitHint = 1000;
serviceStatus.dwCurrentState = SERVICE_STOP_PENDING;
add_log("Service stop pending");
break;
case SERVICE_STOPPED:
serviceStatus.dwControlsAccepted = 0;
serviceStatus.dwCheckPoint = 0;
serviceStatus.dwCurrentState = SERVICE_STOPPED;
add_log("Service stopped");
break;
case SERVICE_REFRESH:
if (serviceStatus.dwCurrentState == SERVICE_STOP_PENDING &&
serviceStatus.dwCurrentState == SERVICE_START_PENDING)
serviceStatus.dwCheckPoint++;
break;
}
if (!SetServiceStatus(serviceHandle, &serviceStatus))
add_log("SetServiceStatus failed, error %u", GetLastError());
}
// ...

How to install/deinstall a Windows service in win32?

I am trying to create a Win32 program that could delete temporary files in a specific path.
But I am actually in trouble with the install/uninstall functions in my code.
I'm working on Visual Studio 2012 and when I launch the debug process to test my code the debug window is closed immediately.
Maybe the problem is not coming from VS 2012 but from my code?
Here it is:
/*
** INCLUDES
*/
#include <Windows.h>
#include <stdio.h>
/*
** MACROS
*/
# define MY_SERVICE_NAME "DiskCleaner"
# define MY_SERVICE_DISPLAY_NAME "Nettoyeur de disque"
SERVICE_STATUS my_ServiceStatus;
SERVICE_STATUS_HANDLE my_ServiceStatusHandle;
BOOL bRunning;
BOOL InstallMyService();
BOOL DeleteMyService();
void WINAPI ServiceCtrlHandler(DWORD Opcode);
void WINAPI ServiceMain(DWORD argc, LPTSTR *argv);
/* INSTALL THE SERVICE */
BOOL InstallMyService()
{
char strDir[MAX_PATH];
SC_HANDLE hSCManager;
SC_HANDLE hService;
LPCTSTR lpBinaryPathName;
GetCurrentDirectory(MAX_PATH, strDir);
strcat(strDir, "\\AutoClean.exe");
hSCManager = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (hSCManager == NULL)
return (FALSE);
lpBinaryPathName=strDir;
hService = CreateService(
hSCManager, MY_SERVICE_NAME,
MY_SERVICE_DISPLAY_NAME, SERVICE_ALL_ACCESS,
SERVICE_WIN32_OWN_PROCESS,
SERVICE_AUTO_START,
SERVICE_ERROR_NORMAL,
lpBinaryPathName,
NULL,
NULL,
NULL,
NULL,
NULL);
if (hService == NULL)
return (FALSE);
CloseServiceHandle(hService);
return (TRUE);
}
/* DELETE THE SERVICE */
BOOL DeleteMyService()
{
SC_HANDLE hSCManager;
SC_HANDLE hService;
hSCManager = OpenSCManager (NULL, NULL, SC_MANAGER_ALL_ACCESS);
if (hSCManager == NULL)
return (FALSE);
hService = OpenService (hSCManager, MY_SERVICE_NAME, SERVICE_ALL_ACCESS);
if (hService == NULL)
return (FALSE);
if (DeleteService(hService) == NULL)
return (FALSE);
if (CloseServiceHandle(hService) == NULL)
return (FALSE);
return (TRUE);
}
/* SERVICE EVENT HANDLER */
void WINAPI ServiceCtrlHandler(DWORD Opcode)
{
switch (Opcode)
{
case SERVICE_CONTROL_PAUSE:
my_ServiceStatus.dwCurrentState = SERVICE_PAUSED;
break;
case SERVICE_CONTROL_CONTINUE:
my_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
break;
case SERVICE_CONTROL_STOP:
my_ServiceStatus.dwWin32ExitCode = 0;
my_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
my_ServiceStatus.dwCheckPoint = 0;
my_ServiceStatus.dwWaitHint = 0;
SetServiceStatus (my_ServiceStatusHandle, &my_ServiceStatus);
bRunning = FALSE;
break;
case SERVICE_CONTROL_INTERROGATE:
break;
default:
break;
}
return;
}
/* SERVICE ENTRY POINT */
void WINAPI ServiceMain(DWORD argc, LPTSTR *argv)
{
DWORD Status;
DWORD SpecificError;
my_ServiceStatus.dwServiceType = SERVICE_WIN32;
my_ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
my_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
my_ServiceStatus.dwWin32ExitCode = 0;
my_ServiceStatus.dwServiceSpecificExitCode = 0;
my_ServiceStatus.dwCheckPoint = 0;
my_ServiceStatus.dwWaitHint = 0;
my_ServiceStatusHandle = RegisterServiceCtrlHandler(MY_SERVICE_NAME, ServiceCtrlHandler);
if (my_ServiceStatusHandle == (SERVICE_STATUS_HANDLE)0)
{
return;
}
my_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
my_ServiceStatus.dwCheckPoint = 0;
my_ServiceStatus.dwWaitHint = 0;
SetServiceStatus(my_ServiceStatusHandle, &my_ServiceStatus);
bRunning = TRUE;
while (bRunning)
{
printf("\nOK just to test if this part works well before implementing my cleaning part\n");
}
return;
}
/* ENTRY POINT */
int main(int argc, char* argv[])
{
if (argc > 1)
{
if (strcmp(argv[1], "-i"))
{
if (InstallMyService())
printf("\nService successfully installed\n");
else
printf("\nService installtion unsuccessfull\n");
}
else if (strcmp(argv[1], "-d"))
{
if (DeleteMyService())
printf("\nService successfully deleted\n");
else
printf("\nService delete unsuccesfull\n");
}
else
printf("\nUsage incorrect\n");
}
else
{
SERVICE_TABLE_ENTRY DispatchTable[]={{MY_SERVICE_NAME, ServiceMain}, {NULL, NULL}};
StartServiceCtrlDispatcher(DispatchTable);
}
return (EXIT_SUCCESS);
}
In your main function you have errors:
if (strcmp(argv[1], "-i"))
if (strcmp(argv[1], "-d"))
This condition is FALSE, so your InstallMyService() / DeleteMyService() is not executed.
Also for sake of complexity you forgot close service manager handle.
I've corrected my code and it works now. This is the entire solution :
#include <Windows.h>
#include <stdio.h>
/*
** MACROS
*/
# define MY_SERVICE_NAME "DiskCleaner"
# define MY_SERVICE_DESCRIPTOR "Nettoyeur de fichiers temporaires"
# define MY_SERVICE_BIN_NAME "DiskCleaner.exe"
/*
** GLOBALS
*/
SERVICE_STATUS g_ServiceStatus;
SERVICE_STATUS_HANDLE g_ServiceStatusHandle;
/*
** INSTALL THE SERVICE
*/
BOOL InstallMyService()
{
char strDir[MAX_PATH + 1];
SC_HANDLE schSCManager;
SC_HANDLE schService;
LPCTSTR lpszBinaryPathName;
GetCurrentDirectory(MAX_PATH, strDir);
strcat(strDir, "\\"MY_SERVICE_BIN_NAME);
if ((schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS)) == NULL)
return (TRUE);
lpszBinaryPathName = strDir;
schService = CreateService(schSCManager, MY_SERVICE_NAME, MY_SERVICE_DESCRIPTOR,
SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
lpszBinaryPathName, NULL, NULL, NULL, NULL, NULL);
if (schService == NULL)
return (FALSE);
CloseServiceHandle(schService);
return (TRUE);
}
/*
** DELETE THE SERVICE
*/
BOOL DeleteMyService()
{
SC_HANDLE schSCManager;
SC_HANDLE hService;
if ((schSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS)) == NULL)
return (FALSE);
if ((hService = OpenService(schSCManager, MY_SERVICE_NAME, SERVICE_ALL_ACCESS)) == NULL)
return (FALSE);
if (!DeleteService(hService))
return (FALSE);
if (!CloseServiceHandle(hService))
return (FALSE);
return (TRUE);
}
/*
** SERVICE EVENT HANDLER
*/
void WINAPI ServiceCtrlHandler(DWORD Opcode)
{
switch (Opcode)
{
case SERVICE_CONTROL_PAUSE:
g_ServiceStatus.dwCurrentState = SERVICE_PAUSED;
break;
case SERVICE_CONTROL_CONTINUE:
g_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
break;
case SERVICE_CONTROL_STOP:
g_ServiceStatus.dwWin32ExitCode = 0;
g_ServiceStatus.dwCurrentState = SERVICE_STOPPED;
g_ServiceStatus.dwCheckPoint = 0;
g_ServiceStatus.dwWaitHint = 0;
SetServiceStatus (g_ServiceStatusHandle, &g_ServiceStatus);
break;
case SERVICE_CONTROL_INTERROGATE:
break;
default:
break;
}
}
/*
** SERVICE MAIN ENTRY
*/
void WINAPI ServiceMain(DWORD argc, LPTSTR *argv)
{
g_ServiceStatus.dwServiceType = SERVICE_WIN32;
g_ServiceStatus.dwCurrentState = SERVICE_START_PENDING;
g_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
g_ServiceStatus.dwWin32ExitCode = 0;
g_ServiceStatus.dwServiceSpecificExitCode = 0;
g_ServiceStatus.dwCheckPoint = 0;
g_ServiceStatus.dwWaitHint = 0;
g_ServiceStatusHandle = RegisterServiceCtrlHandler(MY_SERVICE_NAME, ServiceCtrlHandler);
if (g_ServiceStatusHandle == (SERVICE_STATUS_HANDLE)0)
return;
g_ServiceStatus.dwCurrentState = SERVICE_RUNNING;
g_ServiceStatus.dwCheckPoint = 0;
g_ServiceStatus.dwWaitHint = 0;
SetServiceStatus(g_ServiceStatusHandle, &g_ServiceStatus);
}
/*
** MAIN ENTRY
*/
int main(int argc, char* argv[])
{
if (argc > 1)
{
if (!strcmp(argv[1], "-i"))
if(InstallMyService())
printf("\nService correctly installed\n");
else
printf("\nService uncorrectly installed\n");
else if (!strcmp(argv[1], "-d"))
if(DeleteMyService())
printf("\nService correctly deleted\n");
else
printf("\nService uncorrectly deleted\n");
}
else
{
SERVICE_TABLE_ENTRY DispatchTable[]={{MY_SERVICE_NAME, ServiceMain}, {NULL, NULL}};
StartServiceCtrlDispatcher(DispatchTable);
}
return (EXIT_SUCCESS);
}

Resources