//callbacks static VOID WINAPI _Handler(_In_ DWORD dwOpcode) throw() { switch( dwOpcode ) { case SERVICE_CONTROL_STOP: // stop _set_service_status(SERVICE_STOP_PENDING); ::PostThreadMessage(g_dwThreadID, WM_QUIT, 0, 0); //no check break; case SERVICE_CONTROL_PAUSE: // pause break; case SERVICE_CONTROL_CONTINUE: // continue break; case SERVICE_CONTROL_INTERROGATE: // interrogate break; case SERVICE_CONTROL_SHUTDOWN: // shutdown break; default: // UnknownRequest report_service_log(GKC_SERVICE_NAME, SERVICE_LOG_ERROR, _S("Bad service request")); break; } //end switch }
static VOID WINAPI _ServiceMain( _In_ DWORD dwArgc, _In_ LPWSTR* lpszArgv) throw() { //Register the control request handler g_status.dwCurrentState = SERVICE_START_PENDING; g_dwThreadID = ::GetCurrentThreadId(); g_hServiceStatus = ::RegisterServiceCtrlHandlerW(L"", _Handler); if( g_hServiceStatus == NULL ) { report_service_log(GKC_SERVICE_NAME, SERVICE_LOG_ERROR, _S("Handler not installed")); return ; } _set_service_status(SERVICE_START_PENDING); g_status.dwWin32ExitCode = S_OK; g_status.dwCheckPoint = 0; g_status.dwWaitHint = 0; //command const_array<const_string_s> args; _auto_mem spArgs; //convert try { _cmdline_to_strings(dwArgc, lpszArgv, spArgs, args); //may throw } catch(...) { _set_service_status(SERVICE_STOPPED); report_service_log(GKC_SERVICE_NAME, SERVICE_LOG_ERROR, _S("Out of memory")); return ; } //COM HRESULT hr = ::CoInitializeEx(NULL, COINIT_MULTITHREADED); if( FAILED(hr) ) { _set_service_status(SERVICE_STOPPED); report_service_log(GKC_SERVICE_NAME, SERVICE_LOG_ERROR, _S("Cannot initialize MTA!")); return ; } //loop _os_create_thread_message_queue(); //message queue _set_service_status(SERVICE_RUNNING); report_service_log(GKC_SERVICE_NAME, SERVICE_LOG_SUCCESS, _S("Service started/resumed")); service_main_loop sml; if( !sml.Prepare(args) ) { ::CoUninitialize(); _set_service_status(SERVICE_STOPPED); report_service_log(GKC_SERVICE_NAME, SERVICE_LOG_ERROR, _S("Initialize loop failed!")); return ; } while( true ) { MSG msg; BOOL bRet = ::PeekMessageW(&msg, NULL, 0, 0, PM_NOREMOVE); if( bRet ) { bRet = ::GetMessageW(&msg, NULL, 0, 0); //WM_QUIT if( !bRet ) break; ::TranslateMessage(&msg); //no check ::DispatchMessageW(&msg); //no check } else { if( !sml.OneLoop() ) break; //to be continued thread_sleep(1); } //end if } //end while //final g_status.dwWin32ExitCode = sml.Cleanup(); ::CoUninitialize(); _set_service_status(SERVICE_STOPPED); report_service_log(GKC_SERVICE_NAME, SERVICE_LOG_SUCCESS, _S("Service stopped!")); }
int main(int argc, char *argv[], char *envp[]) { //start //no check ::signal(SIGTTOU, SIG_IGN); ::signal(SIGTTIN, SIG_IGN); ::signal(SIGTSTP, SIG_IGN); ::signal(SIGHUP, SIG_IGN); //fork pid_t pid = ::fork(); if( pid == -1 ) { ::perror("cannot fork!\n"); exit(EXIT_FAILURE); //return -1; } if( pid != 0 ) { exit(EXIT_SUCCESS); //parent process //return 0; } //in child //setsid pid = ::setsid(); if( pid == (pid_t)-1 ) { ::perror("cannot initialize session!\n"); return -1; } ::signal(SIGHUP, SIG_IGN); /* //second //fork pid_t pid2 = ::fork(); if( pid2 == -1 ) { ::perror("cannot fork 2!\n"); exit(EXIT_FAILURE); //return -1; } if( pid2 != 0 ) { exit(EXIT_SUCCESS); //parent process //return 0; } ::signal(SIGHUP, SIG_IGN); */ //cwd if( ::chdir("/") == -1 ) { ::perror("cannot change dir!\n"); return -1; } //close handles const int c_MAXFILE = 65535; for( int i = 0; i < c_MAXFILE; i ++ ) ::close(i); //no check //::open("/dev/null", O_RDONLY); //::open("/dev/null", O_RDWR); //::open("/dev/null", O_RDWR); //mask ::umask(0); //signal ::signal(SIGCHLD, SIG_IGN); //no check /* ::signal(SIGINT, SIG_IGN); //no check ::signal(SIGWINCH, SIG_IGN); //no check */ //command const_array<const_string_s> args; _auto_mem spArgs; //convert try { _cmdline_to_strings(argc, argv, spArgs, args); //may throw } catch(...) { report_service_log(GKC_SERVICE_NAME, SERVICE_LOG_ERROR, _S("Out of memory!")); return -1; } //arrange to catch the signal ::signal(SIGTERM, _sig_term); //no check //global //time time_initialize(); //loop report_service_log(GKC_SERVICE_NAME, SERVICE_LOG_SUCCESS, _S("Start Service!")); service_main_loop sml; if( !sml.Prepare(args) ) { report_service_log(GKC_SERVICE_NAME, SERVICE_LOG_ERROR, _S("Initialize loop failed!")); return -1; } while( !g_ServiceExitFlag ) { if( !sml.OneLoop() ) break; thread_sleep(1); } //end while //final int ret = sml.Cleanup(); report_service_log(GKC_SERVICE_NAME, SERVICE_LOG_SUCCESS, _S("Service Stopped!")); return ret; }