Windows Service App in C++


This is C++ code for minimal windows service including functionarities of installation and uninstallation.

svc.cpp
#include "SvcApp.h"
#include <assert.h>
#include <stdarg.h>

#define SERVICE_NAME "ScvApp"
#define DEBUG_BUFF_SIZE (1024)
#define SERVICE_CONTROL_EXEC 128

SERVICE_TABLE_ENTRY ServiceTable[] = {
          { (LPSTR)SERVICE_NAME, ServiceMain },
          { NULL, NULL }
};

BOOL g_bRun = TRUE;
BOOL g_bService = TRUE;

SERVICE_STATUS_HANDLE g_hServiceStatus = NULL;

int main() {

	LPWSTR buf = NULL;
	int dst_size = 0;
	int rc = 0;

	rc = MultiByteToWideChar(CP_ACP, 0, GetCommandLine(), -1, NULL, 0);
	if (rc == 0) {
		return NULL;
	}

	dst_size = rc + 1;
	buf = (LPWSTR) malloc(sizeof(WCHAR) * dst_size);
	if (buf == NULL) {
		return NULL;
	}

	rc = MultiByteToWideChar(CP_ACP, 0, GetCommandLine(), -1, buf, dst_size);
	if (rc == 0) {
		free(buf);
		return NULL;
	}
	buf[rc] = L'\0';

	int nArgc = 0;
	WCHAR** lppArgv = CommandLineToArgvW( buf, &nArgc );
	if(lppArgv == NULL){
		free(buf);
		return -1;
	}

	for(int i = 0;i < nArgc; i++){
		WCHAR* arg = *(lppArgv + i);
		if(!arg){
			return -1;
		}

		if(wcscmp(arg, L"Install") == 0){
			InstallService();
			MessageBox(NULL,"instlation finished","Debug",MB_OK);
			return 0;
		} else if(wcscmp(arg, L"Uninstall") == 0){
			UninstallService();
			MessageBox(NULL,"uninstlation finished","Debug",MB_OK);
			return 0;
		}
	}

	StartServiceCtrlDispatcher (ServiceTable);

    return 0;
}

DWORD WINAPI HandlerEx (
	DWORD dwControl,
	DWORD dwEventType,
	LPVOID lpEventData,
	LPVOID lpContext ) {

     SERVICE_STATUS ss;
     BOOL bRet;

     // Initialize Variables for Service Control
     ss.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
     ss.dwWin32ExitCode = NO_ERROR;
     ss.dwServiceSpecificExitCode = 0;
     ss.dwCheckPoint = 1;
     ss.dwWaitHint = 3000;
     ss.dwControlsAccepted = SERVICE_ACCEPT_STOP;

     switch(dwControl) {
     case SERVICE_CONTROL_STOP:

          // Set STOP_PENDING status.
          ss.dwCurrentState = SERVICE_STOP_PENDING;

          bRet = SetServiceStatus (g_hServiceStatus, &ss);

          if (!bRet) {
               break;
          }

         // SERVICE SPECIFIC STOPPING CODE HERE.
          // ...
          // ...

          g_bService = FALSE;
          Sleep (3 * 1000);

          // Set STOPPED status.
          ss.dwCurrentState = SERVICE_STOPPED;
          ss.dwCheckPoint = 0;
          ss.dwWaitHint = 0;

          bRet = SetServiceStatus (g_hServiceStatus, &ss);

          if (!bRet) {
               break;
          }

          break;

     case SERVICE_CONTROL_PAUSE:

          // Set PAUSE_PENDING status.
          ss.dwCurrentState = SERVICE_PAUSE_PENDING;

          bRet = SetServiceStatus (g_hServiceStatus, &ss);

          if (!bRet) {
               break;
          }

          // APPLICATION SPECIFIC PAUSE_PENDING CODE HERE.

          g_bRun = FALSE;

          // Set SERVICE_PAUSED status.
          ss.dwCurrentState = SERVICE_PAUSED;
          ss.dwCheckPoint = 0;
          ss.dwWaitHint = 0;
          ss.dwControlsAccepted |= SERVICE_ACCEPT_PAUSE_CONTINUE;

          bRet = SetServiceStatus (g_hServiceStatus, &ss);

          if (!bRet) {
               break;
          }

          break;

     case SERVICE_CONTROL_CONTINUE:

          // Set PAUSE_PENDING status.
          ss.dwCurrentState = SERVICE_START_PENDING;

          bRet = SetServiceStatus (g_hServiceStatus, &ss);

          if (!bRet) {
               break;
          }

          // APPLICATION SPECIFIC START_PENDING CODE HERE.

          g_bRun = TRUE;

          // Set RUNNING status.
          ss.dwCurrentState = SERVICE_RUNNING;
          ss.dwCheckPoint = 0;
          ss.dwWaitHint = 0;
          ss.dwControlsAccepted |= SERVICE_ACCEPT_PAUSE_CONTINUE;

          bRet = SetServiceStatus (g_hServiceStatus, &ss);

          if (!bRet) {
               break;
          }

          break;
     default:

          return ERROR_CALL_NOT_IMPLEMENTED;

     }

     return NO_ERROR;
}

VOID WINAPI ServiceMain(DWORD dwArgc, PTSTR* pszArgv) {

     BOOL bRet;
     SERVICE_STATUS ss;

     // Initialize Variables for Service Control
     ss.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
     ss.dwWin32ExitCode = NO_ERROR;
     ss.dwServiceSpecificExitCode = 0;
     ss.dwCheckPoint = 1;
     ss.dwWaitHint = 1000;
     ss.dwControlsAccepted = SERVICE_ACCEPT_STOP;

     // Register Service Control Handler
     g_hServiceStatus =
          RegisterServiceCtrlHandlerEx (SERVICE_NAME, HandlerEx, NULL);

     if(0 == g_hServiceStatus) {
          return;
     }

     // Entering Starting Service.
     ss.dwCurrentState = SERVICE_START_PENDING;

     bRet = SetServiceStatus (g_hServiceStatus, &ss);

     if (!bRet) {
          return;
     }

     // APPLICATION SPECIFIC INITIALIZATION CODE


     // Finish Initializing.
     ss.dwCurrentState = SERVICE_RUNNING;
     ss.dwCheckPoint = 0;
     ss.dwWaitHint = 0;
     ss.dwControlsAccepted =
          SERVICE_ACCEPT_PAUSE_CONTINUE |
          SERVICE_ACCEPT_STOP;

     bRet = SetServiceStatus (g_hServiceStatus, &ss);

     if (!bRet) {
          return;
     }

	//
	// Service Main Code.
	//

     MSG msg = {0};
     while(g_bService) {
    	 if(PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)){
    		 if(!GetMessage(&msg, NULL, 0 ,0 )){
    			 break;
    		 }
    		 TranslateMessage(&msg);
    		 DispatchMessage(&msg);
    	 }
          Sleep(1 * 1000);
     }

}

bool InstallService()
{
    SC_HANDLE hSCM = NULL;
    SC_HANDLE hService = NULL;
    TCHAR szBinaryPathName[MAX_PATH];
    SERVICE_DESCRIPTION sd;
    bool bRet = FALSE;

    hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE);
    if (hSCM == NULL) {
        goto EXIT;
    }

    //Get Path
    GetModuleFileName(NULL,
        szBinaryPathName,
        sizeof(szBinaryPathName)/sizeof(szBinaryPathName[0]));

    //Register My Service
    hService = CreateService(hSCM, 
        "SvcApp",
        "SvcApp",
        SERVICE_CHANGE_CONFIG,
        SERVICE_WIN32_OWN_PROCESS, 
        SERVICE_DEMAND_START,
        SERVICE_ERROR_IGNORE,
        szBinaryPathName,
        NULL,
        NULL,
        NULL,
        NULL,
        NULL);

    if (hService == NULL) {
        goto EXIT;
    }

    sd.lpDescription = (LPSTR)"This is SvcApp."; //Description

    ChangeServiceConfig2(hService, SERVICE_CONFIG_DESCRIPTION, &sd);

    bRet = true;

EXIT:
    //Crean up
    CloseServiceHandle(hService);
    CloseServiceHandle(hSCM);

    return bRet;
}

bool UninstallService()
{
    SC_HANDLE hSCM = NULL;
    SC_HANDLE hService = NULL;
    bool bRet = FALSE;

    hSCM = OpenSCManager(NULL, NULL, SC_MANAGER_CONNECT);
    if (hSCM == NULL) {
        goto EXIT;
    }

    //Calling Delete Service Function
    hService = OpenService(hSCM, SERVICE_NAME, DELETE);
    if (hService == NULL) {
        goto EXIT;
    }

    //Delete My Service
    if (DeleteService(hService) == FALSE) {
        goto EXIT;
    }

    bRet = true;

EXIT:
    //Crean up
    CloseServiceHandle(hSCM);
    CloseServiceHandle(hService);

    return bRet;
}
Profile
I have technical job experience in enbedded software development and server side infrastructure/application engineering. I'm interested in programming and computer security.
Objective
To write down my technical knowledge in the place where I can access from anywhere. To share my program source code. To train my writing skill.
Link
  • LinkedIn (preparing)

  • Twitter

  • Facebook (preparing)

  • GitHub

  • StackOverFlow (preparing)

Archives