/**
 * @file iPTd_R2.cpp
 *
 */

#include <SDKDDKVer.h>
#include <windows.h>
#include <stdio.h>
#include <tchar.h>

#include <Raym/Log.h>


#define SERVICE_NAME (TEXT("Demo_Service"))


BOOL g_bRun = TRUE;
BOOL g_bService = TRUE;

SERVICE_STATUS_HANDLE g_hServiceStatus = NULL;



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:

          DebugLog0("SERVICE_CONTROL_STOP\n");

          // Set STOP_PENDING status.
          ss.dwCurrentState = SERVICE_STOP_PENDING;
               
          bRet = SetServiceStatus (g_hServiceStatus, &ss);
          
          if (!bRet) {
               DebugLog0 ("SetServiceStatus failed. %u\n", GetLastError());
               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) {
               DebugLog0 ("SetServiceStatus failed. %u\n", GetLastError());
               break;
          }

          break;

     case SERVICE_CONTROL_PAUSE:

          DebugLog0 ("SERVICE_CONTROL_PAUSE\n");

          // Set PAUSE_PENDING status.
          ss.dwCurrentState = SERVICE_PAUSE_PENDING;
                         
          bRet = SetServiceStatus (g_hServiceStatus, &ss);
                    
          if (!bRet) {
               DebugLog0 ("SetServiceStatus failed. %u\n", GetLastError());
               break;
          }

          // APPLICATION SPECIFIC PAUSE_PENDING CODE HERE.
          // ...
          // ...
          
          g_bRun = FALSE;

          // Set PAUSE_PENDING status.
          ss.dwCurrentState = SERVICE_PAUSED;
          ss.dwCheckPoint = 0;
          ss.dwWaitHint = 0;
          ss.dwControlsAccepted |= SERVICE_ACCEPT_PAUSE_CONTINUE;
                                   
          bRet = SetServiceStatus (g_hServiceStatus, &ss);
                              
          if (!bRet) {
               DebugLog0 ("SetServiceStatus failed. %u\n", GetLastError());
               break;
          }
          
          break;
          
     case SERVICE_CONTROL_CONTINUE:

          DebugLog0 ("SERVICE_CONTROL_CONTINUE\n");

          // Set PAUSE_PENDING status.
          ss.dwCurrentState = SERVICE_START_PENDING;
                                   
          bRet = SetServiceStatus (g_hServiceStatus, &ss);
                              
          if (!bRet) {
               DebugLog0 ("SetServiceStatus failed. %u\n", GetLastError());
               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) {
               DebugLog0 ("SetServiceStatus failed. %u\n", GetLastError());
               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) {
          DebugLog0 (
               "RegisterServiceCtrlHandler failed. %u\n", 
               GetLastError());
          return;
     }

     // Entering Starting Service.
     DebugLog0 ("SERVICE_START_PENDING...\n");
     
     ss.dwCurrentState = SERVICE_START_PENDING;
     
     bRet = SetServiceStatus (g_hServiceStatus, &ss);

     if (!bRet) {
          DebugLog0 ("SetServiceStatus failed. %u\n", GetLastError());
          return;
     }

     // APPLICATION SPECIFIC INITIALIZATION CODE
     // ...
     // ...
     
     // Finish Initializing.
     DebugLog0 ("SERVICE_RUNNING.\n");
     
     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) {
          DebugLog0 ("SetServiceStatus failed. %u\n", GetLastError());
          return;
     }

     //
     // Service Main Code.
     //
     
     while(g_bService) {

          if(g_bRun) {
               DebugLog0 ("%s is running.\n", SERVICE_NAME);
          }

          Sleep(2 * 1000);
     }

     DebugLog0 ("END OF ServiceMain\n");
     
}

SERVICE_TABLE_ENTRY ServiceTable[] =
{
    { TEXT("iPTd"), ServiceMain },
    { NULL, NULL }
};



int main(int argc, char *argv[])
{
    BOOL bRet;
    bRet = StartServiceCtrlDispatcher(ServiceTable);
//    assert(bRet);
}

