#include <windows.h>
#include <cstdio>
#include <iostream>

#pragma comment(lib, "advapi32.lib")
using namespace std;



void StartService_(char argv[]);
void ShutdownService(char argv[]);
void EnumServices();
void CreateService_(char argv[]);
void RemoveService(char argv[]);

SC_HANDLE hSCManager;

unsigned const char State[][30] = {"UNKNOWN",
                                "SERVICE_STOPPED",
                                "SERVICE_START_PENDING",
                                "SERVICE_STOP_PENDING",
                                "SERVICE_RUNNING",
                                "SERVICE_CONTINUE_PENDING",
                                "SERVICE_PAUSE_PENDING",
                                "SERVICE_PAUSED"};

unsigned const char Type[][30] = {"UNKNOWN",
                                "SERVICE_KERNEL_DRIVER",
                                "SERVICE_FILE_SYSTEM_DRIVER",
                                "UNKNOWN",
                                "UNKNOWN",
                                "UNKNOWN",
                                "UNKNOWN",
                                "UNKNOWN",
                                "UNKNOWN",
                                "UNKNOWN",
                                "UNKNOWN",
                                "UNKNOWN",
                                "UNKNOWN",
                                "UNKNOWN",
                                "UNKNOWN",
                                "UNKNOWN",
                                "SERVICE_WIN32_OWN_PROCESS",
                                "UNKNOWN",
                                "UNKNOWN",
                                "UNKNOWN",
                                "UNKNOWN",
                                "UNKNOWN",
                                "UNKNOWN",
                                "UNKNOWN",
                                "UNKNOWN",
                                "UNKNOWN",
                                "UNKNOWN",
                                "UNKNOWN",
                                "UNKNOWN",
                                "UNKNOWN",
                                "UNKNOWN",
                                "UNKNOWN",
                                "SERVICE_WIN32_SHARE_PROCESS"};


int main(int args, char *argv[])
{

    /*
    SC_HANDLE WINAPI OpenSCManager(
          __in_opt  LPCTSTR lpMachineName,
          __in_opt  LPCTSTR lpDatabaseName,
          __in      DWORD dwDesiredAccess
        );

    http://msdn2.microsoft.com/en-us/library/ms684323(VS.85).aspx
    http://msdn2.microsoft.com/en-us/library/ms685981(VS.85).aspx
    */
    hSCManager = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);


    cout<<"\n**************| Gestionnaire de services par lilxam |***************\n\n";

    char service_name[500];
    int action = 0;

    memset(service_name, 0, sizeof(service_name));

    start:
        cout<<"\nTapez \"enum\" pour enumerer les services\nOu entrez un nom de service : ";
        cin>>service_name;

    if(!strcmp(service_name, "enum"))
    {
        EnumServices();
        goto start;
    }

    menu:
        cout<<"\n\n***** Menu :\n--- 1 -> Demarrer le service\n--- 2 -> Arreter le service\n--- 3 -> Enumerer les services\n--- 4 -> Creer un service\n--- 5 -> Effacer un service\n\n--- 6 -> Choix du service\n--- 7 -> Quitter\n\n";
        cin>>action;
    switch(action)
    {
        case 1:
            StartService_(service_name);
            break;
        case 2:
            ShutdownService(service_name);
            break;
        case 3:
            EnumServices();
            break;
        case 4:
            CreateService_(service_name);
            break;
        case 5:
            RemoveService(service_name);
            break;
        case 6:
            goto start;
            break;
        case 7:
            goto exit;
            break;
    }

    goto menu;

    exit:
        CloseServiceHandle(hSCManager);
        cout<<"\n\n********** GOODBYE **********";
        Sleep(3);
        return 0;
}

/*
SC_HANDLE WINAPI OpenService(
  __in  SC_HANDLE hSCManager,
  __in  LPCTSTR lpServiceName,
  __in  DWORD dwDesiredAccess
);

http://msdn2.microsoft.com/en-us/library/ms684330(VS.85).aspx
*/

void StartService_(char argv[])
{
    cout<<"\nDemmarrage du service...";
    SC_HANDLE hService;

    hService = OpenService(hSCManager, argv, SERVICE_START);

    if(hService == NULL)
        printf("\n[-]Impossible d'ouvrir le service.\n--- Erreur avec OpenService : 0x%x", GetLastError());
    else
    {
        printf("\n[+]Service ouvert");

        /*
        BOOL WINAPI StartService(
          __in      SC_HANDLE hService,
          __in      DWORD dwNumServiceArgs,
          __in_opt  LPCTSTR* lpServiceArgVectors
        );

        http://msdn2.microsoft.com/en-us/library/ms686321(VS.85).aspx
        */

        if(StartService(hService, 0, NULL))
            printf("\n[+]Service demarre");
        else
            printf("\n[-]Impossible de demarrer le service %s.\n--- Erreur avec StartService() : 0x%x", argv, GetLastError());
    }

    CloseServiceHandle(hService);

}

void ShutdownService(char argv[])
{
    cout<<"\nInstinction du service...";
    SC_HANDLE hService;
    SERVICE_STATUS ServiceState;

    /*
        typedef struct _SERVICE_STATUS {
          DWORD dwServiceType;
          DWORD dwCurrentState;
          DWORD dwControlsAccepted;
          DWORD dwWin32ExitCode;
          DWORD dwServiceSpecificExitCode;
          DWORD dwCheckPoint;
          DWORD dwWaitHint;
        } SERVICE_STATUS,
         *LPSERVICE_STATUS;
    */


    hService = OpenService(hSCManager, argv, SERVICE_ALL_ACCESS);

    if(hService == NULL)
        printf("\n[-]Impossible d'ouvrir le service.\n--- Erreur avec OpenService : 0x%x", GetLastError());
    else
    {
        printf("\n[+]Service ouvert");

        /*
        BOOL WINAPI ControlService(
          __in   SC_HANDLE hService,
          __in   DWORD dwControl,
          __out  LPSERVICE_STATUS lpServiceStatus
        );
        http://msdn2.microsoft.com/en-us/library/ms682108(VS.85).aspx
        */


        if(ControlService(hService, SERVICE_CONTROL_STOP, &ServiceState)  && GetLastError() != ERROR_SERVICE_NOT_ACTIVE)
            printf("\n[+]Service arrete");
        else
            printf("\n[-]Impossible d'arrete le service %s.\n--- Erreur avec ControlService() : 0x%x", argv, GetLastError());

    }

    CloseServiceHandle(hService);
}

void CreateService_(char argv[])
{
    cout<<"\nCréation du service...";
    char service[200];

    cout<<"\n\nChemin du service : ";
    cin>>service;

    cout<<"\n\nNom du service : ";
    cin>>argv;

    HANDLE hService;

    /*
    SC_HANDLE WINAPI CreateService(
      __in       SC_HANDLE hSCManager,
      __in       LPCTSTR lpServiceName,
      __in_opt   LPCTSTR lpDisplayName,
      __in       DWORD dwDesiredAccess,
      __in       DWORD dwServiceType,
      __in       DWORD dwStartType,
      __in       DWORD dwErrorControl,
      __in_opt   LPCTSTR lpBinaryPathName,
      __in_opt   LPCTSTR lpLoadOrderGroup,
      __out_opt  LPDWORD lpdwTagId,
      __in_opt   LPCTSTR lpDependencies,
      __in_opt   LPCTSTR lpServiceStartName,
      __in_opt   LPCTSTR lpPassword
    );

    http://msdn2.microsoft.com/en-us/library/ms682450(VS.85).aspx
    */

    hService = CreateService(hSCManager, argv, argv, SERVICE_START, SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START, SERVICE_ERROR_IGNORE, service, NULL, NULL, NULL, NULL, NULL);

    if(hService == NULL)
        printf("\n[-]Impossible de creer le service %s.\n--- Erreur avec CreateService : 0x%x", argv, GetLastError());
    else
        printf("\n[+]Service Cree");

    CloseServiceHandle(hService);
}

void RemoveService(char argv[])
{
    cout<<"\nEffacage du service...";

    SC_HANDLE hService;
    SERVICE_STATUS ServiceState;

    hService = OpenService(hSCManager, argv, SERVICE_ALL_ACCESS);

    if(hService == NULL)
        printf("\n[-]Impossible d'ouvrir le service.\n--- Erreur avec OpenService : 0x%x", GetLastError());
    else
    {
        printf("\n[+]Service ouvert");

        ControlService(hService, SERVICE_CONTROL_STOP, &ServiceState);

        if(DeleteService(hService))
            printf("\n[+]Service efface");
        else
            printf("\n[-]Impossible d'effacer le service %s.\n--- Erreur avec DeleteService() : 0x%x", argv, GetLastError());
    }

    CloseServiceHandle(hService);
}

void EnumServices()
{
    cout<<"\nEnumeration des services...";

    /*

     typedef struct _ENUM_SERVICE_STATUS_PROCESS {
          LPTSTR lpServiceName;
          LPTSTR lpDisplayName;
          SERVICE_STATUS_PROCESS ServiceStatusProcess;
    } ENUM_SERVICE_STATUS_PROCESS,
     *LPENUM_SERVICE_STATUS_PROCESS;

     http://msdn2.microsoft.com/en-us/library/ms682648(VS.85).aspx


     typedef struct _SERVICE_STATUS_PROCESS {
          DWORD dwServiceType;
          DWORD dwCurrentState;
          DWORD dwControlsAccepted;
          DWORD dwWin32ExitCode;
          DWORD dwServiceSpecificExitCode;
          DWORD dwCheckPoint;
          DWORD dwWaitHint;
          DWORD dwProcessId;
          DWORD dwServiceFlags;
    } SERVICE_STATUS_PROCESS,
     *LPSERVICE_STATUS_PROCESS;

     http://msdn2.microsoft.com/en-us/library/ms685992(VS.85).aspx
    */


    LPENUM_SERVICE_STATUS_PROCESS lpServiceStatus = NULL;
    DWORD NumberOfServices, BufferSize, BytesNeeded;
    PUCHAR buffer = NULL;

        /*
       BOOL WINAPI EnumServicesStatusEx(
              __in         SC_HANDLE hSCManager,
              __in         SC_ENUM_TYPE InfoLevel,
              __in         DWORD dwServiceType,
              __in         DWORD dwServiceState,
              __out_opt    LPBYTE lpServices,
              __in         DWORD cbBufSize,
              __out        LPDWORD pcbBytesNeeded,
              __out        LPDWORD lpServicesReturned,
              __inout_opt  LPDWORD lpResumeHandle,
              __in_opt     LPCTSTR pszGroupName
        );
        
        http://msdn2.microsoft.com/en-us/library/ms682640(VS.85).aspx
        */
        //On appelle une premiere fois la fonctions pour récupérer le nombre d'octets à allouer
        EnumServicesStatusEx(
                          hSCManager,
                          SC_ENUM_PROCESS_INFO,
                          SERVICE_WIN32,
                          SERVICE_STATE_ALL,
                          NULL,
                          BufferSize,
                          &BytesNeeded,
                          &NumberOfServices,
                          NULL,
                          NULL);


        BufferSize = BytesNeeded + 0x10;
        buffer  = (PUCHAR) malloc(BufferSize);


        EnumServicesStatusEx(
                          hSCManager,
                          SC_ENUM_PROCESS_INFO,
                          SERVICE_WIN32,
                          SERVICE_STATE_ALL,
                          buffer,
                          BufferSize,
                          &BytesNeeded,
                          &NumberOfServices,
                          NULL,
                          NULL);

        lpServiceStatus = (LPENUM_SERVICE_STATUS_PROCESS)buffer;

        for(int i = 0; i <= NumberOfServices; i++)
        {

            printf("\n        -----------| %s |------------", lpServiceStatus[i].lpDisplayName);
            printf("\n\n[+]Nom du service : %s", lpServiceStatus[i].lpServiceName);
            printf("\n[+]Type de service : 0x%x : %s", lpServiceStatus[i].ServiceStatusProcess.dwServiceType, Type[lpServiceStatus[i].ServiceStatusProcess.dwServiceType]);
            printf("\n[+]Status actuel : 0x%x : %s\n\n", lpServiceStatus[i].ServiceStatusProcess.dwCurrentState, State[lpServiceStatus[i].ServiceStatusProcess.dwCurrentState]);

        }

}

