//添加服务主线程函数和控制函数 void WINAPI wx_service::ServiceMain(DWORD dwArgc, LPTSTR *lpszArgv) { log( "ServiceMain : ServeiceName: %s args: %s ", szServiceName , lpszArgv); //注册服务控制 hServiceStatus = RegisterServiceCtrlHandler( szServiceName, &ServiceHandle); if (hServiceStatus == NULL) { log( "ServiceHandle not installed" ); LogEvent(("ServiceHandle not installed")); return; } log( "ServiceHandle installed & SetServiceStatus SERVICE_START_PENDING " ); status.dwWaitHint = 10; status.dwCurrentState = SERVICE_START_PENDING; status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE | SERVICE_ACCEPT_SHUTDOWN;//这个要使用,否则你不能控制 SetServiceStatus(hServiceStatus, &status); status.dwWin32ExitCode = S_OK; status.dwCheckPoint = 0; status.dwWaitHint = 0; status.dwCurrentState = SERVICE_RUNNING; log( "SetServiceStatus SERVICE_RUNNING" ); SetServiceStatus( hServiceStatus, &status); log( "RUNNING" ); //运行监控 dwThreadID = GetCurrentThreadId() ; Run(); log( "Run() returned" ); status.dwCurrentState = SERVICE_STOPPED; SetServiceStatus(hServiceStatus, &status); LogEvent(("Service stopped")); }
void WINAPI ServiceMain(DWORD dwNumServicesArgs, LPSTR *lpServiceArgVectors) { /* initialise service status */ serviceStatus.dwServiceType = SERVICE_WIN32; serviceStatus.dwCurrentState = SERVICE_STOPPED; serviceStatus.dwControlsAccepted = 0; serviceStatus.dwWin32ExitCode = NO_ERROR; serviceStatus.dwServiceSpecificExitCode = NO_ERROR; serviceStatus.dwCheckPoint = 0; serviceStatus.dwWaitHint = 0; serviceStatusHandle = RegisterServiceCtrlHandler(PACKAGE_NAME, ServiceControlHandler); if(serviceStatusHandle) { /* set the service curent status as starting */ serviceStatus.dwCurrentState = SERVICE_START_PENDING; SetServiceStatus(serviceStatusHandle, &serviceStatus); /* set the service curent status as running and accepting shutdown */ serviceStatus.dwControlsAccepted |= (SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN); serviceStatus.dwCurrentState = SERVICE_RUNNING; SetServiceStatus(serviceStatusHandle, &serviceStatus); /* execute the main code */ if(runServer) runServer(); /* set the service curent status as stopping */ serviceStatus.dwCurrentState = SERVICE_STOP_PENDING; SetServiceStatus(serviceStatusHandle, &serviceStatus); /* set the service curent status as stopped and not accepting shutdown*/ serviceStatus.dwControlsAccepted &= ~(SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN); serviceStatus.dwCurrentState = SERVICE_STOPPED; SetServiceStatus(serviceStatusHandle, &serviceStatus); } }
/** void WINAPI OssecServiceStart (DWORD argc, LPTSTR *argv) * Starts OSSEC service */ void WINAPI OssecServiceStart (DWORD argc, LPTSTR *argv) { ossecServiceStatus.dwServiceType = SERVICE_WIN32; ossecServiceStatus.dwCurrentState = SERVICE_START_PENDING; ossecServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP; ossecServiceStatus.dwWin32ExitCode = 0; ossecServiceStatus.dwServiceSpecificExitCode= 0; ossecServiceStatus.dwCheckPoint = 0; ossecServiceStatus.dwWaitHint = 0; ossecServiceStatusHandle = RegisterServiceCtrlHandler(g_lpszServiceName, OssecServiceCtrlHandler); if (ossecServiceStatusHandle == (SERVICE_STATUS_HANDLE)0) { merror("%s: RegisterServiceCtrlHandler failed.", ARGV0); return; } ossecServiceStatus.dwCurrentState = SERVICE_RUNNING; ossecServiceStatus.dwCheckPoint = 0; ossecServiceStatus.dwWaitHint = 0; if (!SetServiceStatus(ossecServiceStatusHandle, &ossecServiceStatus)) { merror("%s: SetServiceStatus error.", ARGV0); return; } #ifdef OSSECHIDS /* Starting process */ local_start(); #endif }
VOID wisvc_KublServiceStart (DWORD argc, LPTSTR * argv) { DWORD status; DWORD specificError = 0; char *service_name = find_service_name_from (argv); char *cutpnt; /* First chdir to the same directory where the executable is (got from argv[0] of original main arguments), so that further error messages printed with wisvc_err_printf (which calls log_error in turn) will be appended to wi.err file in more appropriate place than \WINNT\SYSTEM32 directory. */ if (wisvc_Main_G_argv && wisvc_Main_G_argv[0] && (NULL != (cutpnt = strrchr (wisvc_Main_G_argv[0], '\\')))) { /* Search the last backslash. */ ptrlong len; char *work_dir; len = (cutpnt - wisvc_Main_G_argv[0]); if (NULL == (work_dir = ((char *) malloc (len + 1)))) { exit (7); /* Failed beyond all reason, best to exit. */ } else { strncpy (work_dir, wisvc_Main_G_argv[0], len); /* Leave backslash there */ work_dir[len] = '\0'; } if (chdir (work_dir)) /* Is not zero, i.e. -1, an error. */ { /* However, we do not exit yet. */ /* DWORD erhe = GetLastError(); */ wisvc_err_printf ("%s: Cannot chdir to \"%s\" because: %s", argv[0], work_dir, strerror (errno)); } free (work_dir); } wisvc_KublServiceStatus.dwServiceType = SERVICE_WIN32; wisvc_KublServiceStatus.dwCurrentState = SERVICE_START_PENDING; wisvc_KublServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP; /* | SERVICE_ACCEPT_PAUSE_CONTINUE; (Not for wisvc_Kubl) */ wisvc_KublServiceStatus.dwWin32ExitCode = 0; wisvc_KublServiceStatus.dwServiceSpecificExitCode = 0; wisvc_KublServiceStatus.dwCheckPoint = 0; wisvc_KublServiceStatus.dwWaitHint = 2; wisvc_KublServiceStatusHandle = RegisterServiceCtrlHandler (TEXT (service_name), ((LPHANDLER_FUNCTION) wisvc_KublServiceCtrlHandler)); if (wisvc_KublServiceStatusHandle == (SERVICE_STATUS_HANDLE) 0) { wisvc_err_printf ("%s: (%s) RegisterServiceCtrlHandler failed %ld\n", wisvc_Main_G_argv[0], service_name, GetLastError ()); return; } /* Now we are calling kubl_main second time. */ status = kubl_main (argc, argv, 1, &specificError); if (status != NO_ERROR) /* Handle error condition */ { wisvc_KublServiceStatus.dwCurrentState = SERVICE_STOPPED; wisvc_KublServiceStatus.dwCheckPoint = 0; wisvc_KublServiceStatus.dwWaitHint = 0; wisvc_KublServiceStatus.dwWin32ExitCode = status; wisvc_KublServiceStatus.dwServiceSpecificExitCode = specificError; SetServiceStatus (wisvc_KublServiceStatusHandle, &wisvc_KublServiceStatus); return; } wisvc_send_service_running_status (); /* This is where the service either does few checkpoints now and then or does nothing: */ main_the_rest (); /* In chil.c */ return; }
int WIN32_Subsystem_Init(int *argc, char ***argv) { WIN32_OS_version = GetOSVersion(); if ((WIN32_OS_version == _WIN_OS_UNKNOWN) || (WIN32_OS_version == _WIN_OS_WIN32S)) return 1; if (atexit(WIN32_Exit) != 0) return 1; #if USE_WIN32_SERVICE if (WIN32_run_mode == _WIN_SQUID_RUN_MODE_SERVICE) { char path[512]; HKEY hndKey; if (signal(SIGABRT, WIN32_Abort) == SIG_ERR) return 1; /* Register the service Handler function */ svcHandle = RegisterServiceCtrlHandler(WIN32_Service_name, WIN32_svcHandler); if (svcHandle == 0) return 1; /* Set Process work dir to directory cointaining squid.exe */ GetModuleFileName(NULL, path, 512); WIN32_module_name = xstrdup(path); path[strlen(path) - 10] = '\0'; if (SetCurrentDirectory(path) == 0) return 1; safe_free(ConfigFile); /* get config file from Windows Registry */ if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, REGKEY, 0, KEY_QUERY_VALUE, &hndKey) == ERROR_SUCCESS) { DWORD Type = 0; DWORD Size = 0; LONG Result; Result = RegQueryValueEx(hndKey, CONFIGFILE, NULL, &Type, NULL, &Size); if (Result == ERROR_SUCCESS && Size) { ConfigFile = xmalloc(Size); RegQueryValueEx(hndKey, CONFIGFILE, NULL, &Type, ConfigFile, &Size); } else ConfigFile = xstrdup(DefaultConfigFile); Size = 0; Type = 0; Result = RegQueryValueEx(hndKey, COMMANDLINE, NULL, &Type, NULL, &Size); if (Result == ERROR_SUCCESS && Size) { WIN32_Service_Command_Line = xmalloc(Size); RegQueryValueEx(hndKey, COMMANDLINE, NULL, &Type, WIN32_Service_Command_Line, &Size); } else WIN32_Service_Command_Line = xstrdup(""); RegCloseKey(hndKey); } else { ConfigFile = xstrdup(DefaultConfigFile); WIN32_Service_Command_Line = xstrdup(""); } WIN32_build_argv(WIN32_Service_Command_Line); *argc = WIN32_argc; *argv = WIN32_argv; /* Set Service Status to SERVICE_START_PENDING */ svcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; svcStatus.dwCurrentState = SERVICE_START_PENDING; svcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN; svcStatus.dwWin32ExitCode = 0; svcStatus.dwServiceSpecificExitCode = 0; svcStatus.dwCheckPoint = 0; svcStatus.dwWaitHint = 10000; SetServiceStatus(svcHandle, &svcStatus); #ifdef _SQUID_MSWIN_ _setmaxstdio(Squid_MaxFD); #endif } #endif #ifdef _SQUID_MSWIN_ if (Win32SockInit() < 0) return 1; #endif return 0; }
static void WINAPI service_(DWORD argc, char** argv) { /* Arguments are unused: these are specified as the "start parameters" in the Service Control Manager. */ /* Service thread. */ const char* sname; aug_bool daemon = AUG_TRUE; char home[AUG_PATH_MAX + 1]; /* DebugBreak(); */ /* Ensure writes performed on main thread are visible. */ aug_rmb(); if (!aug_inittlx()) { fprintf(stderr, "aug_inittlx() failed\n"); return; } if (!(sname = aug_getservopt(AUG_OPTSHORTNAME))) { aug_setctxerror(aug_tlx, __FILE__, __LINE__, "aug", AUG_EINVAL, AUG_MSG("option 'AUG_OPTSHORTNAME' not set")); aug_perrinfo(aug_tlx, "getservopt() failed", NULL); goto done; } /* Start console if interactive. The console is opened before aug_readservconf() is called to prevent any log files from begin opened. */ if (createconsole_(sname)) daemon = AUG_FALSE; /* Install daemon logger prior to opening log file. */ aug_setdaemonlog(aug_tlx); /* Fallback to tmp. */ if (!aug_gethome(home, sizeof(home)) && !aug_gettmp(home, sizeof(home))) { aug_ctxerror(aug_tlx, "failed to determine home directory"); goto done; } /* Move away from system32. */ if (!SetCurrentDirectory(home)) { aug_setwin32error(aug_tlx, __FILE__, __LINE__, GetLastError()); aug_perrinfo(aug_tlx, "SetCurrentDirectory() failed", NULL); goto done; } if (AUG_CMDDEFAULT != options_.command_) { /* Commands other than AUG_CMDDEFAULT are invalid in this context. */ aug_setctxerror(aug_tlx, __FILE__, __LINE__, "aug", AUG_EINVAL, AUG_MSG("unexpected command value")); aug_perrinfo(aug_tlx, "invalid options", NULL); goto done; } if (aug_readservconf(AUG_CONFFILE(&options_), AUG_FALSE, daemon) < 0) { aug_perrinfo(aug_tlx, "aug_readservconf() failed", NULL); goto done; } if (!(ssh_ = RegisterServiceCtrlHandler(sname, handler_))) { aug_setwin32error(aug_tlx, __FILE__, __LINE__, GetLastError()); aug_perrinfo(aug_tlx, "RegisterServiceCtrlHandler() failed", NULL); goto done; } setstatus_(SERVICE_START_PENDING); if (aug_initserv_BIN() < 0) { aug_perrinfo(aug_tlx, "aug_initserv_BIN() failed", NULL); setstatus_(SERVICE_STOPPED); goto done; } aug_ctxnotice(aug_tlx, "daemon started"); setstatus_(SERVICE_RUNNING); if (aug_runserv() < 0) aug_perrinfo(aug_tlx, "aug_runserv() failed", NULL); aug_ctxnotice(aug_tlx, "daemon stopped"); setstatus_(SERVICE_STOPPED); /* This function will be called on the Service Manager's thread. Given that aug_initserv_BIN() and aug_runserv() have been called on this thread, aug_termserv() is also called from this thread and not the main thread. */ aug_termserv(); done: /* Flush pending writes to main memory. */ aug_wmb(); aug_term(); if (!daemon) FreeConsole(); }
VOID WINAPI service_main(DWORD dwArgc, LPTSTR *lpszArgv) { HKEY hkey = NULL; char *config = NULL; DWORD type, config_size, status; // register our service control handler: // sshStatusHandle = RegisterServiceCtrlHandler("tdifw", service_ctrl); if (sshStatusHandle == 0) { winerr("install_service: RegisterServiceCtrlHandler"); goto cleanup; } // SERVICE_STATUS members that don't change in example // ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; ssStatus.dwServiceSpecificExitCode = 0; // report the status to the service control manager. // if (!ReportStatusToSCMgr( SERVICE_START_PENDING, // service state NO_ERROR, // exit code 3000)) // wait hint goto cleanup; /* get config name from registry */ if ((status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, CONFIG_SUBKEY, 0, KEY_QUERY_VALUE, &hkey)) != ERROR_SUCCESS) { SetLastError(status); winerr("RegOpenKeyEx"); goto cleanup; } if ((status = RegQueryValueEx(hkey, "config", 0, &type, NULL, &config_size)) != ERROR_SUCCESS) { SetLastError(status); winerr("RegOpenKeyEx"); goto cleanup; } if (type != REG_SZ) { error("Invalid type for config value in registry"); SetLastError(ERROR_INVALID_DATA); goto cleanup; } config = (char *)malloc(config_size); if (config == NULL) { liberr("malloc"); goto cleanup; } if ((status = RegQueryValueEx(hkey, "config", 0, NULL, config, &config_size)) != ERROR_SUCCESS) { SetLastError(status); winerr("RegOpenKeyEx"); goto cleanup; } if (start(config)) { // start success // report the status to the service control manager. // if (!ReportStatusToSCMgr( SERVICE_RUNNING, // service state NO_ERROR, // exit code 0)) // wait hint goto cleanup; wait(); SetLastError(0); } cleanup: // try to report the stopped status to the service control manager. // if (sshStatusHandle != 0) ReportStatusToSCMgr(SERVICE_STOPPED, GetLastError(), 0); if (hkey != NULL) RegCloseKey(hkey); free(config); }
VOID WINAPI MyServiceMain(DWORD dwArgc, LPTSTR *lpszArgv) { WSADATA w; char text[256]; int pid; //HANDLE event_han; // int fd; // char text[256]; // fd = g_file_open("c:\\temp\\xrdp\\log.txt"); // g_file_write(fd, "hi\r\n", 4); //event_han = RegisterEventSource(0, "xrdp"); //log_event(event_han, "hi xrdp log"); g_threadid = tc_get_threadid(); g_set_current_dir("c:\\temp\\xrdp"); g_listen = 0; WSAStartup(2, &w); g_sync_mutex = tc_mutex_create(); g_sync1_mutex = tc_mutex_create(); pid = g_getpid(); g_snprintf(text, 255, "xrdp_%8.8x_main_term", pid); g_term_event = g_create_wait_obj(text); g_snprintf(text, 255, "xrdp_%8.8x_main_sync", pid); g_sync_event = g_create_wait_obj(text); g_memset(&g_service_status, 0, sizeof(SERVICE_STATUS)); g_service_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS; g_service_status.dwCurrentState = SERVICE_RUNNING; g_service_status.dwControlsAccepted = SERVICE_CONTROL_INTERROGATE | SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN; g_service_status.dwWin32ExitCode = NO_ERROR; g_service_status.dwServiceSpecificExitCode = 0; g_service_status.dwCheckPoint = 0; g_service_status.dwWaitHint = 0; // g_sprintf(text, "calling RegisterServiceCtrlHandler\r\n"); // g_file_write(fd, text, g_strlen(text)); g_ssh = RegisterServiceCtrlHandler("xrdp", MyHandler); if (g_ssh != 0) { // g_sprintf(text, "ok\r\n"); // g_file_write(fd, text, g_strlen(text)); SetServiceStatus(g_ssh, &g_service_status); g_listen = xrdp_listen_create(); xrdp_listen_main_loop(g_listen); g_sleep(100); g_service_status.dwCurrentState = SERVICE_STOPPED; SetServiceStatus(g_ssh, &g_service_status); } else { //g_sprintf(text, "RegisterServiceCtrlHandler failed\r\n"); //g_file_write(fd, text, g_strlen(text)); } xrdp_listen_delete(g_listen); tc_mutex_delete(g_sync_mutex); tc_mutex_delete(g_sync1_mutex); g_destroy_wait_obj(g_term_event); g_destroy_wait_obj(g_sync_event); WSACleanup(); //CloseHandle(event_han); }
VOID WINAPI ServiceMain(DWORD argc, LPTSTR *argv) { DWORD Status = E_FAIL; // Register our service control handler with the SCM g_StatusHandle = RegisterServiceCtrlHandler(SERVICE_NAME, ServiceCtrlHandler); if (g_StatusHandle == NULL) { goto EXIT; } // Tell the service controller we are starting ZeroMemory(&g_ServiceStatus, sizeof(g_ServiceStatus)); g_ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; g_ServiceStatus.dwControlsAccepted = 0; g_ServiceStatus.dwCurrentState = SERVICE_START_PENDING; g_ServiceStatus.dwWin32ExitCode = 0; g_ServiceStatus.dwServiceSpecificExitCode = 0; g_ServiceStatus.dwCheckPoint = 0; if (SetServiceStatus(g_StatusHandle, &g_ServiceStatus) == FALSE) { OutputDebugString(_T( "My Sample Service: ServiceMain: SetServiceStatus returned error")); } /* * Perform tasks necessary to start the service here */ startup_sockets_mechanism(); // Create a service stop event to wait on later g_ServiceStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); if (g_ServiceStopEvent == NULL) { // Error creating event // Tell service controller we are stopped and exit g_ServiceStatus.dwControlsAccepted = 0; g_ServiceStatus.dwCurrentState = SERVICE_STOPPED; g_ServiceStatus.dwWin32ExitCode = GetLastError(); g_ServiceStatus.dwCheckPoint = 1; if (SetServiceStatus(g_StatusHandle, &g_ServiceStatus) == FALSE) { OutputDebugString(_T( "My Sample Service: ServiceMain: SetServiceStatus returned error")); } goto EXIT; } // Tell the service controller we are started g_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP; g_ServiceStatus.dwCurrentState = SERVICE_RUNNING; g_ServiceStatus.dwWin32ExitCode = 0; g_ServiceStatus.dwCheckPoint = 0; if (SetServiceStatus(g_StatusHandle, &g_ServiceStatus) == FALSE) { OutputDebugString(_T( "My Sample Service: ServiceMain: SetServiceStatus returned error")); } // Start a thread that will perform the main task of the service HANDLE hThread = CreateThread(NULL, 0, ServiceWorkerThread, NULL, 0, NULL); // Wait until our worker thread exits signaling that the service needs to stop WaitForSingleObject(hThread, INFINITE); /* * Perform any cleanup tasks */ cleanup_sockets_mechanism(); CloseHandle(g_ServiceStopEvent); // Tell the service controller we are stopped g_ServiceStatus.dwControlsAccepted = 0; g_ServiceStatus.dwCurrentState = SERVICE_STOPPED; g_ServiceStatus.dwWin32ExitCode = 0; g_ServiceStatus.dwCheckPoint = 3; if (SetServiceStatus(g_StatusHandle, &g_ServiceStatus) == FALSE) { OutputDebugString(_T( "My Sample Service: ServiceMain: SetServiceStatus returned error")); } EXIT: return; }
void WINAPI CNTL_main_thread( DWORD /*argc*/, char* /*argv*/[]) { /************************************** * * C N T L _ m a i n _ t h r e a d * ************************************** * * Functional description * **************************************/ service_handle = RegisterServiceCtrlHandler(service_name->c_str(), control_thread); if (!service_handle) return; // start everything, and wait here for ever, or at // least until we get the stop event indicating that // the service is stoping. bool failure = true; DWORD temp = 0; if (report_status(SERVICE_START_PENDING, NO_ERROR, 1, 3000) && (stop_event_handle = CreateEvent(NULL, TRUE, FALSE, NULL)) != NULL && report_status(SERVICE_START_PENDING, NO_ERROR, 2, 3000)) { try { Thread::start(main_handler, NULL, THREAD_medium); if (report_status(SERVICE_RUNNING, NO_ERROR, 0, 0)) { failure = false; temp = WaitForSingleObject(stop_event_handle, INFINITE); } } catch (const Firebird::Exception& ex) { iscLogException("CNTL: cannot start service handler thread", ex); } } DWORD last_error = 0; if (failure || temp == WAIT_FAILED) last_error = GetLastError(); if (stop_event_handle) CloseHandle(stop_event_handle); // Once we are stopped, we will tell the server to // do the same. We could not do this in the control_thread // since the Services Control Manager is single threaded, // and thus can only process one request at the time. SERVICE_STATUS status_info; SC_HANDLE hScManager = 0, hService = 0; hScManager = OpenSCManager(NULL, NULL, GENERIC_READ); hService = OpenService(hScManager, remote_name->c_str(), GENERIC_READ | GENERIC_EXECUTE); ControlService(hService, SERVICE_CONTROL_STOP, &status_info); CloseServiceHandle(hScManager); CloseServiceHandle(hService); report_status(SERVICE_STOPPED, last_error, 0, 0); }
void CALLBACK ServiceMain(DWORD dwArgc, LPTSTR *lpszArgv) { TCHAR szTmp[8192]; char szTmpA[8192]; TCHAR szTmp2[8192]; char szAuthServer[32]; DWORD dwTmp,dwType; HKEY hk; int seq=1,err; LPCSTR szNode; addrinfo *pAddrInfo; if(dwArgc!=999) { if (!(g_hService = RegisterServiceCtrlHandler(SERVICE_NAME,ServiceHandler))) { ReportError(TRUE,"Unable to start "SERVICE_NAMEA" - RegisterServiceCtrlHandler failed"); return; } NotifySCM(SERVICE_START_PENDING, 0, seq++); } else { g_bTestMode=TRUE; printf(SERVICE_NAMEA" " CVSNT_PRODUCTVERSION_STRING " ("__DATE__") starting in test mode.\n"); } if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,_T("SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment"),NULL,KEY_QUERY_VALUE,&hk)) { ReportError(TRUE,"Unable to start "SERVICE_NAMEA" - Couldn't open environment key"); if(!g_bTestMode) NotifySCM(SERVICE_STOPPED,0,0); return; } dwTmp=sizeof(szTmp); if(RegQueryValueEx(hk,_T("PATH"),NULL,&dwType,(BYTE*)szTmp,&dwTmp)) { ReportError(TRUE,"Unable to start "SERVICE_NAMEA" - PATH environment variable not defined in system environment"); if(!g_bTestMode) NotifySCM(SERVICE_STOPPED,0,0); return; } ExpandEnvironmentStrings(szTmp,szTmp2,sizeof(szTmp)); SetEnvironmentVariable(_T("PATH"),szTmp2); RegCloseKey(hk); if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,_T("Software\\CVS\\Pserver"),NULL,KEY_QUERY_VALUE,&hk)) { ReportError(TRUE,"Unable to start "SERVICE_NAMEA" - Couldn't open HKLM\\Software\\CVS\\Pserver key"); if(!g_bTestMode) NotifySCM(SERVICE_STOPPED,0,0); return; } dwTmp=sizeof(szTmp); if(RegQueryValueEx(hk,_T("TempDir"),NULL,&dwType,(LPBYTE)szTmp,&dwTmp) && SHRegGetUSValue(_T("SYSTEM\\CurrentControlSet\\Control\\Session Manager\\Environment"),_T("TEMP"),NULL,(LPVOID)szTmp,&dwTmp,TRUE,NULL,0) && !GetEnvironmentVariable(_T("TEMP"),(LPTSTR)szTmp,sizeof(szTmp)) && !GetEnvironmentVariable(_T("TMP"),(LPTSTR)szTmp,sizeof(szTmp))) { _tcscpy(szTmp,_T("C:\\")); } SetEnvironmentVariable(_T("TEMP"),szTmp); SetEnvironmentVariable(_T("TMP"),szTmp); if(g_bTestMode) _tprintf(_T("TEMP/TMP currently set to %s\n"),szTmp); dwTmp=sizeof(DWORD); if(!RegQueryValueEx(hk,_T("PServerPort"),NULL,&dwType,(BYTE*)szTmp,&dwTmp)) { authserver_port=*(DWORD*)szTmp; } itoa(authserver_port,szAuthServer,10); // Initialisation WSADATA data; if(WSAStartup (MAKEWORD (1, 1), &data)) { ReportError(TRUE,"WSAStartup failed... aborting - Error %d\n",WSAGetLastError()); if(!g_bTestMode) NotifySCM(SERVICE_STOPPED,0,0); return; } dwTmp=sizeof(szTmpA); szNode = NULL; if(!RegQueryValueExA(hk,"BindAddress",NULL,&dwType,(BYTE*)szTmpA,&dwTmp)) { if(stricmp(szTmpA,"*")) szNode = szTmpA; } addrinfo hint = {0}; hint.ai_family=PF_UNSPEC; hint.ai_socktype=SOCK_STREAM; hint.ai_protocol=IPPROTO_TCP; hint.ai_flags=AI_PASSIVE; pAddrInfo=NULL; if(g_bTestMode) { printf("Initialising socket..."); } err=getaddrinfo(szNode,szAuthServer,&hint,&pAddrInfo); if(g_bTestMode) { if(err) printf("failed (%s)\n",gai_strerror(err)); else { if(!pAddrInfo) { printf("This server doesn't know how to bind tcp sockets!!! Your sockets layer is broken!!!\n"); } else printf("ok\n"); } } if(err) ReportError(FALSE,"Failed to get ipv4 socket details: %s",gai_strerror(err)); RegCloseKey(hk); if(!g_bTestMode) NotifySCM(SERVICE_START_PENDING, 0, seq++); int impersonate=1; if(!RegOpenKeyEx(HKEY_LOCAL_MACHINE,_T("Software\\CVS\\Pserver"),0,KEY_QUERY_VALUE,&hk)) { DWORD dwType,dwImpersonate; DWORD dwTmp=sizeof(dwTmp); if(!RegQueryValueEx(hk,_T("Impersonation"),NULL,&dwType,(BYTE*)&dwImpersonate,&dwTmp)) impersonate = dwImpersonate; RegCloseKey(hk); hk = 0; } if(impersonate) printf("Impersonation is enabled\n"); else printf("*WARNING* Impersonation is disabled - all file access will be done as System user\n"); if(g_bTestMode) printf("Starting auth server on port %d/tcp...\n",authserver_port); addrinfo* ai; for(ai=pAddrInfo;ai;ai=ai->ai_next) { SOCKET s = WSASocket(ai->ai_family,ai->ai_socktype,ai->ai_protocol,NULL,0,0); if(s!=-1 && !bind(s,ai->ai_addr,ai->ai_addrlen)) { if(listen(s,50)==SOCKET_ERROR) { ReportError(TRUE,"Listen on socket failed: %s\n",gai_strerror(WSAGetLastError())); if(!g_bTestMode) NotifySCM(SERVICE_STOPPED,0,0); freeaddrinfo(pAddrInfo); return; } g_Sockets.push_back(s); } else { if(g_bTestMode) printf("Socket Failed (Handle=%08x Family=%d,Socktype=%d,Protocol=%d): %s (not fatal)\n",s,ai->ai_family,ai->ai_socktype,ai->ai_protocol, gai_strerror(WSAGetLastError())); closesocket(s); } } freeaddrinfo(pAddrInfo); if(!g_Sockets.size()) { ReportError(TRUE,"All socket binds failed."); if(!g_bTestMode) NotifySCM(SERVICE_STOPPED,0,0); return; } DWORD (WINAPI *pDsServerRegisterSpn)(DS_SPN_WRITE_OP Operation, LPCTSTR ServiceClass, LPCTSTR UserObjectDN); UINT oldMode=SetErrorMode(SEM_NOOPENFILEERRORBOX|SEM_FAILCRITICALERRORS); pDsServerRegisterSpn = (DWORD (WINAPI*)(DS_SPN_WRITE_OP,LPCTSTR,LPCTSTR))GetProcAddress(LoadLibrary("ntdsapi.dll"),"DsServerRegisterSpnA"); SetErrorMode(oldMode); if(pDsServerRegisterSpn) { if(g_bTestMode) printf("Registering service SPN... "); pDsServerRegisterSpn(DS_SPN_DELETE_SPN_OP,"cvs",NULL); if(!g_bTestMode) NotifySCM(SERVICE_START_PENDING, 0, seq++); pDsServerRegisterSpn(DS_SPN_DELETE_SPN_OP,"cvs",NULL); if(!g_bTestMode) NotifySCM(SERVICE_START_PENDING, 0, seq++); if((dwTmp=pDsServerRegisterSpn(DS_SPN_ADD_SPN_OP,"cvs",NULL))!=0) { if(g_bTestMode) printf("failed (Error %d)\n",dwTmp); //ReportError(TRUE,"Registering cvs service SPN failed (error %d)", dwTmp); } else { if(g_bTestMode) printf("ok\n"); } } // Process running, wait for closedown ReportError(FALSE,SERVICE_NAMEA" initialised successfully"); if(!g_bTestMode) NotifySCM(SERVICE_RUNNING, 0, 0); g_bStop=FALSE; do { fd_set rfd; sockaddr_storage sin; size_t n; FD_ZERO(&rfd); for(n=0; n<g_Sockets.size(); n++) FD_SET(g_Sockets[n],&rfd); TIMEVAL tv = { 5, 0 }; // 5 seconds max wait int sel=select(1,&rfd,NULL,NULL,&tv); if(g_bStop || sel==SOCKET_ERROR) break; // Error on socket, or stopped for(n=0; n<g_Sockets.size(); n++) { if(FD_ISSET(g_Sockets[n],&rfd)) { HANDLE hConn=(HANDLE)accept(g_Sockets[n],(struct sockaddr*)&sin,NULL); CloseHandle(CreateThread(NULL,0,DoCvsThread,(void*)hConn,0,NULL)); } } } while(!g_bStop); if(pDsServerRegisterSpn) { if(g_bTestMode) printf("Unregistering service SPN...\n"); pDsServerRegisterSpn(DS_SPN_DELETE_SPN_OP,"cvs",NULL); } NotifySCM(SERVICE_STOPPED, 0, 0); ReportError(FALSE,SERVICE_NAMEA" stopped successfully"); }
VOID WINAPI ServiceMain (DWORD argc, LPTSTR *argv) { DWORD Status = E_FAIL; addLog("Print Service: ServiceMain: Entry"); g_StatusHandle = RegisterServiceCtrlHandler (SERVICE_NAME, ServiceCtrlHandler); if (g_StatusHandle == NULL) { addLog("Print Service: ServiceMain: RegisterServiceCtrlHandler returned error"); return; } ZeroMemory (&g_ServiceStatus, sizeof (g_ServiceStatus)); g_ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; g_ServiceStatus.dwControlsAccepted = 0; g_ServiceStatus.dwCurrentState = SERVICE_START_PENDING; g_ServiceStatus.dwWin32ExitCode = 0; g_ServiceStatus.dwServiceSpecificExitCode = 0; g_ServiceStatus.dwCheckPoint = 0; if (SetServiceStatus (g_StatusHandle, &g_ServiceStatus) == FALSE) { addLog("Print Service: ServiceMain: SetServiceStatus returned error"); } addLog("Print Service: ServiceMain: Performing Service Start Operations"); g_ServiceStopEvent = CreateEvent (NULL, TRUE, FALSE, NULL); if (g_ServiceStopEvent == NULL) { addLog("Print Service: ServiceMain: CreateEvent(g_ServiceStopEvent) returned error"); g_ServiceStatus.dwControlsAccepted = 0; g_ServiceStatus.dwCurrentState = SERVICE_STOPPED; g_ServiceStatus.dwWin32ExitCode = GetLastError(); g_ServiceStatus.dwCheckPoint = 1; if (SetServiceStatus (g_StatusHandle, &g_ServiceStatus) == FALSE) { addLog("Print Service: ServiceMain: SetServiceStatus returned error"); } return; } g_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP; g_ServiceStatus.dwCurrentState = SERVICE_RUNNING; g_ServiceStatus.dwWin32ExitCode = 0; g_ServiceStatus.dwCheckPoint = 0; if (SetServiceStatus (g_StatusHandle, &g_ServiceStatus) == FALSE) { addLog("Print Service: ServiceMain: SetServiceStatus returned error"); } HANDLE hThread = CreateThread (NULL, 0, ServiceWorkerThread, NULL, 0, NULL); addLog("Print Service: ServiceMain: Waiting for Worker Thread to complete"); WaitForSingleObject (hThread, INFINITE); addLog("Print Service: ServiceMain: Worker Thread Stop Event signaled"); addLog("Print Service: ServiceMain: Performing Cleanup Operations"); CloseHandle (g_ServiceStopEvent); g_ServiceStatus.dwControlsAccepted = 0; g_ServiceStatus.dwCurrentState = SERVICE_STOPPED; g_ServiceStatus.dwWin32ExitCode = 0; g_ServiceStatus.dwCheckPoint = 3; if (SetServiceStatus (g_StatusHandle, &g_ServiceStatus) == FALSE) { addLog("Print Service: ServiceMain: SetServiceStatus returned error"); } addLog("Print Service: ServiceMain: Exit"); return; }
VOID WINAPI ServiceMain(DWORD argc, LPTSTR *argv) { DWORD Status = E_FAIL; OutputDebugString(_T("GDaemon: ServiceMain: Entry")); g_StatusHandle = RegisterServiceCtrlHandler(SERVICE_NAME, ServiceCtrlHandler); if (g_StatusHandle == NULL) { OutputDebugString(_T("GDaemon: ServiceMain: RegisterServiceCtrlHandler returned error")); return; } // Tell the service controller we are starting ZeroMemory(&g_ServiceStatus, sizeof (g_ServiceStatus)); g_ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; g_ServiceStatus.dwControlsAccepted = 0; g_ServiceStatus.dwCurrentState = SERVICE_START_PENDING; g_ServiceStatus.dwWin32ExitCode = 0; g_ServiceStatus.dwServiceSpecificExitCode = 0; g_ServiceStatus.dwCheckPoint = 0; if (SetServiceStatus(g_StatusHandle, &g_ServiceStatus) == FALSE) { OutputDebugString(_T("GDaemon: ServiceMain: SetServiceStatus returned error")); } /* * Perform tasks neccesary to start the service here */ OutputDebugString(_T("GDaemon: ServiceMain: Performing Service Start Operations")); // Create stop event to wait on later. g_ServiceStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); if (g_ServiceStopEvent == NULL) { OutputDebugString(_T("GDaemon: ServiceMain: CreateEvent(g_ServiceStopEvent) returned error")); g_ServiceStatus.dwControlsAccepted = 0; g_ServiceStatus.dwCurrentState = SERVICE_STOPPED; g_ServiceStatus.dwWin32ExitCode = GetLastError(); g_ServiceStatus.dwCheckPoint = 1; if (SetServiceStatus(g_StatusHandle, &g_ServiceStatus) == FALSE) { OutputDebugString(_T("GDaemon: ServiceMain: SetServiceStatus returned error")); } return; } // Tell the service controller we are started g_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP; g_ServiceStatus.dwCurrentState = SERVICE_RUNNING; g_ServiceStatus.dwWin32ExitCode = 0; g_ServiceStatus.dwCheckPoint = 0; if (SetServiceStatus(g_StatusHandle, &g_ServiceStatus) == FALSE) { OutputDebugString(_T("GDaemon: ServiceMain: SetServiceStatus returned error")); } // Start the thread that will perform the main task of the service HANDLE hThread = CreateThread(NULL, 0, ServiceWorkerThread, NULL, 0, NULL); OutputDebugString(_T("GDaemon: ServiceMain: Waiting for Worker Thread to complete")); // Wait until our worker thread exits effectively signaling that the service needs to stop WaitForSingleObject(hThread, INFINITE); OutputDebugString(_T("GDaemon: ServiceMain: Worker Thread Stop Event signaled")); /* * Perform any cleanup tasks */ OutputDebugString(_T("GDaemon: ServiceMain: Performing Cleanup Operations")); CloseHandle(g_ServiceStopEvent); g_ServiceStatus.dwControlsAccepted = 0; g_ServiceStatus.dwCurrentState = SERVICE_STOPPED; g_ServiceStatus.dwWin32ExitCode = 0; g_ServiceStatus.dwCheckPoint = 3; if (SetServiceStatus(g_StatusHandle, &g_ServiceStatus) == FALSE) { OutputDebugString(_T("GDaemon: SetServiceStatus returned error")); } return; }
void __stdcall service_main_fn(DWORD argc, LPTSTR *argv) { HANDLE hCurrentProcess; HANDLE hPipeRead = NULL; HANDLE hPipeReadDup; HANDLE hNullFile; DWORD threadid; SECURITY_ATTRIBUTES sa = {0}; char **newargv; if(!(globdat.hServiceStatus = RegisterServiceCtrlHandler(argv[0], service_ctrl))) { ap_log_error(APLOG_MARK, APLOG_ERR|APLOG_WIN32ERROR, NULL, "Failure registering service handler"); return; } ReportStatusToSCMgr( SERVICE_START_PENDING, // service state NO_ERROR, // exit code 3000); // wait hint /* Create a pipe to send stderr messages to the system error log */ hCurrentProcess = GetCurrentProcess(); if (CreatePipe(&hPipeRead, &eventlog_pipewrite, &sa, 0)) { if (DuplicateHandle(hCurrentProcess, hPipeRead, hCurrentProcess, &hPipeReadDup, 0, FALSE, DUPLICATE_SAME_ACCESS)) { CloseHandle(hPipeRead); hPipeRead = hPipeReadDup; eventlog_thread = CreateThread(NULL, 0, service_stderr_thread, (LPVOID) hPipeRead, 0, &threadid); if (eventlog_thread) { int fh; FILE *fl; fflush(stderr); SetStdHandle(STD_ERROR_HANDLE, eventlog_pipewrite); fh = _open_osfhandle((long) STD_ERROR_HANDLE, _O_WRONLY | _O_BINARY); dup2(fh, STDERR_FILENO); fl = _fdopen(STDERR_FILENO, "wcb"); memcpy(stderr, fl, sizeof(FILE)); } else { CloseHandle(hPipeRead); CloseHandle(eventlog_pipewrite); eventlog_pipewrite = NULL; } } else { CloseHandle(hPipeRead); CloseHandle(eventlog_pipewrite); eventlog_pipewrite = NULL; } } /* Open a null handle to nak our stdin */ hNullFile = CreateFile("nul", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, OPEN_EXISTING, 0, NULL); if (hNullFile == INVALID_HANDLE_VALUE) { ap_log_error(APLOG_MARK, APLOG_WIN32ERROR | APLOG_CRIT, NULL, "Parent: Unable to create null stdin pipe for this service process.\n"); } else { int fh; FILE *fl; fflush(stdin); SetStdHandle(STD_INPUT_HANDLE, hNullFile); fh = _open_osfhandle((long) STD_INPUT_HANDLE, _O_RDONLY | _O_BINARY); dup2(fh, STDIN_FILENO); fl = _fdopen(STDIN_FILENO, "rcb"); memcpy(stdin, fl, sizeof(FILE)); } /* Open a null handle to soak our stdout */ hNullFile = CreateFile("nul", GENERIC_READ | GENERIC_WRITE, FILE_SHARE_READ | FILE_SHARE_WRITE, &sa, OPEN_EXISTING, 0, NULL); if (hNullFile == INVALID_HANDLE_VALUE) { ap_log_error(APLOG_MARK, APLOG_WIN32ERROR | APLOG_CRIT, NULL, "Parent: Unable to create null stdout pipe for this service process.\n"); } else { int fh; FILE *fl; fflush(stdout); SetStdHandle(STD_OUTPUT_HANDLE, hNullFile); fh = _open_osfhandle((long) STD_OUTPUT_HANDLE, _O_WRONLY | _O_BINARY); dup2(fh, STDOUT_FILENO); fl = _fdopen(STDOUT_FILENO, "wcb"); memcpy(stdout, fl, sizeof(FILE)); } /* Grab it or lose it */ globdat.name = argv[0]; ap_log_error(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, NULL, "Hooked up the Service Error Event Logger."); /* Fold the "Start Parameters" in with the true executable argv[0], * and insert a -n tag to pass the service name from the SCM's argv[0] */ newargv = (char**) malloc((argc + 3) * sizeof(char*)); newargv[0] = ap_server_argv0; /* The true executable name */ newargv[1] = "-n"; /* True service name follows (argv[0]) */ memcpy (newargv + 2, argv, argc * sizeof(char*)); newargv[argc + 2] = NULL; /* SCM doesn't null terminate the array */ argv = newargv; argc += 2; /* Use the name of the service as the error log marker */ ap_server_argv0 = globdat.name; globdat.exit_status = globdat.main_fn( argc, argv ); }
VOID WINAPI ServiceMain (DWORD argc, LPTSTR *argv) { DWORD Status = E_FAIL; g_StatusHandle = RegisterServiceCtrlHandler (SERVICE_NAME, ServiceCtrlHandler); if (g_StatusHandle == nullptr) { return; } ZeroMemory (&g_ServiceStatus, sizeof (g_ServiceStatus)); g_ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; g_ServiceStatus.dwControlsAccepted = 0; g_ServiceStatus.dwCurrentState = SERVICE_START_PENDING; g_ServiceStatus.dwWin32ExitCode = 0; g_ServiceStatus.dwServiceSpecificExitCode = 0; g_ServiceStatus.dwCheckPoint = 0; if (SetServiceStatus (g_StatusHandle , &g_ServiceStatus) == FALSE) { OutputDebugString(_T("NewYearGarland: ServiceMain: SetServiceStatus returned error")); } g_ServiceStopEvent = CreateEvent (nullptr, TRUE, FALSE, nullptr); if (g_ServiceStopEvent == nullptr) { g_ServiceStatus.dwControlsAccepted = 0; g_ServiceStatus.dwCurrentState = SERVICE_STOPPED; g_ServiceStatus.dwWin32ExitCode = GetLastError(); g_ServiceStatus.dwCheckPoint = 1; if (SetServiceStatus (g_StatusHandle, &g_ServiceStatus) == FALSE) { OutputDebugString(_T("NewYearGarland: ServiceMain: SetServiceStatus returned error")); } return; } g_ServiceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP; g_ServiceStatus.dwCurrentState = SERVICE_RUNNING; g_ServiceStatus.dwWin32ExitCode = 0; g_ServiceStatus.dwCheckPoint = 0; if (SetServiceStatus (g_StatusHandle, &g_ServiceStatus) == FALSE) { OutputDebugString(_T("NewYearGarland: ServiceMain: SetServiceStatus returned error")); } HANDLE hThread = CreateThread (nullptr, 0, ServiceWorkerThread, nullptr, 0, nullptr); WaitForSingleObject (hThread, INFINITE); CloseHandle (g_ServiceStopEvent); g_ServiceStatus.dwControlsAccepted = 0; g_ServiceStatus.dwCurrentState = SERVICE_STOPPED; g_ServiceStatus.dwWin32ExitCode = 0; g_ServiceStatus.dwCheckPoint = 3; if (SetServiceStatus (g_StatusHandle, &g_ServiceStatus) == FALSE) { OutputDebugString(_T("NewYearGarland: ServiceMain: SetServiceStatus returned error")); } }
void ArchDaemonWindows::serviceMain(DWORD argc, LPTSTR* argvIn) { typedef std::vector<LPCTSTR> ArgList; typedef std::vector<std::string> Arguments; const char** argv = const_cast<const char**>(argvIn); // create synchronization objects m_serviceMutex = ARCH->newMutex(); m_serviceCondVar = ARCH->newCondVar(); // register our service handler function m_statusHandle = RegisterServiceCtrlHandler(argv[0], &ArchDaemonWindows::serviceHandlerEntry); if (m_statusHandle == 0) { // cannot start as service m_daemonResult = -1; ARCH->closeCondVar(m_serviceCondVar); ARCH->closeMutex(m_serviceMutex); return; } // tell service control manager that we're starting m_serviceState = SERVICE_START_PENDING; setStatus(m_serviceState, 0, 10000); std::string commandLine; // if no arguments supplied then try getting them from the registry. // the first argument doesn't count because it's the service name. Arguments args; ArgList myArgv; if (argc <= 1) { // read command line HKEY key = openNTServicesKey(); key = ArchMiscWindows::openKey(key, argvIn[0]); key = ArchMiscWindows::openKey(key, _T("Parameters")); if (key != NULL) { commandLine = ArchMiscWindows::readValueString(key, _T("CommandLine")); } // if the command line isn't empty then parse and use it if (!commandLine.empty()) { // parse, honoring double quoted substrings std::string::size_type i = commandLine.find_first_not_of(" \t"); while (i != std::string::npos && i != commandLine.size()) { // find end of string std::string::size_type e; if (commandLine[i] == '\"') { // quoted. find closing quote. ++i; e = commandLine.find("\"", i); // whitespace must follow closing quote if (e == std::string::npos || (e + 1 != commandLine.size() && commandLine[e + 1] != ' ' && commandLine[e + 1] != '\t')) { args.clear(); break; } // extract args.push_back(commandLine.substr(i, e - i)); i = e + 1; } else { // unquoted. find next whitespace. e = commandLine.find_first_of(" \t", i); if (e == std::string::npos) { e = commandLine.size(); } // extract args.push_back(commandLine.substr(i, e - i)); i = e + 1; } // next argument i = commandLine.find_first_not_of(" \t", i); } // service name goes first myArgv.push_back(argv[0]); // get pointers for (size_t j = 0; j < args.size(); ++j) { myArgv.push_back(args[j].c_str()); } // adjust argc/argv argc = (DWORD)myArgv.size(); argv = &myArgv[0]; } } m_commandLine = commandLine; try { // invoke daemon function m_daemonResult = m_daemonFunc(static_cast<int>(argc), argv); } catch (XArchDaemonRunFailed& e) { setStatusError(e.m_result); m_daemonResult = -1; } catch (...) { setStatusError(1); m_daemonResult = -1; } // clean up ARCH->closeCondVar(m_serviceCondVar); ARCH->closeMutex(m_serviceMutex); // we're going to exit now, so set status to stopped m_serviceState = SERVICE_STOPPED; setStatus(m_serviceState, 0, 10000); }
void WINAPI TimeServiceMain(DWORD dwArgc, LPTSTR *lpszArgv) { #ifdef _WIN64 unsigned __int64 dwCompKey = CK_SERVICECONTROL; #else DWORD dwCompKey = CK_SERVICECONTROL; #endif DWORD fdwControl = SERVICE_CONTROL_RUN; DWORD dwBytesTransferred; OVERLAPPED *po; SERVICE_STATUS ss; SERVICE_STATUS_HANDLE hSS; BOOL bPasswordCompileEmbedded = 0; // We must get the private password for connecting to this machine. // The password can be compiled into the server any of the following ways...... // 1 way - the easiest way, just uncomment and put any value between the quotes // then remove the code between --Load External Password Begin & End-- below // ***** example of very simple integrated password ******** // GString strPassword("Password"); // GString strPort("80"); // GString strRoot; // bPasswordCompileEmbedded = 1; // Another way - a most secure way to embed the password. // ***** example of integrated password ******** // GString strPassword; // MakePassword(strPassword); // Go read the MakePassword() routine above. // GString strPort("80"); // GString strRoot; // bPasswordCompileEmbedded = 1; // OR // The password can be retrieved from an external disk location. // Passwords can be obtained from disk in two different ways. // Either in a registry key matching the (probably renamed) // executable file that is this server, OR by loading a // predefined file name at a predefined location. // This file must be present while starting the server, but can be // removed once this process has fully started. // --Load External Password Begin-- GString strPassword; GString strPort; GString strRoot; if (!bPasswordCompileEmbedded) { GString strThisEXEName(GetThisEXEName()); GString strStartupKey; // use our runtime image name as the registry key char buf[512]; long lSize = sizeof(buf); if (RegQueryValue(HKEY_CLASSES_ROOT,(const char *)strThisEXEName,buf,&lSize) == ERROR_SUCCESS) { // uudecode the startup key BUFFER b; BufferInit(&b); unsigned int nDecoded; uudecode(buf, &b, &nDecoded, false); strStartupKey.write((const char *)b.pBuf,nDecoded); BufferTerminate(&b); } GString strStartupData; if (strStartupKey.Length()) { // look for a file in the root of the file system (c:\) // with the same name as this .exe GString strFile("c:\\"); strFile += strThisEXEName; // load the crypted disk file into clear text memory char *pDest; int nDestLen; GString strErrorOut; if (FileDecryptToMemory(strStartupKey, strFile, &pDest, &nDestLen, strErrorOut)) { // parse into the profile data structures pDest[7 + nDestLen] = 0; // null terminate it strStartupData.write(&pDest[7], nDestLen + 1); // and cap the GString } else { // if the file was not in the root of the file system // see if there is an environment setting directing // this server to look for the file in another location // The variable name is dynamic, matching this .exe name // and the environment variable value must be a fully // qualified path and file name to the startup file. if (getenv(strThisEXEName)) { if (FileDecryptToMemory(strStartupKey, getenv(strThisEXEName), &pDest, &nDestLen, strErrorOut)) { // parse into the profile data structures strStartupData.write(&pDest[7], nDestLen-7); } } } // parse stored settings in startup file to startup variables if (strStartupData.Length()) { GStringList lstOptions("&&",strStartupData); GStringIterator it(&lstOptions); if (it()) strPassword = it++; if (it()) strRoot = it++; // currently not used if (it()) strPort = it++; } } } // --Load External Password End-- GString strFile; GString strConfigFileDefault; GString strErrorOut; int bSetStartupFile = 0; #ifdef _WIN32 SetPriorityClass(GetCurrentProcess(),HIGH_PRIORITY_CLASS); // = 1 point above normal #endif // Create the completion port and save its handle in a global // variable so that the Handler function can access it. g_hIOCP = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, CK_PIPE, 0); // Give SCM the address of this service's Handler // NOTE: hSS does not have to be closed. hSS = RegisterServiceCtrlHandler((const char *)strServerName, TimeServiceHandler); // Do what the service should do. // Initialize the members that never change ss.dwServiceType = SERVICE_WIN32_OWN_PROCESS; ss.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE | SERVICE_ACCEPT_SHUTDOWN; do { switch (dwCompKey) { case CK_SERVICECONTROL: // We got a new control code ss.dwWin32ExitCode = NO_ERROR; ss.dwServiceSpecificExitCode = 0; ss.dwCheckPoint = 0; ss.dwWaitHint = 0; if (fdwControl == SERVICE_CONTROL_INTERROGATE) { SetServiceStatus(hSS, &ss); break; } // Determine which PENDING state to return if (dwSrvCtrlToPend[fdwControl] != 0) { ss.dwCurrentState = dwSrvCtrlToPend[fdwControl]; ss.dwCheckPoint = 0; ss.dwWaitHint = 500; // half a second SetServiceStatus(hSS, &ss); } switch (fdwControl) { case SERVICE_CONTROL_RUN: case SERVICE_CONTROL_CONTINUE: try { if (strRoot.Length() && strPort.Length()) { GString strCfgData; strCfgData.Format(pzBoundStartupConfig,(const char *)strRoot,(const char *)strPort); SetProfile(new GProfile((const char *)strCfgData, (int)strCfgData.Length(), 0)); if (!server_start()) { ss.dwCurrentState = SERVICE_STOPPED; ss.dwCheckPoint = ss.dwWaitHint = 0; SetServiceStatus(hSS, &ss); break; } } else { // No password compiled in - and no valid startup file found for(int i=0; i<3;i++) { // three beeps MessageBeep(0); Sleep(1000); } ss.dwCurrentState = SERVICE_STOPPED; ss.dwCheckPoint = ss.dwWaitHint = 0; SetServiceStatus(hSS, &ss); break; } } catch ( GException &) { ss.dwCurrentState = SERVICE_STOPPED; ss.dwCheckPoint = ss.dwWaitHint = 0; SetServiceStatus(hSS, &ss); break; } if (dwSrvPendToState[ss.dwCurrentState] != 0) { ss.dwCurrentState = dwSrvPendToState[ss.dwCurrentState]; ss.dwCheckPoint = ss.dwWaitHint = 0; SetServiceStatus(hSS, &ss); } break; case SERVICE_CONTROL_PAUSE: case SERVICE_CONTROL_STOP: case SERVICE_CONTROL_SHUTDOWN: server_stop(); if (dwSrvPendToState[ss.dwCurrentState] != 0) { ss.dwCurrentState = dwSrvPendToState[ss.dwCurrentState]; ss.dwCheckPoint = ss.dwWaitHint = 0; SetServiceStatus(hSS, &ss); } break; } // Determine which complete state to return break; } if (ss.dwCurrentState != SERVICE_STOPPED) { // Sleep until a control code comes in or a client connects GetQueuedCompletionStatus(g_hIOCP, &dwBytesTransferred, &dwCompKey, &po, INFINITE); fdwControl = dwBytesTransferred; } } while (ss.dwCurrentState != SERVICE_STOPPED); // Cleanup and stop this service CloseHandle(g_hIOCP); }
// 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_); }
/* * Service Main function - Called by the SCM after the service has started */ void WINAPI ServiceMain(DWORD argc, LPTSTR *argv) { gServiceHandle = RegisterServiceCtrlHandler(g_serviceName, ServiceCtrlHandler); if (gServiceHandle == 0) { logStartError("RegisterServiceCtrlHandler failed."); } else { // signal service is starting setServiceStatus(SERVICE_START_PENDING, TRUE, NO_ERROR, 3000); // create event for when service is signaled to stop g_serviceStopEvent = CreateEvent(NULL, TRUE, FALSE, NULL); if (g_serviceStopEvent) { TCHAR szPath[MAX_PATH]; char *last_slash; GetModuleFileName(NULL, szPath, MAX_PATH); last_slash = s_strrchr(szPath, '\\', MAX_PATH); if (NULL != last_slash) *last_slash = '\0'; if (SetCurrentDirectory(szPath)) { std::vector<monitor::NvmMonitorBase *> monitors; monitor::NvmMonitorBase::getMonitors(monitors); size_t handleCount = monitors.size() + 1; // +1 to also add g_serviceStopEvent HANDLE handles[handleCount]; for (size_t i = 0; i < monitors.size(); i++) { handles[i] = CreateThread(NULL, 0, WorkerThread, (LPVOID) (monitors[i]), 0, NULL); } // In the case there are no monitor items, adding the stop event will keep the // service running until a Service Stop Event occurs. handles[handleCount - 1] = g_serviceStopEvent; // now running setServiceStatus(SERVICE_RUNNING, false, NO_ERROR, 0); // wait for all threads to end and Service Stop Event WaitForMultipleObjects(handleCount, handles, true, INFINITE); // clean up for (size_t i = 0; i < handleCount; i++) { CloseHandle(handles[i]); } monitor::NvmMonitorBase::deleteMonitors(monitors); setServiceStatus(SERVICE_STOPPED, FALSE, NO_ERROR, 0); } else { logStartError("Failed to set working directory."); setServiceStatus(SERVICE_STOPPED, FALSE, NO_ERROR, 0); } } else { logStartError("CreateEvent Failed"); setServiceStatus(SERVICE_STOPPED, FALSE, NO_ERROR, 0); } } }
void WINAPI ServiceMain(DWORD argc, LPTSTR argv[]) { bool bConnected; CHAR chRequest[MAX_PATH + 1]; DWORD cbBytesRead, cbTotalBytes; BOOL bSuccess; char* szData = new char[BUFFER_SIZE]; char* szArguments = NULL; HANDLE hPipe; SERVICE_STATUS ss = { SERVICE_WIN32_OWN_PROCESS, SERVICE_START_PENDING, SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN, NO_ERROR, 0, 1, 5000 }; hStopEvent = CreateEvent(NULL, FALSE, FALSE, NULL); g_hServiceStatus = RegisterServiceCtrlHandler(SERVICE_NAME, ControlHandler); if (!g_hServiceStatus) { delete szData; ss.dwCurrentState = SERVICE_STOPPED; SetServiceStatus(g_hServiceStatus, &ss); return; } if (!SetServiceStatus(g_hServiceStatus, &ss)) { delete szData; ss.dwCurrentState = SERVICE_STOPPED; SetServiceStatus(g_hServiceStatus, &ss); return; } ss.dwCheckPoint++; if (!SetServiceStatus(g_hServiceStatus, &ss)) { delete szData; ss.dwCurrentState = SERVICE_STOPPED; SetServiceStatus(g_hServiceStatus, &ss); return; } hPipe = CreateNamedPipe(g_szPipeName, PIPE_ACCESS_DUPLEX, // read/write access PIPE_TYPE_MESSAGE | // message type pipe PIPE_READMODE_MESSAGE | // message-read mode PIPE_WAIT, // non-blocking mode PIPE_UNLIMITED_INSTANCES, // max. instances BUFSIZE, // output buffer size MAX_PATH, // input buffer size 1000, // client time-out NULL); // no security attribute if (hPipe == INVALID_HANDLE_VALUE) { delete szData; ss.dwCurrentState = SERVICE_STOPPED; SetServiceStatus(g_hServiceStatus, &ss); return; } ss.dwCheckPoint = 0; ss.dwCurrentState = SERVICE_RUNNING; ss.dwControlsAccepted = SERVICE_ACCEPT_STOP; if (!SetServiceStatus(g_hServiceStatus, &ss)) { delete szData; ss.dwCurrentState = SERVICE_STOPPED; SetServiceStatus(g_hServiceStatus, &ss); return; } bConnected = ConnectNamedPipe(hPipe, NULL) ? true : (GetLastError() == ERROR_PIPE_CONNECTED || GetLastError() == ERROR_PIPE_LISTENING); while(bConnected) { if (WaitForSingleObject(hStopEvent, 1000) == WAIT_OBJECT_0) { ss.dwCheckPoint = 1; ss.dwCurrentState = SERVICE_STOP_PENDING; ss.dwWaitHint = 2000; SetServiceStatus(g_hServiceStatus, &ss); break; // Stop the service now } if (bConnected) { memset(chRequest, 0, MAX_PATH); //bSuccess = PeekNamedPipe(hPipe, chRequest, MAX_PATH, &cbBytesRead, &cbTotalBytes, &cbBytesLeft); bSuccess = ReadFile(hPipe, chRequest, MAX_PATH, &cbBytesRead, NULL); if (bSuccess && cbBytesRead > 0) { chRequest[cbBytesRead] = '\0'; //FlushFileBuffers(hPipe); // Try to execute the command ::ZeroMemory(szData, BUFFER_SIZE); // See if there is a "||" sequence in the command - if so, it separates the arguments and the command if (strstr(chRequest, "||") != NULL) { szArguments = strstr(chRequest, "||"); *szArguments = '\0'; // Make this the end of the string szArguments += 2; } if (ExecuteCommand(chRequest, szArguments, 120000, &szData, BUFFER_SIZE)) // 2 minute timeout { WriteFile(hPipe, szData, strlen(szData), &cbTotalBytes, NULL); } else { char szError[256]; ::ZeroMemory(szError, 256); _snprintf_s(szError, 256, sizeof(GetLastError())+37, "Exec failed, GetLastError returned %d\n", GetLastError()); WriteFile(hPipe, szError, strlen(szError), &cbTotalBytes, NULL); } FlushFileBuffers(hPipe); DisconnectNamedPipe(hPipe); bConnected = ConnectNamedPipe(hPipe, NULL) ? true : (GetLastError() == ERROR_PIPE_CONNECTED || GetLastError() == ERROR_PIPE_LISTENING); } } } CloseHandle(hPipe); CloseHandle(hStopEvent); ss.dwCurrentState = SERVICE_STOPPED; SetServiceStatus(g_hServiceStatus, &ss); delete szData; }
static void #if defined(_WIN32) WINAPI #endif service_loop(int argc, char** argv) { int argn; char* arg; char str[128]; char compiler[128]; for(argn=1; argn<(int)argc; argn++) { arg=argv[argn]; if(*arg!='-') { /* .ini file specified */ if(!fexist(arg)) { lprintf(LOG_ERR,"Initialization file does not exist: %s", arg); exit(usage(argv[0])); } parse_ini_file(arg); continue; } while(*arg=='-') arg++; if(stricmp(arg,"null")==0) mdm_null=TRUE; else if(stricmp(arg,"com")==0 && argc > argn+1) SAFECOPY(com_dev, argv[++argn]); else if(stricmp(arg,"baud")==0 && argc > argn+1) com_baudrate = (ulong)strtol(argv[++argn],NULL,0); else if(stricmp(arg,"host")==0 && argc > argn+1) SAFECOPY(host, argv[++argn]); else if(stricmp(arg,"port")==0 && argc > argn+1) port = (ushort)strtol(argv[++argn], NULL, 0); else if(stricmp(arg,"live")==0) { if(argc > argn+1 && (com_handle = (COM_HANDLE)strtol(argv[argn+1], NULL, 0)) != 0) { argn++; com_handle_passed=TRUE; } com_alreadyconnected=TRUE; terminate_after_one_call=TRUE; mdm_null=TRUE; } else if(stricmp(arg,"nohangup")==0) { com_hangup=FALSE; } else if(stricmp(arg,"debug")==0) { log_level=LOG_DEBUG; } else if(stricmp(arg,"help")==0 || *arg=='?') exit(usage(argv[0])); else { fprintf(stderr,"Invalid option: %s\n", arg); exit(usage(argv[0])); } } #if defined(_WIN32) /* Convert "1" to "COM1" for Windows */ { int i; if((i=atoi(com_dev)) != 0) SAFEPRINTF(com_dev, "COM%d", i); } if(daemonize) { if((svc_status_handle = RegisterServiceCtrlHandler(NAME, ServiceControlHandler))==0) { lprintf(LOG_ERR,"!ERROR %d registering service control handler",GetLastError()); return; } svc_status.dwServiceType=SERVICE_WIN32_OWN_PROCESS; svc_status.dwControlsAccepted=SERVICE_ACCEPT_SHUTDOWN; svc_status.dwWaitHint=NTSVC_TIMEOUT_STARTUP; svc_status.dwCurrentState=SERVICE_START_PENDING; SetServiceStatus(svc_status_handle, &svc_status); } #endif lprintf(LOG_INFO,"%s", comVersion(str,sizeof(str))); DESCRIBE_COMPILER(compiler); lprintf(LOG_INFO,"Build %s %s %s", __DATE__, __TIME__, compiler); /************************************/ /* Inititalize WinSock and COM Port */ /************************************/ if(!winsock_startup()) exit(1); /* Install clean-up callback */ atexit(cleanup); lprintf(LOG_INFO,"TCP Host: %s", host); lprintf(LOG_INFO,"TCP Port: %u", port); if(!com_handle_passed) { lprintf(LOG_INFO,"Opening Communications Device (COM Port): %s", com_dev); if((com_handle=comOpen(com_dev)) == COM_HANDLE_INVALID) { lprintf(LOG_ERR,"ERROR %u opening communications device/port: '%s'", COM_ERROR_VALUE, com_dev); exit(1); } } lprintf(LOG_INFO,"COM Port device handle: %u", com_handle); if(com_baudrate!=0) { if(!comSetBaudRate(com_handle,com_baudrate)) lprintf(LOG_ERR,"ERROR %u setting DTE rate to %lu bps" ,COM_ERROR_VALUE, com_baudrate); } lprintf(LOG_INFO,"COM Port DTE rate: %ld bps", comGetBaudRate(com_handle)); if(ident) _beginthread(ident_server_thread, 0, NULL); #if defined(_WIN32) if(daemonize) { svc_status.dwCurrentState=SERVICE_RUNNING; svc_status.dwControlsAccepted|=SERVICE_ACCEPT_STOP; SetServiceStatus(svc_status_handle, &svc_status); } #endif /***************************/ /* Initialization Complete */ /***************************/ /* Main service loop: */ while(!terminated && wait_for_call(com_handle)) { if(!carrier_detect(com_handle)) /* re-initialization timer time-out? */ continue; comWriteByte(com_handle,'\r'); comWriteString(com_handle, banner); comWriteString(com_handle, "\r\n"); if((sock=connect_socket(host, port)) == INVALID_SOCKET) { comWriteString(com_handle,"\7\r\n!ERROR connecting to TCP port\r\n"); } else { handle_call(); close_socket(&sock); total_calls++; lprintf(LOG_INFO,"Call completed (%lu total)", total_calls); } if(com_hangup && !hangup_call(com_handle)) break; if(terminate_after_one_call) break; } exit(0); }
/** * The main function for the service. * Called by the services API when starting unbound on windows in background. * Arguments could have been present in the string 'path'. * @param argc: nr args * @param argv: arg text. */ static void service_main(DWORD ATTR_UNUSED(argc), LPTSTR* ATTR_UNUSED(argv)) { struct config_file* cfg = NULL; struct daemon* daemon = NULL; service_status_handle = RegisterServiceCtrlHandler(SERVICE_NAME, (LPHANDLER_FUNCTION)hdlr); if(!service_status_handle) { reportev("Could not RegisterServiceCtrlHandler"); return; } service_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS; service_status.dwServiceSpecificExitCode = 0; /* see if we have root anchor update enabled */ call_root_update(); /* we are now starting up */ report_status(SERVICE_START_PENDING, NO_ERROR, 3000); if(!service_init(0, &daemon, &cfg)) { reportev("Could not service_init"); report_status(SERVICE_STOPPED, NO_ERROR, 0); return; } /* event that gets signalled when we want to quit; it * should get registered in the worker-0 waiting loop. */ service_stop_event = WSACreateEvent(); if(service_stop_event == WSA_INVALID_EVENT) { log_err("WSACreateEvent: %s", wsa_strerror(WSAGetLastError())); reportev("Could not WSACreateEvent"); report_status(SERVICE_STOPPED, NO_ERROR, 0); return; } if(!WSAResetEvent(service_stop_event)) { log_err("WSAResetEvent: %s", wsa_strerror(WSAGetLastError())); } /* SetServiceStatus SERVICE_RUNNING;*/ report_status(SERVICE_RUNNING, NO_ERROR, 0); verbose(VERB_QUERY, "winservice - init complete"); /* daemon performs work */ while(!service_stop_shutdown) { daemon_fork(daemon); if(!service_stop_shutdown) { daemon_cleanup(daemon); config_delete(cfg); cfg=NULL; if(!service_init(1, &daemon, &cfg)) { reportev("Could not service_init"); report_status(SERVICE_STOPPED, NO_ERROR, 0); return; } } } /* exit */ verbose(VERB_ALGO, "winservice - cleanup."); report_status(SERVICE_STOP_PENDING, NO_ERROR, 0); service_deinit(daemon, cfg); free(service_cfgfile); if(service_stop_event) (void)WSACloseEvent(service_stop_event); verbose(VERB_QUERY, "winservice - full stop"); report_status(SERVICE_STOPPED, NO_ERROR, 0); }
static void WINAPI StartService(DWORD /*argc*/, char* argv[]) { ssh = RegisterServiceCtrlHandler(argv[0], CtrlHandler); if(ssh == NULL) { AppendLog("RegisterServiceCtrlHandler failed ("+string((uint32_t)GetLastError())+")!"); return; } ss.dwServiceType = SERVICE_WIN32_OWN_PROCESS; ss.dwCurrentState = SERVICE_START_PENDING; ss.dwControlsAccepted = SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_STOP; ss.dwWin32ExitCode = NO_ERROR; ss.dwCheckPoint = 0; ss.dwWaitHint = 10 * 1000; if(SetServiceStatus(ssh, &ss) == false) { AppendLog("StartService::SetServiceStatus failed ("+string((uint32_t)GetLastError())+")!"); return; } ServerInitialize(); if(ServerStart() == false) { AppendLog("Server start failed!"); ss.dwCurrentState = SERVICE_STOPPED; SetServiceStatus(ssh, &ss); return; } ss.dwCurrentState = SERVICE_RUNNING; if(SetServiceStatus(ssh, &ss) == false) { AppendLog("StartService::SetServiceStatus1 failed ("+string((uint32_t)GetLastError())+")!"); return; } MSG msg; BOOL bRet; while((bRet = GetMessage(&msg, NULL, 0, 0)) != 0) { if(bRet == -1) { // handle the error and possibly exit } else { if(msg.message == WM_USER+1) { break; } else if(msg.message == WM_TIMER) { if(msg.wParam == sectimer) { ServerOnSecTimer(); } else if(msg.wParam == srvLoopTimer) { srvLoop->Looper(); } else if(msg.wParam == regtimer) { ServerOnRegTimer(); } else { //Must be script timer ScriptOnTimer(msg.wParam); } } TranslateMessage(&msg); DispatchMessage(&msg); } } ExceptionHandlingUnitialize(); ss.dwCurrentState = SERVICE_STOPPED; SetServiceStatus(ssh, &ss); }
// ------------------------------------------------------------------------- // void KsNtServiceServer::serviceMain(int argc, char **argv) { // // First, create some signaling objects. The _one_shot_event signals // the serviceRun() task that it should wake up and iterate once again, // thus spinning up the KS server, and process requests. The next event, // _service_done_event, signals, that the whole service task (executable) // is now ready to cease. // _service_done_event = CreateEvent(0, FALSE, FALSE, 0); _one_shot_event = CreateEvent(0, FALSE, FALSE, 0); if ( !_service_done_event || !_one_shot_event ) { lastError("Can't initialize signaling mechanism"); } // // Next, register the service controller. Remember, that only after we've // done this, we can report the service status to the service manager. // _service_status_handle = RegisterServiceCtrlHandler( (LPCTSTR) _service_name, (LPHANDLER_FUNCTION) ks_c_serviceController); if ( !_service_status_handle ) { lastError("Can't register service control handler"); return; } // // Next, we ask the developer for a KS server object, which will be // subsequently used within the real workhorse thread. // reportServiceStatus(SERVICE_START_PENDING, NO_ERROR, 0, 1, _create_to); _my_server = createServer((int) argc, (char **) argv); if ( !_is_ok || (_my_server == 0) || !_my_server->isOk() ) { _is_ok = false; PltLog::Error("abnormal service termination"); return; } verbose("Created server object successfully"); reportServiceStatus(SERVICE_START_PENDING, NO_ERROR, 0, 2, _spinup_to); // // We must use the apropriate function from the C++ RTL here, as we will // otherwise get memory leaks. As if NT wouldn't be the biggest memory // leak ever created by menkind... // #if PLT_COMPILER_MSVC _workhorse_thread = (HANDLE) _beginthread( (void (*)(void *)) ks_c_serviceRun, // entry point of new thread 0, // stack size (default) 0); // arguments (none) #else # if PLT_COMPILER_BORLAND _workhorse_thread = (HANDLE) _beginthreadNT( (void (*)(void *)) ks_c_serviceRun, // entry point of new thread 32768, // initial stack size 0, // no arguments to pass to thread 0, // no security, as NT hasn't one... 0, // spin up thread immediately &_workhorse_thread_id); # else # error "Don't know how to start threads" # endif #endif if ( _workhorse_thread <= 0) { _is_ok = false; PltLog::Error("Can't start service thread"); return; } verbose("Started service thread"); // // Gosh! Finally, we're up and running. Yeah, I can't believe it! // reportServiceStatus(SERVICE_RUNNING, NO_ERROR, 0, 0, 0); if ( WaitForSingleObject(_service_done_event, INFINITE) != WAIT_OBJECT_0 ) { PltLog::Warning("\"Service Done\" signaling failed"); } verbose("Service thread woken up"); if ( !TerminateThread(_workhorse_thread, 0) ) { lastError("Can't terminate service thread"); } if ( _my_server ) { delete _my_server; _my_server = 0; } // // Simply terminate. This will throw us back to the main thread. // reportServiceStatus(SERVICE_STOPPED, _service_status.dwWin32ExitCode, _service_status.dwServiceSpecificExitCode, 0, 0); } // KsNtServiceServer::serviceMain
VOID svcMain(DWORD argc, LPTSTR *argv) { DWORD wait; /* Register the control handler */ SvcStatusHandle = RegisterServiceCtrlHandler(TEXT(SvcName), (LPHANDLER_FUNCTION)svcControl); if (!SvcStatusHandle) { message(0, 0, "failed to register service control handler"); goto finish; } /* Initialise static service status values */ SvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; SvcStatus.dwServiceSpecificExitCode = 0; /* Report to SCM */ if (!svcReport(SERVICE_START_PENDING, /* Service state */ NO_ERROR, /* Exit code */ 1, /* Checkpoint number */ 5000)) /* Wait hint -- 5 secs */ { message(0, 0, "failed to report status to SCM"); goto finish; } /* ** Create the "stop event" object. The arguments indicate a manually ** reset event whose initial state is unset. */ if ((SvcFinishEvent = CreateEvent(NULL, 1, 0, NULL)) == NULL) { goto finish; } /* Report next checkpoint to SCM */ if (!svcReport(SERVICE_START_PENDING, NO_ERROR, 2, 5000)) { message(0, 0, "failed to report status to SCM"); goto finish; } /* Start the worker thread */ SvcThreadHandle = (HANDLE)CreateThread(NULL, 65536, SvcFunction, SvcArg, 0, NULL); if (!SvcThreadHandle) { message(0, 0, "failed to create worker thread"); goto finish; } /* Report all systems GO! */ if (!svcReport(SERVICE_RUNNING, NO_ERROR, 0, 0)) { message(0, 0, "failed to report status to SCM"); goto finish; } /* Wait until SvcFinishEvent is set */ wait = WaitForSingleObject(SvcFinishEvent, INFINITE); finish: if (SvcFinishEvent != NULL) { CloseHandle(SvcFinishEvent); } /* Report to SCM if possible */ if (SvcStatusHandle != 0) { svcReport(SERVICE_STOPPED, SvcError, 0, 0); } return; }
/** This callback is called by windows when the service is started */ VOID ServiceMain(DWORD argc, LPCSTR *argv) { g_ServiceStatusHandle = RegisterServiceCtrlHandler(TEXT("InspIRCd"), (LPHANDLER_FUNCTION)ServiceCtrlHandler); if( !g_ServiceStatusHandle ) return; g_ServiceStatus.dwCheckPoint = 1; g_ServiceStatus.dwControlsAccepted = 0; g_ServiceStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; g_ServiceStatus.dwWaitHint = 5000; g_ServiceStatus.dwWin32ExitCode = NO_ERROR; g_ServiceStatus.dwCurrentState = SERVICE_START_PENDING; if( !SetServiceStatus( g_ServiceStatusHandle, &g_ServiceStatus ) ) return; char szModuleName[MAX_PATH]; if(GetModuleFileNameA(NULL, szModuleName, MAX_PATH)) { if(!argc) argc = 1; g_ServiceData.argc = argc; // Note: since this memory is going to stay allocated for the rest of the execution, // it doesn't make sense to free it, as it's going to be "freed" on process termination try { g_ServiceData.argv = new char*[argc]; uint32_t allocsize = strnlen_s(szModuleName, MAX_PATH) + 1; g_ServiceData.argv[0] = new char[allocsize]; strcpy_s(g_ServiceData.argv[0], allocsize, szModuleName); for(uint32_t i = 1; i < argc; i++) { allocsize = strnlen_s(argv[i], MAX_PATH) + 1; g_ServiceData.argv[i] = new char[allocsize]; strcpy_s(g_ServiceData.argv[i], allocsize, argv[i]); } *(strrchr(szModuleName, '\\') + 1) = NULL; SetCurrentDirectoryA(szModuleName); HANDLE hThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)WorkerThread, NULL, 0, NULL); if (hThread != NULL) { WaitForSingleObject(hThread, INFINITE); CloseHandle(hThread); } } catch(...) { g_ServiceStatus.dwCurrentState = SERVICE_STOPPED; g_ServiceStatus.dwWin32ExitCode = ERROR_OUTOFMEMORY; SetServiceStatus( g_ServiceStatusHandle, &g_ServiceStatus ); } } if(g_ServiceStatus.dwCurrentState == SERVICE_STOPPED) return; g_ServiceStatus.dwCurrentState = SERVICE_STOPPED; g_ServiceStatus.dwWin32ExitCode = GetLastError(); SetServiceStatus( g_ServiceStatusHandle, &g_ServiceStatus ); }
/* * ServiceMain function. */ VOID WINAPI ServiceMain (DWORD argc, LPTSTR argv[]) { SECURITY_ATTRIBUTES SecurityAttributes; unsigned threadId; /* * Input arguments */ DWORD ArgCount = 0; LPTSTR *ArgArray = NULL; TCHAR szRegKey[512]; HKEY hParamKey = NULL; DWORD TotalParams = 0; DWORD i; InputParams ThreadInputParams; /* * Build the Input parameters to pass to worker thread */ /* * SCM sends Service Name as first arg, increment to point * arguments user specified while starting control agent */ /* * Read registry parameter */ ArgCount = 1; /* * Create registry key path */ _sntprintf (szRegKey, CountOf(szRegKey), _T("%s%s\\%s"), _T ("SYSTEM\\CurrentControlSet\\Services\\"), app_name_long, _T("Parameters")); if (RegOpenKeyEx (HKEY_LOCAL_MACHINE, szRegKey, 0, KEY_ALL_ACCESS, &hParamKey) == ERROR_SUCCESS) { /* * Read startup configuration information */ /* * Find number of subkeys inside parameters */ if (RegQueryInfoKey (hParamKey, NULL, NULL, 0, NULL, NULL, NULL, &TotalParams, NULL, NULL, NULL, NULL) == ERROR_SUCCESS) { if (TotalParams != 0) { ArgCount += TotalParams; /* * Allocate memory to hold strings */ ArgArray = calloc(ArgCount, sizeof(ArgArray[0])); if (ArgArray == 0) { WriteToEventLog (EVENTLOG_ERROR_TYPE, _T ("Resource failure")); return; } /* * Copy first argument */ ArgArray[0] = _tcsdup (argv[0]); for (i = 1; i <= TotalParams; i++) { DWORD dwErrorcode; DWORD nSize; DWORD nRegkeyType; TCHAR *szValue; /* * Create Subkey value name */ _sntprintf (szRegKey, CountOf(szRegKey), _T("%s%d"), _T("Param"), i); /* * Query subkey. */ nSize = 0; dwErrorcode = RegQueryValueEx(hParamKey, szRegKey, NULL, &nRegkeyType, NULL, &nSize); if (dwErrorcode == ERROR_SUCCESS) { if (nRegkeyType == REG_SZ || nRegkeyType == REG_EXPAND_SZ) { szValue = malloc(nSize + sizeof(szValue[0])); if (szValue) { dwErrorcode = RegQueryValueEx(hParamKey, szRegKey, NULL, &nRegkeyType, (LPBYTE)szValue, &nSize); if (dwErrorcode == ERROR_SUCCESS) { szValue[nSize] = 0; ArgArray[i] = szValue; } else { free(szValue); WriteToEventLog(EVENTLOG_ERROR_TYPE, _T("Querying registry key %s failed: error code %ld"), szRegKey, dwErrorcode); } } else WriteToEventLog(EVENTLOG_ERROR_TYPE, _T("Querying registry key %s failed: out of memory"), szRegKey); } else WriteToEventLog(EVENTLOG_ERROR_TYPE, _T("Type %ld of registry key %s is incorrect"), nRegkeyType, szRegKey); } else WriteToEventLog(EVENTLOG_ERROR_TYPE, _T("Querying registry key %s failed: error code %ld"), szRegKey, dwErrorcode); if (!ArgArray[i]) { TotalParams = ArgCount = i; break; } } } } RegCloseKey (hParamKey); } if (ArgCount == 1) { /* * No startup args are given */ ThreadInputParams.Argc = argc; ThreadInputParams.Argv = argv; } else { ThreadInputParams.Argc = ArgCount; ThreadInputParams.Argv = ArgArray; } /* * Register Service Control Handler */ hServiceStatus = RegisterServiceCtrlHandler (app_name_long, ControlHandler); if (hServiceStatus == 0) { WriteToEventLog (EVENTLOG_ERROR_TYPE, _T ("RegisterServiceCtrlHandler failed")); return; } /* * Update the service status to START_PENDING. */ UpdateServiceStatus (SERVICE_START_PENDING, NO_ERROR, SCM_WAIT_INTERVAL); /* * Start the worker thread, which does the majority of the work . */ TRY { if (SetSimpleSecurityAttributes (&SecurityAttributes) == FALSE) { WriteToEventLog (EVENTLOG_ERROR_TYPE, _T ("Couldn't init security attributes")); LEAVE; } hServiceThread = (void *) _beginthreadex (&SecurityAttributes, 0, ThreadFunction, (void *) &ThreadInputParams, 0, &threadId); if (hServiceThread == NULL) { WriteToEventLog (EVENTLOG_ERROR_TYPE, _T ("Couldn't start worker thread")); LEAVE; } /* * Set service status to SERVICE_RUNNING. */ UpdateServiceStatus (SERVICE_RUNNING, NO_ERROR, SCM_WAIT_INTERVAL); /* * Wait until the worker thread finishes. */ WaitForSingleObject (hServiceThread, INFINITE); } FINALLY { /* * Release resources */ UpdateServiceStatus (SERVICE_STOPPED, NO_ERROR, SCM_WAIT_INTERVAL); if (hServiceThread) CloseHandle (hServiceThread); FreeSecurityAttributes (&SecurityAttributes); /* * Free allocated argument list */ if (ArgCount > 1 && ArgArray != NULL) { /* * Free all strings */ for (i = 0; i < ArgCount; i++) { free (ArgArray[i]); } free (ArgArray); } } }
/* Registers the call-back and configures the actions in case of a failure * with the Windows services manager. */ void service_start(int *argcp, char **argvp[]) { int argc = *argcp; char **argv = *argvp; int i; SERVICE_TABLE_ENTRY service_table[] = { {(LPTSTR)program_name, (LPSERVICE_MAIN_FUNCTION)main}, {NULL, NULL} }; /* 'detached' is 'false' when service_start() is called the first time. * It is 'true', when it is called the second time by the Windows services * manager. */ if (detached) { init_service_status(); wevent = CreateEvent(NULL, TRUE, FALSE, NULL); if (!wevent) { char *msg_buf = ovs_lasterror_to_string(); VLOG_FATAL("Failed to create a event (%s).", msg_buf); } poll_fd_wait_event(0, wevent, POLLIN); /* Register the control handler. This function is called by the service * manager to stop the service. */ hstatus = RegisterServiceCtrlHandler(program_name, (LPHANDLER_FUNCTION)control_handler); if (!hstatus) { char *msg_buf = ovs_lasterror_to_string(); VLOG_FATAL("Failed to register the service control handler (%s).", msg_buf); } if (monitor) { set_config_failure_actions(); } /* When the service control manager does the call back, it does not * send the same arguments as sent to the main function during the * service start. So, use the arguments passed over during the first * time. */ *argcp = sargc; *argvp = *sargvp; /* XXX: Windows implementation cannot have a unixctl commands in the * traditional sense of unix domain sockets. If an implementation is * done that involves 'unixctl' vlog commands the following call is * needed to make sure that the unixctl commands for vlog get * registered in a daemon, even before the first log message. */ vlog_init(); return; } assert_single_threaded(); /* A reference to arguments passed to the main function the first time. * We need it after the call-back from service control manager. */ sargc = argc; sargvp = argvp; /* We are only interested in the '--service' and '--service-monitor' * options before the call-back from the service control manager. */ for (i = 0; i < argc; i ++) { if (!strcmp(argv[i], "--service")) { detach = true; } else if (!strcmp(argv[i], "--service-monitor")) { monitor = true; } } /* If '--service' is not a command line option, run in foreground. */ if (!detach) { return; } /* If we have been configured to run as a service, then that service * should already have been created either manually or through a start up * script. */ check_service(); detached = true; /* StartServiceCtrlDispatcher blocks and returns after the service is * stopped. */ if (!StartServiceCtrlDispatcher(service_table)) { char *msg_buf = ovs_lasterror_to_string(); VLOG_FATAL("Failed at StartServiceCtrlDispatcher (%s)", msg_buf); } exit(0); }
VOID ReplMain( IN DWORD dwNumServicesArgs, IN LPTSTR *lpServiceArgVectors ) /*++ Routine Description: Talk to service controller, read registry, and change role (which starts import and/or export parts). Arguments: Ignored. (Required by service controller interface.) Return Value: None. --*/ { NET_API_STATUS ApiStatus; BOOL LockedConfigData = FALSE; DWORD NewRole; UNREFERENCED_PARAMETER( dwNumServicesArgs ); UNREFERENCED_PARAMETER( lpServiceArgVectors ); IF_DEBUG( MAJOR ) { NetpKdPrint(( PREFIX_REPL "**************************** STARTING REPL " "****************************\n" )); } // DbgBreakPoint(); // Register control routine. // This must be done before any calls to ReportStatus(). ReplGlobalServiceHandle = RegisterServiceCtrlHandler( (LPTSTR) SERVICE_REPL, ReplControlRoutine ); if (ReplGlobalServiceHandle == (SERVICE_STATUS_HANDLE) NULL) { // can't start service NetpKdPrint(( PREFIX_REPL "can't start repl service, " "RegisterServiceCtrlHandler is in error.\n" )); // Haven't done anything to clean up, so don't. return; } ReportStatus( SERVICE_START_PENDING, NO_ERROR, REPL_WAIT_HINT, 1 ); // checkpoint // initialize global data ApiStatus = ReplInit(); if (ApiStatus != NO_ERROR) { goto Cleanup; } ReportStatus( SERVICE_START_PENDING, NO_ERROR, REPL_WAIT_HINT, 2 ); // checkpoint // Read config data from registry. We just read the stuff controlling the // service as a whole here; the client and master threads each read their // own config data as well. ApiStatus = ReplConfigRead( NULL, // no server name & NewRole, ReplConfigExportPath, &ReplConfigExportList, // Alloc and set ptr. ReplConfigImportPath, &ReplConfigImportList, // Alloc and set ptr. ReplConfigLogonUserName, & ReplConfigInterval, & ReplConfigPulse, & ReplConfigGuardTime, & ReplConfigRandom ); if (ApiStatus != NO_ERROR) { goto Cleanup; } #if DBG { LPNET_CONFIG_HANDLE SectionHandle = NULL; LPWSTR ValueT = NULL; ApiStatus = NetpOpenConfigData( &SectionHandle, NULL, // no server name. (LPTSTR) SECT_NT_REPLICATOR, // section name TRUE ); // we only want readonly access NetpAssert( ApiStatus == NO_ERROR ); ApiStatus = NetpGetConfigValue ( SectionHandle, (LPTSTR) REPL_KEYWORD_DBFLAG, &ValueT ); (VOID) NetpCloseConfigData( SectionHandle ); if (ApiStatus == NO_ERROR) { NetpAssert( ValueT != NULL ); ReplGlobalTrace = NetpAtoX( ValueT ); (VOID) NetApiBufferFree( ValueT ); } else if (ApiStatus == NERR_CfgParamNotFound) { // // copy default value in here. // // ReplGlobalTrace = 0; } else { NetpKdPrint(( PREFIX_REPL "ReplMain: unexpected error " FORMAT_API_STATUS " from NetpGetConfigValue.\n", ApiStatus )); // Probably harmless, so let's continue... } } #endif // DBG // // Make sure role in registry is allowed with current product type. // if ( !ReplConfigIsRoleAllowed( NULL, NewRole ) ) { // BUGBUG: Log this! NetpKdPrint(( PREFIX_REPL "Role inconsistent with product type; " " assuming role of " FORMAT_DWORD ".\n", REPL_ROLE_IMPORT )); NewRole = REPL_ROLE_IMPORT; // Update registry so we don't get this every time. ApiStatus = ReplConfigWrite( NULL, // no server name NewRole, ReplConfigExportPath, ReplConfigExportList, ReplConfigImportPath, ReplConfigImportList, ReplConfigLogonUserName, ReplConfigInterval, ReplConfigPulse, ReplConfigGuardTime, ReplConfigRandom ); if (ApiStatus != NO_ERROR) { goto Cleanup; } } ReportStatus( SERVICE_START_PENDING, NO_ERROR, REPL_WAIT_HINT, 3 ); // checkpoint // ReplChangeRole assumes caller has exclusive lock on ReplConfigLock. ACQUIRE_LOCK( ReplConfigLock ); LockedConfigData = TRUE; // // Change the role to the one. This is where most of the work gets done, // like starting other threads and so on. This is also where ReplConfigRole // gets set. Also, the RPC server will be started or stopped as necessary. // Last and not least, ReplChngRole() will inform the service controller. // NOTE: ReplChangeRole assumes caller has exclusive lock on ReplConfigLock. // ApiStatus = ReplChangeRole( NewRole ); if (ApiStatus != NO_ERROR) { goto Cleanup; } IF_DEBUG(REPL) { NetpKdPrint(( PREFIX_REPL "ReplMain: changed role OK.\n" )); } if (LockedConfigData) { RELEASE_LOCK( ReplConfigLock ); LockedConfigData = FALSE; } IF_DEBUG( REPL ) { NetpKdPrint(( PREFIX_REPL "ReplMain: exiting thread!!!!!!!!!!!!!!\n" )); } // // That's all, folks. When somebody decides to stop the service, // ReplControlRoutine will create the Stopper and Staller threads to do it. // return; Cleanup : NetpKdPrint(( PREFIX_REPL "ReplMain: forced to cleanup; shutting down svc...; status " FORMAT_API_STATUS "\n", ApiStatus )); ReplGlobalUninstallUicCode = ApiStatus; // So service ctrl gets told. if ( !LockedConfigData ) { // Get lock for ReplChangeRole(). ACQUIRE_LOCK( ReplConfigLock ); LockedConfigData = TRUE; } // // Make sure nothing is left running... // // Change role back to stopped, and do all other cleanup. // NOTE: ReplChangeRole assumes caller has exclusive lock on ReplConfigLock. (VOID) ReplChangeRole( REPL_ROLE_STOPPED ); if (LockedConfigData) { RELEASE_LOCK( ReplConfigLock ); } ReplCleanup(); // Report status. This needs ReplGlobalServiceHandle one last time. ReportStatus( SERVICE_STOPPED, ReplGlobalUninstallUicCode, 0, // wait hint 0 ); // checkpoint // BUGBUG: Close ReplGlobalServiceHandle here someday? IF_DEBUG( MAJOR ) { NetpKdPrint(( PREFIX_REPL "**************************** ENDING REPL " "****************************\n" )); } return; } // ReplMain
/* service_main */ static VOID WINAPI service_main(DWORD argc, LPTSTR *argv) { config_t conf; void* net; void* threads; void* pipe; h_service = RegisterServiceCtrlHandler(LDMSVC_SERVICE_NAME, handler); if(h_service == NULL) { return; } set_state1(SERVICE_START_PENDING); // SERVICE_START_PENDING // open the heap if(!heap_start()) { dout("Failed to create the heap\n"); set_state2(SERVICE_STOPPED, 1); return; } // parse configuration if(!config_parse_args(&conf, argc, argv)) { heap_stop(); set_state2(SERVICE_STOPPED, 1); return; } if(0) { dout(va("PORT: %u\n", conf.port)); dout(va("PIPE: %s\n", conf.pipe)); dout(va("MAXC: %u\n", conf.maxconn)); } // open network if((net = net_start()) == NULL) { heap_stop(); set_state2(SERVICE_STOPPED, 1); return; } // open the pipe if((pipe = pipe_start(conf.pipe)) == NULL) { net_stop(net); heap_stop(); set_state2(SERVICE_STOPPED, 1); return; } // connect the pipe if(!pipe_open(pipe)) { pipe_stop(pipe); net_stop(net); heap_stop(); set_state2(SERVICE_STOPPED, 1); return; } // start threads if((threads = threads_start(net, pipe, conf.maxconn)) == NULL) { pipe_stop(pipe); net_stop(net); heap_stop(); set_state2(SERVICE_STOPPED, 1); return; } set_state1(SERVICE_RUNNING); // SERVICE_RUNNING while(svc_state == SERVICE_RUNNING) { if(!net_is_ready(net)) { net_bind(net, NULL, conf.port); } if(!threads_think(threads)) { break; } Sleep(1); } set_state1(SERVICE_STOP_PENDING); // SERVICE_STOP_PENDING // close everything here threads_stop(threads); pipe_stop(pipe); net_stop(net); heap_stop(); set_state2(SERVICE_STOPPED, 0); // SERVICE_STOPPED }