/* * The ServiceMain function to start service. */ VOID WINAPI ServiceMain (DWORD argc, LPTSTR argv[]) { SECURITY_ATTRIBUTES SecurityAttributes; DWORD dwThreadId; /* * Input Arguments to function startup */ DWORD ArgCount = 0; LPTSTR *ArgArray = NULL; TCHAR szRegKey[512]; TCHAR szValue[128]; DWORD nSize; HKEY hParamKey = NULL; /* To read startup parameters */ 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 contorl agent */ /* * Read registry parameter */ ArgCount = 1; /* * Create Registry Key path */ _snprintf (szRegKey, sizeof(szRegKey), "%s%s\\%s", _T ("SYSTEM\\CurrentControlSet\\Services\\"), app_name, "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 = (LPTSTR *) malloc (sizeof (LPTSTR) * ArgCount); /* * Copy first argument */ ArgArray[0] = _tcsdup (argv[0]); for (i = 1; i <= TotalParams; i++) { /* * Create Subkey value name */ _snprintf (szRegKey, sizeof(szRegKey), "%s%d", "Param", i); /* * Set size */ nSize = 128; RegQueryValueEx (hParamKey, szRegKey, 0, NULL, (LPBYTE) & szValue, &nSize); ArgArray[i] = _tcsdup (szValue); } } } RegCloseKey (hParamKey); } if (ArgCount == 1) { /* * No statup agrs are given */ ThreadInputParams.Argc = argc; ThreadInputParams.Argv = argv; } else { ThreadInputParams.Argc = ArgCount; ThreadInputParams.Argv = ArgArray; } /* * Register Service Control Handler */ hServiceStatus = RegisterServiceCtrlHandler (app_name, 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); /* * Spin of worker thread, which does 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, &dwThreadId); if (hServiceThread == NULL) { WriteToEventLog (EVENTLOG_ERROR_TYPE, _T ("Couldn't start worker thread")); LEAVE; } /* * Set Service Status to Running */ UpdateServiceStatus (SERVICE_RUNNING, NO_ERROR, SCM_WAIT_INTERVAL); /* * Wait for termination event and worker thread to * * spin down. */ WaitForSingleObject (hServiceThread, INFINITE); } FINALLY { /* * Release resources */ UpdateServiceStatus (SERVICE_STOPPED, NO_ERROR, SCM_WAIT_INTERVAL); if (hServiceThread) CloseHandle (hServiceThread); FreeSecurityAttributes (&SecurityAttributes); /* * Delete allocated argument list */ if (ArgCount > 1 && ArgArray != NULL) { /* * Delete all strings */ for (i = 0; i < ArgCount; i++) { free (ArgArray[i]); } free (ArgArray); } } }
/* * 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); } } }
void SvcInit(DWORD dwArgc, LPTSTR* lpszArgv) { SECURITY_ATTRIBUTES securityAttributes; if (!GetSecurityAttributes(securityAttributes)) { ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0); return; } HANDLE pipe = CreateNamedPipeA( "\\\\.\\pipe\\TagServicePipe", PIPE_ACCESS_DUPLEX, PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE | PIPE_WAIT | PIPE_REJECT_REMOTE_CLIENTS, PIPE_UNLIMITED_INSTANCES, 4096, 4096, 50, &securityAttributes); if (pipe == INVALID_HANDLE_VALUE) { SvcReportWinFuncError(TEXT("CreateNamedPipeA")); FreeSecurityAttributes(securityAttributes); ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0); return; } ghSvcStopEvent = CreateEvent(nullptr, TRUE, FALSE, nullptr); if (ghSvcStopEvent == nullptr) { SvcReportWinFuncError(TEXT("CreateEvent")); FreeSecurityAttributes(securityAttributes); CloseHandle(pipe); ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0); return; } SvcReportInfo(TEXT("Service running")); ReportSvcStatus(SERVICE_RUNNING, NO_ERROR, 0); while (WaitForSingleObject(ghSvcStopEvent, 0) == WAIT_TIMEOUT) { if (ConnectNamedPipe(pipe, nullptr)) { //SvcReportInfo(TEXT("Connected pipe")); char buffer[4096]; DWORD bytesRead; if (ReadFile(pipe, buffer, 4096, &bytesRead, nullptr)) { for (unsigned int i = 0; i < bytesRead / 2; ++i) { char temp = buffer[i]; buffer[i] = buffer[bytesRead - i - 1]; buffer[bytesRead - i - 1] = temp; } DWORD bytesWritten; WriteFile(pipe, buffer, bytesRead, &bytesWritten, nullptr); } FlushFileBuffers(pipe); DisconnectNamedPipe(pipe); } } FreeSecurityAttributes(securityAttributes); CloseHandle(pipe); ReportSvcStatus(SERVICE_STOPPED, NO_ERROR, 0); }