////////////////////////////////////////////////////////////////////// // NT Service Stub Code (For XYROOT ) ////////////////////////////////////////////////////////////////////// #include #include #include #include #include const int nBufferSize = 500; char pServiceName[nBufferSize+1]; char pExeFile[nBufferSize+1]; char pInitFile[nBufferSize+1]; char pLogFile[nBufferSize+1]; const int nMaxProcCount = 127; PROCESS_INFORMATION pProcInfo[nMaxProcCount]; SERVICE_STATUS serviceStatus; SERVICE_STATUS_HANDLE hServiceStatusHandle; VOID WINAPI XYNTServiceMain( DWORD dwArgc, LPTSTR *lpszArgv ); VOID WINAPI XYNTServiceHandler( DWORD fdwControl ); CRITICAL_SECTION myCS; void WriteLog(char* pMsg) { // write error or other information into log file ::EnterCriticalSection(&myCS); try { SYSTEMTIME oT; ::GetLocalTime(&oT); FILE* pLog = fopen(pLogFile,"a"); fprintf(pLog,"%02d/%02d/%04d, %02d:%02d:%02d\n %s\n",oT.wMonth,oT.wDay,oT.wYear,oT.wHour,oT.wMinute,oT.wSecond,pMsg); fclose(pLog); } catch(...) {} ::LeaveCriticalSection(&myCS); } ////////////////////////////////////////////////////////////////////// // // Configuration Data and Tables // SERVICE_TABLE_ENTRY DispatchTable[] = { {pServiceName, XYNTServiceMain}, {NULL, NULL} }; // helper functions BOOL StartProcess(int nIndex) { // start a process with given index STARTUPINFO startUpInfo = { sizeof(STARTUPINFO),NULL,"",NULL,0,0,0,0,0,0,0,STARTF_USESHOWWINDOW,0,0,NULL,0,0,0}; char pItem[nBufferSize+1]; sprintf(pItem,"Process%d\0",nIndex); char pCommandLine[nBufferSize+1]; GetPrivateProfileString(pItem,"CommandLine","",pCommandLine,nBufferSize,pInitFile); if(strlen(pCommandLine)>4) { char pWorkingDir[nBufferSize+1]; GetPrivateProfileString(pItem,"WorkingDir","",pWorkingDir,nBufferSize,pInitFile); char pUserName[nBufferSize+1]; GetPrivateProfileString(pItem,"UserName","",pUserName,nBufferSize,pInitFile); char pPassword[nBufferSize+1]; GetPrivateProfileString(pItem,"Password","",pPassword,nBufferSize,pInitFile); char pDomain[nBufferSize+1]; GetPrivateProfileString(pItem,"Domain","",pDomain,nBufferSize,pInitFile); BOOL bImpersonate = (::strlen(pUserName)>0&&::strlen(pPassword)>0); char pUserInterface[nBufferSize+1]; GetPrivateProfileString(pItem,"UserInterface","N",pUserInterface,nBufferSize,pInitFile); BOOL bUserInterface = (bImpersonate==FALSE)&&(pUserInterface[0]=='y'||pUserInterface[0]=='Y'||pUserInterface[0]=='1')?TRUE:FALSE; char CurrentDesktopName[512]; // set the correct desktop for the process to be started if(bUserInterface) { startUpInfo.wShowWindow = SW_SHOW; startUpInfo.lpDesktop = NULL; } else { HDESK hCurrentDesktop = GetThreadDesktop(GetCurrentThreadId()); DWORD len; GetUserObjectInformation(hCurrentDesktop,UOI_NAME,CurrentDesktopName,MAX_PATH,&len); startUpInfo.wShowWindow = SW_HIDE; startUpInfo.lpDesktop = (bImpersonate==FALSE)?CurrentDesktopName:""; } if(bImpersonate==FALSE) { // create the process if(CreateProcess(NULL,pCommandLine,NULL,NULL,TRUE,NORMAL_PRIORITY_CLASS,NULL,strlen(pWorkingDir)==0?NULL:pWorkingDir,&startUpInfo,&pProcInfo[nIndex])) { char pPause[nBufferSize+1]; GetPrivateProfileString(pItem,"PauseStart","100",pPause,nBufferSize,pInitFile); Sleep(atoi(pPause)); return TRUE; } else { long nError = GetLastError(); char pTemp[121]; sprintf(pTemp,"Failed to start program '%s', error code = %d", pCommandLine, nError); WriteLog(pTemp); return FALSE; } } else { HANDLE hToken = NULL; if(LogonUser(pUserName,(::strlen(pDomain)==0)?".":pDomain,pPassword,LOGON32_LOGON_SERVICE,LOGON32_PROVIDER_DEFAULT,&hToken)) { if(CreateProcessAsUser(hToken,NULL,pCommandLine,NULL,NULL,TRUE,NORMAL_PRIORITY_CLASS,NULL,(strlen(pWorkingDir)==0)?NULL:pWorkingDir,&startUpInfo,&pProcInfo[nIndex])) { char pPause[nBufferSize+1]; GetPrivateProfileString(pItem,"PauseStart","100",pPause,nBufferSize,pInitFile); Sleep(atoi(pPause)); return TRUE; } long nError = GetLastError(); char pTemp[121]; sprintf(pTemp,"Failed to start program '%s' as user '%s', error code = %d", pCommandLine, pUserName, nError); WriteLog(pTemp); return FALSE; } long nError = GetLastError(); char pTemp[121]; sprintf(pTemp,"Failed to logon as user '%s', error code = %d", pUserName, nError); WriteLog(pTemp); return FALSE; } } else return FALSE; } void EndProcess(int nIndex) { // end a program started by the service if(pProcInfo[nIndex].hProcess) { char pItem[nBufferSize+1]; sprintf(pItem,"Process%d\0",nIndex); char pPause[nBufferSize+1]; GetPrivateProfileString(pItem,"PauseEnd","100",pPause,nBufferSize,pInitFile); int nPauseEnd = atoi(pPause); // post a WM_QUIT message first PostThreadMessage(pProcInfo[nIndex].dwThreadId,WM_QUIT,0,0); // sleep for a while so that the process has a chance to terminate itself ::Sleep(nPauseEnd>0?nPauseEnd:50); // terminate the process by force TerminateProcess(pProcInfo[nIndex].hProcess,0); try // close handles to avoid ERROR_NO_SYSTEM_RESOURCES { ::CloseHandle(pProcInfo[nIndex].hThread); ::CloseHandle(pProcInfo[nIndex].hProcess); } catch(...) {} pProcInfo[nIndex].hProcess = 0; pProcInfo[nIndex].hThread = 0; } } BOOL BounceProcess(char* pName, int nIndex) { // bounce the process with given index SC_HANDLE schSCManager = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS); if (schSCManager==0) { long nError = GetLastError(); char pTemp[121]; sprintf(pTemp, "OpenSCManager failed, error code = %d", nError); WriteLog(pTemp); } else { // open the service SC_HANDLE schService = OpenService( schSCManager, pName, SERVICE_ALL_ACCESS); if (schService==0) { long nError = GetLastError(); char pTemp[121]; sprintf(pTemp, "OpenService failed, error code = %d", nError); WriteLog(pTemp); } else { // call ControlService to invoke handler SERVICE_STATUS status; if(nIndex>=0&&nIndex<128) { if(ControlService(schService,(nIndex|0x80),&status)) { CloseServiceHandle(schService); CloseServiceHandle(schSCManager); return TRUE; } long nError = GetLastError(); char pTemp[121]; sprintf(pTemp, "ControlService failed, error code = %d", nError); WriteLog(pTemp); } else { char pTemp[121]; sprintf(pTemp, "Invalid argument to BounceProcess: %d", nIndex); WriteLog(pTemp); } CloseServiceHandle(schService); } CloseServiceHandle(schSCManager); } return FALSE; } BOOL KillService(char* pName) { // kill service with given name SC_HANDLE schSCManager = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS); if (schSCManager==0) { long nError = GetLastError(); char pTemp[121]; sprintf(pTemp, "OpenSCManager failed, error code = %d", nError); WriteLog(pTemp); } else { // open the service SC_HANDLE schService = OpenService( schSCManager, pName, SERVICE_ALL_ACCESS); if (schService==0) { long nError = GetLastError(); char pTemp[121]; sprintf(pTemp, "OpenService failed, error code = %d", nError); WriteLog(pTemp); } else { // call ControlService to kill the given service SERVICE_STATUS status; if(ControlService(schService,SERVICE_CONTROL_STOP,&status)) { CloseServiceHandle(schService); CloseServiceHandle(schSCManager); return TRUE; } else { long nError = GetLastError(); char pTemp[121]; sprintf(pTemp, "ControlService failed, error code = %d", nError); WriteLog(pTemp); } CloseServiceHandle(schService); } CloseServiceHandle(schSCManager); } return FALSE; } BOOL RunService(char* pName, int nArg, char** pArg) { // run service with given name SC_HANDLE schSCManager = OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS); if (schSCManager==0) { long nError = GetLastError(); char pTemp[121]; sprintf(pTemp, "OpenSCManager failed, error code = %d", nError); WriteLog(pTemp); } else { // open the service SC_HANDLE schService = OpenService( schSCManager, pName, SERVICE_ALL_ACCESS); if (schService==0) { long nError = GetLastError(); char pTemp[121]; sprintf(pTemp, "OpenService failed, error code = %d", nError); WriteLog(pTemp); } else { // call StartService to run the service if(StartService(schService,nArg,(const char**)pArg)) { CloseServiceHandle(schService); CloseServiceHandle(schSCManager); return TRUE; } else { long nError = GetLastError(); char pTemp[121]; sprintf(pTemp, "StartService failed, error code = %d", nError); WriteLog(pTemp); } CloseServiceHandle(schService); } CloseServiceHandle(schSCManager); } return FALSE; } ////////////////////////////////////////////////////////////////////// // // This routine gets used to start your service // VOID WINAPI XYNTServiceMain( DWORD dwArgc, LPTSTR *lpszArgv ) { DWORD status = 0; DWORD specificError = 0xfffffff; serviceStatus.dwServiceType = SERVICE_WIN32; serviceStatus.dwCurrentState = SERVICE_START_PENDING; serviceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN | SERVICE_ACCEPT_PAUSE_CONTINUE; serviceStatus.dwWin32ExitCode = 0; serviceStatus.dwServiceSpecificExitCode = 0; serviceStatus.dwCheckPoint = 0; serviceStatus.dwWaitHint = 0; hServiceStatusHandle = RegisterServiceCtrlHandler(pServiceName, XYNTServiceHandler); if (hServiceStatusHandle==0) { long nError = GetLastError(); char pTemp[121]; sprintf(pTemp, "RegisterServiceCtrlHandler failed, error code = %d", nError); WriteLog(pTemp); return; } // Initialization complete - report running status serviceStatus.dwCurrentState = SERVICE_RUNNING; serviceStatus.dwCheckPoint = 0; serviceStatus.dwWaitHint = 0; if(!SetServiceStatus(hServiceStatusHandle, &serviceStatus)) { long nError = GetLastError(); char pTemp[121]; sprintf(pTemp, "SetServiceStatus failed, error code = %d", nError); WriteLog(pTemp); } for(int i=0;i=0;i--) { EndProcess(i); } if (!SetServiceStatus(hServiceStatusHandle, &serviceStatus)) { long nError = GetLastError(); char pTemp[121]; sprintf(pTemp, "SetServiceStatus failed, error code = %d", nError); WriteLog(pTemp); } } return; case SERVICE_CONTROL_PAUSE: serviceStatus.dwCurrentState = SERVICE_PAUSED; break; case SERVICE_CONTROL_CONTINUE: serviceStatus.dwCurrentState = SERVICE_RUNNING; break; case SERVICE_CONTROL_INTERROGATE: break; default: // bounce processes started by this service if(fdwControl>=128&&fdwControl<256) { int nIndex = fdwControl&0x7F; // bounce a single process if(nIndex>=0&&nIndex=0;i--) { EndProcess(i); } for(int i=0;i0) nCheckProcessSeconds = nCheckProcess*60; else { GetPrivateProfileString("Settings","CheckProcessSeconds","600",pCheckProcess, nBufferSize,pInitFile); nCheckProcessSeconds = atoi(pCheckProcess); } while(nCheckProcessSeconds>0) { ::Sleep(1000*nCheckProcessSeconds); for(int i=0;i4&&pModuleFile[dwSize-4]=='.') { sprintf(pExeFile,"%s",pModuleFile); pModuleFile[dwSize-4] = 0; sprintf(pInitFile,"%s.ini",pModuleFile); sprintf(pLogFile,"%s.log",pModuleFile); } else { printf("Invalid module file name: %s\r\n", pModuleFile); return; } WriteLog(pExeFile); WriteLog(pInitFile); WriteLog(pLogFile); // read service name from .ini file GetPrivateProfileString("Settings","ServiceName","XYNTService",pServiceName,nBufferSize,pInitFile); WriteLog(pServiceName); // uninstall service if switch is "-u" if(argc==2&&_stricmp("-u",argv[1])==0) { UnInstall(pServiceName); } // install service if switch is "-i" else if(argc==2&&_stricmp("-i",argv[1])==0) { Install(pExeFile, pServiceName); } // bounce service if switch is "-b" else if(argc==2&&_stricmp("-b",argv[1])==0) { KillService(pServiceName); RunService(pServiceName,0,NULL); } // bounce a specifc program if the index is supplied else if(argc==3&&_stricmp("-b",argv[1])==0) { int nIndex = atoi(argv[2]); if(BounceProcess(pServiceName, nIndex)) { char pTemp[121]; sprintf(pTemp, "Bounced process %d", nIndex); WriteLog(pTemp); } else { char pTemp[121]; sprintf(pTemp, "Failed to bounce process %d", nIndex); WriteLog(pTemp); } } // kill a service with given name else if(argc==3&&_stricmp("-k",argv[1])==0) { if(KillService(argv[2])) { char pTemp[121]; sprintf(pTemp, "Killed service %s", argv[2]); WriteLog(pTemp); } else { char pTemp[121]; sprintf(pTemp, "Failed to kill service %s", argv[2]); WriteLog(pTemp); } } // run a service with given name else if(argc>=3&&_stricmp("-r",argv[1])==0) { if(RunService(argv[2], argc>3?(argc-3):0,argc>3?(&(argv[3])):NULL)) { char pTemp[121]; sprintf(pTemp, "Ran service %s", argv[2]); WriteLog(pTemp); } else { char pTemp[121]; sprintf(pTemp, "Failed to run service %s", argv[2]); WriteLog(pTemp); } } // assume user is starting this service else { // start a worker thread to check for dead programs (and restart if necessary) if(_beginthread(WorkerProc, 0, NULL)==-1) { long nError = GetLastError(); char pTemp[121]; sprintf(pTemp, "_beginthread failed, error code = %d", nError); WriteLog(pTemp); } // pass dispatch table to service controller if(!StartServiceCtrlDispatcher(DispatchTable)) { long nError = GetLastError(); char pTemp[121]; sprintf(pTemp, "StartServiceCtrlDispatcher failed, error code = %d", nError); WriteLog(pTemp); } // you don't get here unless the service is shutdown } ::DeleteCriticalSection(&myCS); }