// // サービスメイン処理 // void service_main(void) { PROCESS_INFORMATION pi; service_handle = RegisterServiceCtrlHandler(service_name, (LPHANDLER_FUNCTION)service_control_handler); if(service_handle != 0) { send_status_to_scm(SERVICE_START_PENDING, 0, 1); send_status_to_scm(SERVICE_RUNNING, 0, 0); // プログラムを起動する。 if(execute_process(exe_name, option_name, &pi)) { // 2009/3/26 shutdown_flag = 0; process_id = pi.dwProcessId; send_status_to_scm(SERVICE_RUNNING, 0, 0); // サービスの終了で抜ける while(1) { if(WaitForSingleObject(pi.hProcess, 0) != WAIT_TIMEOUT) { // 2001/11/9 CloseHandle(pi.hThread); CloseHandle(pi.hProcess); // 2009/3/26 if(!retry_flag || shutdown_flag) { break; } else { if(execute_process(exe_name, option_name, &pi)) { process_id = pi.dwProcessId; } else { break; } } } Sleep(100); } } // 2011/9/1 kimukou.buzz //if(end_pattern == END_CTRL_BREAK) { if(end_pattern == END_CTRL_BREAK || end_pattern == END_CTRL_C) { // 2011/9/1 kimukou.buzz FreeConsole(); } CloseHandle(mutex); } send_status_to_scm(SERVICE_STOPPED, 0, 0); }
// // サービス制御要求処理 // in: control .. SERVICE_CONTROL_STOP, SERVICE_CONTROL_SHUTDOWN で終了処理 // void service_control_handler(int control) { switch(control) { case SERVICE_CONTROL_STOP: case SERVICE_CONTROL_SHUTDOWN: // 2009/3/26 shutdown_flag = 1; send_status_to_scm(SERVICE_STOP_PENDING, 0, 1); if(end_pattern == END_CTRL_BREAK) { GenerateConsoleCtrlEvent(CTRL_BREAK_EVENT, process_id); // 2011/9/1 kimukou.buzz }else if(end_pattern == END_CTRL_C) { GenerateConsoleCtrlEvent(CTRL_C_EVENT, process_id); // 2011/9/1 kimukou.buzz } else { EnumWindows(EnumWindowsProc, end_pattern); } send_status_to_scm(SERVICE_STOPPED, 0, 0); break; } }
// handle an error from service_main by cleaning up // and telling SCM that the service didn't start. void terminate(DWORD error) { if(error == 0 && terminate_code_ != 0) { error = terminate_code_; } stop(); csbl::shared_ptr<status> st = context_.find<status>(); csbl::shared_ptr<wait_for_termination_request> tr = context_.find<wait_for_termination_request>(); if(st) st->state(status::stopped); if(tr) tr->proceed(); launch_thread_->join(); // Send a message to the scm to tell about stopage send_status_to_scm(SERVICE_STOPPED, 0, 0, error); // Do not need to close serviceStatusHandle }
// scm service thread void service_main(DWORD dw_argc, LPTSTR* lpsz_argv) { string_type void_string; // like this service is SERVICE_WIN32_OWN_PROCESS, // then the RegisterServiceCtrlHandler // function does not verify if the name is valid, because there is only // one registered service in the process. can be "" (void_string) service_status_handle_ = RegisterServiceCtrlHandler( (char_type*)void_string.c_str(), (LPHANDLER_FUNCTION) service_handler_entry); if (!service_status_handle_) { return; } // notify SCM of progress if (!send_status_to_scm(SERVICE_START_PENDING, 1, 1000)) { send_status_to_scm(SERVICE_STOPPED, 0, 0, GetLastError()); return; } // create the termination event terminate_event_ = CreateEvent (0, TRUE, FALSE, 0); if (!terminate_event_) { send_status_to_scm(SERVICE_STOPPED, 0, 0, GetLastError()); return; } // notify SCM of progress if (!send_status_to_scm(SERVICE_START_PENDING, 2, 5000)) { send_status_to_scm(SERVICE_STOPPED, 0, 0, GetLastError()); return; } // Launch work thread (main) launch_thread_ = new csbl::thread( boost::bind(&server_application_impl_::work_thread, this, dw_argc, lpsz_argv)); HANDLE hevent[2]; hevent[0] = launch_thread_->native_handle(); if(hevent[0] == NULL) { send_status_to_scm(SERVICE_STOPPED, 0, 0, -1); return; } // The service is now running. // Notify SCM of progress if (!send_status_to_scm(SERVICE_RUNNING, 0, 0)) { terminate(GetLastError()); return; } hevent[1] = terminate_event_; // Wait for stop signal, and then terminate WaitForMultipleObjects(2,hevent,FALSE,INFINITE); if (!send_status_to_scm(SERVICE_STOP_PENDING, 1, 5000)) { terminate(GetLastError()); return; } // terminate service, no error! terminate(result_code_); }
// Handle SCM signals void service_handler(DWORD dwOpcode) { csbl::shared_ptr<status> st = context_.find<status>(); switch (dwOpcode) { case SERVICE_CONTROL_STOP: { if(!stop()) // don't accept, returns the service // could not accept control messages return; request_terminate(0); } break; case SERVICE_CONTROL_SHUTDOWN: { stop(); request_terminate(0); } case SERVICE_CONTROL_PAUSE: { if(!pause()) // don't accept, returns the service // could not accept control messages return; if (!send_status_to_scm(SERVICE_PAUSE_PENDING, 1, 1000)) { request_terminate(GetLastError()); return; } if(st) st->state(status::paused); if (!send_status_to_scm(SERVICE_PAUSED, 0, 0)) { request_terminate(GetLastError()); return; } } break; case SERVICE_CONTROL_CONTINUE: { if(!resume()) // don't accept, returns the service // could not accept control messages return; if (!send_status_to_scm(SERVICE_CONTINUE_PENDING, 1, 1000)) { request_terminate(GetLastError()); return; } if(st) st->state(status::running); if (!send_status_to_scm(SERVICE_RUNNING, 0, 0)) { request_terminate(GetLastError()); return; } } break; case SERVICE_CONTROL_INTERROGATE: { // Nothing here! } break; } }