From 7fe114ed0f55c2809b00e5ec67ad7a65732625ed Mon Sep 17 00:00:00 2001 From: Fish <> Date: Thu, 24 Apr 2008 07:41:24 +0000 Subject: [PATCH] Add TestService to use with NeoStats Control Panel till I finish that. --- .gitattributes | 2 + src/win32/Gui/Form1.h | 17 ++ src/win32/Gui/Form1.resx | 3 + src/win32/Gui/NeoStats Control Panel.sln | 6 + src/win32/ServiceTest/ServiceTest.cpp | 328 +++++++++++++++++++++++ src/win32/ServiceTest/ServiceTest.vcproj | 193 +++++++++++++ 6 files changed, 549 insertions(+) create mode 100644 src/win32/ServiceTest/ServiceTest.cpp create mode 100644 src/win32/ServiceTest/ServiceTest.vcproj diff --git a/.gitattributes b/.gitattributes index 55f234fa..25166ff4 100644 --- a/.gitattributes +++ b/.gitattributes @@ -569,6 +569,8 @@ src/win32/Gui/resource.h -text src/win32/Gui/stdafx.cpp -text src/win32/Gui/stdafx.h -text src/win32/Rules.rules -text +src/win32/ServiceTest/ServiceTest.cpp -text +src/win32/ServiceTest/ServiceTest.vcproj -text src/win32/icon1.ico -text src/win32/neostats.bmp -text src/win32/neostats.conf eol=crlf diff --git a/src/win32/Gui/Form1.h b/src/win32/Gui/Form1.h index 2f5cd448..2e94f766 100644 --- a/src/win32/Gui/Form1.h +++ b/src/win32/Gui/Form1.h @@ -71,6 +71,7 @@ namespace NeoStatsControlPanel { private: System::Windows::Forms::ToolStripSeparator^ toolStripSeparator1; private: System::Windows::Forms::ToolStripMenuItem^ quitNeoStatsControlPanelToolStripMenuItem; private: System::Windows::Forms::ToolStripMenuItem^ logViewerToolStripMenuItem; + private: System::Diagnostics::Process^ process1; @@ -115,6 +116,7 @@ namespace NeoStatsControlPanel { this->toolStripSeparator1 = (gcnew System::Windows::Forms::ToolStripSeparator()); this->quitNeoStatsControlPanelToolStripMenuItem = (gcnew System::Windows::Forms::ToolStripMenuItem()); this->logViewerToolStripMenuItem = (gcnew System::Windows::Forms::ToolStripMenuItem()); + this->process1 = (gcnew System::Diagnostics::Process()); this->contextMenuStrip1->SuspendLayout(); (cli::safe_cast(this->performanceCounter1))->BeginInit(); (cli::safe_cast(this->performanceCounter2))->BeginInit(); @@ -286,6 +288,17 @@ namespace NeoStatsControlPanel { this->logViewerToolStripMenuItem->Size = System::Drawing::Size(77, 20); this->logViewerToolStripMenuItem->Text = L"Log Viewer"; // + // process1 + // + this->process1->StartInfo->Domain = L""; + this->process1->StartInfo->LoadUserProfile = false; + this->process1->StartInfo->Password = nullptr; + this->process1->StartInfo->StandardErrorEncoding = nullptr; + this->process1->StartInfo->StandardOutputEncoding = nullptr; + this->process1->StartInfo->UserName = L""; + this->process1->SynchronizingObject = this; + this->process1->Exited += gcnew System::EventHandler(this, &Form1::process1_Exited); + // // Form1 // this->AutoScaleDimensions = System::Drawing::SizeF(6, 13); @@ -390,6 +403,10 @@ private: System::Void startToolStripMenuItem_Click(System::Object^ sender, Syst MessageBox::Show(e->Message + ":\r\n" + e->InnerException->Message, "Error Starting Service"); } } +private: System::Void process1_Exited(System::Object^ sender, System::EventArgs^ e) { + System::Diagnostics::Debug::WriteLine(this->process1->ExitCode); + } + }; } diff --git a/src/win32/Gui/Form1.resx b/src/win32/Gui/Form1.resx index 87081b52..f42901fd 100644 --- a/src/win32/Gui/Form1.resx +++ b/src/win32/Gui/Form1.resx @@ -156,6 +156,9 @@ 17, 64 + + 132, 64 + True diff --git a/src/win32/Gui/NeoStats Control Panel.sln b/src/win32/Gui/NeoStats Control Panel.sln index 075eb974..17775619 100644 --- a/src/win32/Gui/NeoStats Control Panel.sln +++ b/src/win32/Gui/NeoStats Control Panel.sln @@ -3,6 +3,8 @@ Microsoft Visual Studio Solution File, Format Version 10.00 # Visual C++ Express 2008 Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "NeoStats Control Panel", "NeoStats Control Panel.vcproj", "{FACB5498-CC3E-415A-96E5-91737F986A52}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ServiceTest", "..\ServiceTest\ServiceTest.vcproj", "{9504558B-6EF4-4ECE-AA2B-00C1AD9C5F4C}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -13,6 +15,10 @@ Global {FACB5498-CC3E-415A-96E5-91737F986A52}.Debug|Win32.Build.0 = Debug|Win32 {FACB5498-CC3E-415A-96E5-91737F986A52}.Release|Win32.ActiveCfg = Release|Win32 {FACB5498-CC3E-415A-96E5-91737F986A52}.Release|Win32.Build.0 = Release|Win32 + {9504558B-6EF4-4ECE-AA2B-00C1AD9C5F4C}.Debug|Win32.ActiveCfg = Debug|Win32 + {9504558B-6EF4-4ECE-AA2B-00C1AD9C5F4C}.Debug|Win32.Build.0 = Debug|Win32 + {9504558B-6EF4-4ECE-AA2B-00C1AD9C5F4C}.Release|Win32.ActiveCfg = Release|Win32 + {9504558B-6EF4-4ECE-AA2B-00C1AD9C5F4C}.Release|Win32.Build.0 = Release|Win32 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/src/win32/ServiceTest/ServiceTest.cpp b/src/win32/ServiceTest/ServiceTest.cpp new file mode 100644 index 00000000..267647a0 --- /dev/null +++ b/src/win32/ServiceTest/ServiceTest.cpp @@ -0,0 +1,328 @@ +#include +#include +#include + +#define SVCNAME TEXT("SvcName") + +SERVICE_STATUS gSvcStatus; +SERVICE_STATUS_HANDLE gSvcStatusHandle; +HANDLE ghSvcStopEvent = NULL; + +VOID SvcInstall(void); +VOID WINAPI SvcCtrlHandler( DWORD ); +VOID WINAPI SvcMain( DWORD, LPTSTR * ); + +VOID ReportSvcStatus( DWORD, DWORD, DWORD ); +VOID SvcInit( DWORD, LPTSTR * ); +VOID SvcReportEvent( LPTSTR ); + +// +// Purpose: +// Entry point for the process +// +// Parameters: +// None +// +// Return value: +// None +// +void __cdecl _tmain(int argc, TCHAR *argv[]) +{ + // If command-line parameter is "install", install the service. + // Otherwise, the service is probably being started by the SCM. + + if( lstrcmpi( argv[1], TEXT("install")) == 0 ) + { + SvcInstall(); + return; + } + + // TO_DO: Add any additional services for the process to this table. + SERVICE_TABLE_ENTRY DispatchTable[] = + { + { SVCNAME, (LPSERVICE_MAIN_FUNCTION) SvcMain }, + { NULL, NULL } + }; + + // This call returns when the service has stopped. + // The process should simply terminate when the call returns. + + if (!StartServiceCtrlDispatcher( DispatchTable )) + { + SvcReportEvent(TEXT("StartServiceCtrlDispatcher")); + } +} + +// +// Purpose: +// Installs a service in the SCM database +// +// Parameters: +// None +// +// Return value: +// None +// +VOID SvcInstall() +{ + SC_HANDLE schSCManager; + SC_HANDLE schService; + TCHAR szPath[MAX_PATH]; + + if( !GetModuleFileName( NULL, szPath, MAX_PATH ) ) + { + printf("Cannot install service (%d)\n", GetLastError()); + return; + } + + // Get a handle to the SCM database. + + schSCManager = OpenSCManager( + NULL, // local computer + NULL, // ServicesActive database + SC_MANAGER_ALL_ACCESS); // full access rights + + if (NULL == schSCManager) + { + printf("OpenSCManager failed (%d)\n", GetLastError()); + return; + } + + // Create the service + + schService = CreateService( + schSCManager, // SCM database + SVCNAME, // name of service + SVCNAME, // 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 + szPath, // path to service's binary + NULL, // no load ordering group + NULL, // no tag identifier + NULL, // no dependencies + NULL, // LocalSystem account + NULL); // no password + + if (schService == NULL) + { + printf("CreateService failed (%d)\n", GetLastError()); + CloseServiceHandle(schSCManager); + return; + } + else printf("Service installed successfully\n"); + + CloseServiceHandle(schService); + CloseServiceHandle(schSCManager); +} + +// +// Purpose: +// Entry point for the service +// +// Parameters: +// dwArgc - Number of arguments in the lpszArgv array +// lpszArgv - Array of strings. The first string is the name of +// the service and subsequent strings are passed by the process +// that called the StartService function to start the service. +// +// Return value: +// None. +// +VOID WINAPI SvcMain( DWORD dwArgc, LPTSTR *lpszArgv ) +{ + // Register the handler function for the service + + gSvcStatusHandle = RegisterServiceCtrlHandler( + SVCNAME, + SvcCtrlHandler); + + if( !gSvcStatusHandle ) + { + SvcReportEvent(TEXT("RegisterServiceCtrlHandler")); + return; + } + + // These SERVICE_STATUS members remain as set here + + gSvcStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; + gSvcStatus.dwServiceSpecificExitCode = 0; + + // Report initial status to the SCM + + ReportSvcStatus( SERVICE_START_PENDING, NO_ERROR, 3000 ); + + // Perform service-specific initialization and work. + + SvcInit( dwArgc, lpszArgv ); +} + +// +// Purpose: +// The service code +// +// Parameters: +// dwArgc - Number of arguments in the lpszArgv array +// lpszArgv - Array of strings. The first string is the name of +// the service and subsequent strings are passed by the process +// that called the StartService function to start the service. +// +// Return value: +// None +// +VOID SvcInit( DWORD dwArgc, LPTSTR *lpszArgv) +{ + // TO_DO: Declare and set any required variables. + // Be sure to periodically call ReportSvcStatus() with + // SERVICE_START_PENDING. If initialization fails, call + // ReportSvcStatus with SERVICE_STOPPED. + + // Create an event. The control handler function, SvcCtrlHandler, + // signals this event when it receives the stop control code. + + ghSvcStopEvent = CreateEvent( + NULL, // default security attributes + TRUE, // manual reset event + FALSE, // not signaled + NULL); // no name + + if ( ghSvcStopEvent == NULL) + { + ReportSvcStatus( SERVICE_STOPPED, NO_ERROR, 0 ); + return; + } + + // Report running status when initialization is complete. + + ReportSvcStatus( SERVICE_RUNNING, NO_ERROR, 0 ); + + // TO_DO: Perform work until service stops. + + while(1) + { + // Check whether to stop the service. + + WaitForSingleObject(ghSvcStopEvent, INFINITE); + + ReportSvcStatus( SERVICE_STOPPED, NO_ERROR, 0 ); + return; + } +} + +// +// Purpose: +// Sets the current service status and reports it to the SCM. +// +// Parameters: +// dwCurrentState - The current state (see SERVICE_STATUS) +// dwWin32ExitCode - The system error code +// dwWaitHint - Estimated time for pending operation, +// in milliseconds +// +// Return value: +// None +// +VOID ReportSvcStatus( DWORD dwCurrentState, + DWORD dwWin32ExitCode, + DWORD dwWaitHint) +{ + static DWORD dwCheckPoint = 1; + + // Fill in the SERVICE_STATUS structure. + + gSvcStatus.dwCurrentState = dwCurrentState; + gSvcStatus.dwWin32ExitCode = dwWin32ExitCode; + gSvcStatus.dwWaitHint = dwWaitHint; + + if (dwCurrentState == SERVICE_START_PENDING) + gSvcStatus.dwControlsAccepted = 0; + else gSvcStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP; + + if ( (dwCurrentState == SERVICE_RUNNING) || + (dwCurrentState == SERVICE_STOPPED) ) + gSvcStatus.dwCheckPoint = 0; + else gSvcStatus.dwCheckPoint = dwCheckPoint++; + + // Report the status of the service to the SCM. + SetServiceStatus( gSvcStatusHandle, &gSvcStatus ); +} + +// +// Purpose: +// Called by SCM whenever a control code is sent to the service +// using the ControlService function. +// +// Parameters: +// dwCtrl - control code +// +// Return value: +// None +// +VOID WINAPI SvcCtrlHandler( DWORD dwCtrl ) +{ + // Handle the requested control code. + + switch(dwCtrl) + { + case SERVICE_CONTROL_STOP: + ReportSvcStatus(SERVICE_STOP_PENDING, NO_ERROR, 0); + + // Signal the service to stop. + + SetEvent(ghSvcStopEvent); + + return; + + case SERVICE_CONTROL_INTERROGATE: + // Fall through to send current status. + break; + + default: + break; + } + + ReportSvcStatus(gSvcStatus.dwCurrentState, NO_ERROR, 0); +} + +// +// Purpose: +// Logs messages to the event log +// +// Parameters: +// szFunction - name of function that failed +// +// Return value: +// None +// +// Remarks: +// The service must have an entry in the Application event log. +// +VOID SvcReportEvent(LPTSTR szFunction) +{ + HANDLE hEventSource; + LPCTSTR lpszStrings[2]; + TCHAR Buffer[80]; + + hEventSource = RegisterEventSource(NULL, SVCNAME); + + if( NULL != hEventSource ) + { + StringCchPrintf(Buffer, 80, TEXT("%s failed with %d"), szFunction, GetLastError()); + + lpszStrings[0] = SVCNAME; + lpszStrings[1] = Buffer; + +// ReportEvent(hEventSource, // event log handle +// EVENTLOG_ERROR_TYPE, // event type +// 0, // event category +// SVC_ERROR, // event identifier +// NULL, // no security identifier +// 2, // size of lpszStrings array +// 0, // no binary data +// lpszStrings, // array of strings +// NULL); // no binary data + + DeregisterEventSource(hEventSource); + } +} \ No newline at end of file diff --git a/src/win32/ServiceTest/ServiceTest.vcproj b/src/win32/ServiceTest/ServiceTest.vcproj new file mode 100644 index 00000000..545dcc8b --- /dev/null +++ b/src/win32/ServiceTest/ServiceTest.vcproj @@ -0,0 +1,193 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +