Author | Message | Time |
---|---|---|
Mephisto | I've written my service code for my bot, but there's just one major problem. After the service is started and is running, it does nothing, at least from what I can tell. Perhaps someone can explain why it's not working based on the following code: Edit: Provided cleaner re-written code (same results occur though)... [code]#include "stdafx.h" #include "extern.h" #include "CModBot.h" #define _WIN32_WINNT 0x0502 #define WINVER 0x0502 // user-defined API CALLBACK functions VOID WINAPI theServiceMain(DWORD argc, LPSTR argv[]); VOID CALLBACK theServiceCtrlHandler(DWORD controlCode); // miscellaneous functions DWORD InitializeService(DWORD argc, LPSTR argv[]); BOOL InstallService(); BOOL UninstallService(); VOID SvcDebugOut(LPSTR String, DWORD Status); // API structures SERVICE_STATUS serviceStatus; SERVICE_STATUS_HANDLE serviceStatusHandle; // API HANDLEs SC_HANDLE serviceHandle = NULL; SC_HANDLE SCMHandle = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS); // miscellaneous data CModBot *pBot; DWORD __cdecl main(DWORD argc, LPSTR argv[]) { freopen("C:\Documents and Settings\Sargera\My Documents\Development\C\ModBot\Forcebot.log", "a", stdout); SERVICE_TABLE_ENTRY serviceTable[2]; memset(&serviceTable, 0, sizeof(serviceTable)); serviceTable[0].lpServiceName = "Forcebot"; serviceTable[0].lpServiceProc = (LPSERVICE_MAIN_FUNCTION)theServiceMain; StartServiceCtrlDispatcher(serviceTable); return 0; } VOID WINAPI theServiceMain(DWORD argc, LPSTR argv[]) { DWORD status = 0; memset(&serviceStatus, 0, sizeof(serviceStatus)); serviceStatus.dwServiceType = SERVICE_WIN32; serviceStatus.dwCurrentState = SERVICE_START_PENDING; serviceStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP|SERVICE_ACCEPT_SHUTDOWN; serviceStatusHandle = RegisterServiceCtrlHandler("Forcebot", (LPHANDLER_FUNCTION)theServiceCtrlHandler); if (serviceStatusHandle == (SERVICE_STATUS_HANDLE)0) { printf("Error registering service control handler!"); return; } status = InitializeService(argc, argv); if (status != 0) { serviceStatus.dwCurrentState = SERVICE_STOPPED; serviceStatus.dwCheckPoint = 0; serviceStatus.dwWaitHint = 0; serviceStatus.dwWin32ExitCode = status; serviceStatus.dwServiceSpecificExitCode = status; SetServiceStatus(serviceStatusHandle, &serviceStatus); return; } serviceStatus.dwCurrentState = SERVICE_RUNNING; serviceStatus.dwCheckPoint = 0; serviceStatus.dwWaitHint = 0; if (!SetServiceStatus (serviceStatusHandle, &serviceStatus)) { status = GetLastError(); SvcDebugOut("[MY_SERVICE] SetServiceStatus error %ld\n", status); } pBot->Main(NULL); // ... serviceStatus.dwCurrentState = SERVICE_STOPPED; SetServiceStatus(serviceStatusHandle, &serviceStatus); SvcDebugOut("[MY_SERVICE] Returning the Main Thread \n", 0); return; } VOID CALLBACK theServiceCtrlHandler(DWORD controlCode) { switch (controlCode) { case SERVICE_CONTROL_STOP: case SERVICE_CONTROL_SHUTDOWN: serviceStatus.dwCurrentState = SERVICE_STOP_PENDING; serviceStatus.dwWaitHint = 1000; SetServiceStatus(serviceStatusHandle, &serviceStatus); externData->shutdownBot = FALSE; serviceStatus.dwWaitHint = 0; serviceStatus.dwCurrentState = SERVICE_STOPPED; SetServiceStatus(serviceStatusHandle, &serviceStatus); SvcDebugOut("[MY_SERVICE] Leaving MyService \n", 0); return; } return; } DWORD InitializeService(DWORD argc, LPSTR argv[]) { argc; argv; pBot = new CModBot; return 0; } BOOL InstallService() { LPSTR filePath = new char[MAX_PATH]; if (!GetModuleFileName(NULL, filePath, MAX_PATH)) { printf("Error: Could not find exe file location! (%d)\n", GetLastError()); return FALSE; } serviceHandle = CreateService( SCMHandle, // SCManager database TEXT("Forcebot"), // name of service TEXT("Forcebot"), // service name to display SERVICE_ALL_ACCESS, // desired access SERVICE_WIN32_OWN_PROCESS, // service type SERVICE_DEMAND_START, // start type SERVICE_ERROR_NORMAL, // error control type filePath, // path to service's binary NULL, // no load ordering group NULL, // no tag identifier NULL, // no dependencies NULL, // LocalSystem account NULL // no password ); if (serviceHandle == NULL) { printf("Failed to install service! (%d)\n", GetLastError()); return FALSE; } else { printf("Successfully installed service Forcebot!\n"); CloseServiceHandle(serviceHandle); return TRUE; } } BOOL UninstallService() { serviceHandle = OpenService(SCMHandle, TEXT("Forcebot"), DELETE); if (serviceHandle == NULL) { printf("Could not open service! (%d)\n", GetLastError()); return FALSE; } if (!DeleteService(serviceHandle)) { printf("DeleteService failed (%d)\n", GetLastError()); return FALSE; } else printf("Deleted service Forcebot successfully!\n"); CloseServiceHandle(serviceHandle); return TRUE; } VOID SvcDebugOut(LPSTR String, DWORD Status) { LPSTR buf = new CHAR[1024]; if (strlen(String) < 1000) { sprintf(buf, String, Status); OutputDebugStringA(buf); } delete buf; }[/code] | November 27, 2004, 12:18 AM |
Adron | I suggest you put a breakpoint on pBot->Main(NULL); and make sure you get there. Then step into it and find out what it's doing.... Perhaps you should allow it interactive access to the desktop so you can see if it pops up some messagebox or something waiting for input? | November 27, 2004, 2:02 PM |
Mephisto | I've suspected it always failed on the call to StartServiceCtrlDispatcher(...), as when debugging when not a service after making that call main() just returns. Unless that call only succeeeds when running as a service. But interestingly enough, any form of output fails when running as a service (e.g. directing stdout to a file, opening a file stream for output, etc.). | November 27, 2004, 6:51 PM |
Adron | [quote author=Mephisto link=topic=9682.msg90262#msg90262 date=1101581472] I've suspected it always failed on the call to StartServiceCtrlDispatcher(...), as when debugging when not a service after making that call main() just returns. Unless that call only succeeeds when running as a service. But interestingly enough, any form of output fails when running as a service (e.g. directing stdout to a file, opening a file stream for output, etc.). [/quote] That call only succeeds when running as a service yes. Try debugging it when running as a service. You can use gflags to set up image file execution options so you get a debugger running as soon as it starts. Opening a file stream for output should work when running as a service, unless your system account lacks permissions to open the file. | November 27, 2004, 7:13 PM |
Skywing | Remember to set the interactive desktop flag if you are going to use the image debugger setting or your debugger will not be reachable. | November 27, 2004, 11:14 PM |
Mephisto | Alright, thanks. So there's nothing particuarily wrong with my code as it is? Just one of those minute bugs that causes everything to fail... | November 28, 2004, 9:14 AM |
Mephisto | I've pinpointed the problem to the call to SetServiceStatus using __asm int 3 breakpoints. However, the error is that the function is never returning (though interestingly enough the service starts successfully). I did try to comment out the call to SetServiceStatus but that caused the service to not start properly (obviously). Anyways, does anyone know why based on the above code why this would happen. | December 5, 2004, 12:16 AM |
Arta | hmm, you're not always calling SetServiceStatus in your handler. [quote] When a service receives a control request, the service's Handler function must call SetServiceStatus, even if the service's status did not change. A service can also use this function at any time and by any thread of the service to notify the service control manager of status changes. Examples of such unsolicited status updates include: - Checkpoint updates that occur when the service is in transition from one state to another. - Fatal error updates that occur when the service must stop due to a recoverable error. [/quote] | December 5, 2004, 7:56 AM |
Mephisto | Changed it after I posted my most recent reply; it always sets it now regardless of the control code. | December 5, 2004, 8:19 AM |