|
@@ -0,0 +1,563 @@
|
|
|
+/****************************** Module Header ******************************\
|
|
|
+* Module Name: ServiceBase.cpp
|
|
|
+* Project: CppWindowsService
|
|
|
+* Copyright (c) Microsoft Corporation.
|
|
|
+*
|
|
|
+* Provides a base class for a service that will exist as part of a service
|
|
|
+* application. CServiceBase must be derived from when creating a new service
|
|
|
+* class.
|
|
|
+*
|
|
|
+* This source is subject to the Microsoft Public License.
|
|
|
+* See http://www.microsoft.com/en-us/openness/resources/licenses.aspx#MPL.
|
|
|
+* All other rights reserved.
|
|
|
+*
|
|
|
+* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND,
|
|
|
+* EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED
|
|
|
+* WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.
|
|
|
+\***************************************************************************/
|
|
|
+
|
|
|
+#pragma region Includes
|
|
|
+#include "ServiceBase.h"
|
|
|
+#include <assert.h>
|
|
|
+#include <strsafe.h>
|
|
|
+#include <string>
|
|
|
+#pragma endregion
|
|
|
+
|
|
|
+
|
|
|
+#pragma region Static Members
|
|
|
+
|
|
|
+// Initialize the singleton service instance.
|
|
|
+CServiceBase *CServiceBase::s_service = NULL;
|
|
|
+
|
|
|
+
|
|
|
+//
|
|
|
+// FUNCTION: CServiceBase::Run(CServiceBase &)
|
|
|
+//
|
|
|
+// PURPOSE: Register the executable for a service with the Service Control
|
|
|
+// Manager (SCM). After you call Run(ServiceBase), the SCM issues a Start
|
|
|
+// command, which results in a call to the OnStart method in the service.
|
|
|
+// This method blocks until the service has stopped.
|
|
|
+//
|
|
|
+// PARAMETERS:
|
|
|
+// * service - the reference to a CServiceBase object. It will become the
|
|
|
+// singleton service instance of this service application.
|
|
|
+//
|
|
|
+// RETURN VALUE: If the function succeeds, the return value is TRUE. If the
|
|
|
+// function fails, the return value is FALSE. To get extended error
|
|
|
+// information, call GetLastError.
|
|
|
+//
|
|
|
+BOOL CServiceBase::Run(CServiceBase &service)
|
|
|
+{
|
|
|
+ s_service = &service;
|
|
|
+
|
|
|
+ SERVICE_TABLE_ENTRYA serviceTable[] =
|
|
|
+ {
|
|
|
+ { service.m_name, ServiceMain },
|
|
|
+ { NULL, NULL }
|
|
|
+ };
|
|
|
+
|
|
|
+ // Connects the main thread of a service process to the service control
|
|
|
+ // manager, which causes the thread to be the service control dispatcher
|
|
|
+ // thread for the calling process. This call returns when the service has
|
|
|
+ // stopped. The process should simply terminate when the call returns.
|
|
|
+ return StartServiceCtrlDispatcher(serviceTable);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+//
|
|
|
+// FUNCTION: CServiceBase::ServiceMain(DWORD, PWSTR *)
|
|
|
+//
|
|
|
+// PURPOSE: Entry point for the service. It registers the handler function
|
|
|
+// for the service and starts the service.
|
|
|
+//
|
|
|
+// PARAMETERS:
|
|
|
+// * dwArgc - number of command line arguments
|
|
|
+// * lpszArgv - array of command line arguments
|
|
|
+//
|
|
|
+void WINAPI CServiceBase::ServiceMain(DWORD dwArgc, PSTR *pszArgv)
|
|
|
+{
|
|
|
+ assert(s_service != NULL);
|
|
|
+
|
|
|
+ // Register the handler function for the service
|
|
|
+ s_service->m_statusHandle = RegisterServiceCtrlHandler(
|
|
|
+ s_service->m_name, ServiceCtrlHandler);
|
|
|
+ if (s_service->m_statusHandle == NULL)
|
|
|
+ {
|
|
|
+ throw GetLastError();
|
|
|
+ }
|
|
|
+
|
|
|
+ // Start the service.
|
|
|
+ s_service->Start(dwArgc, pszArgv);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+//
|
|
|
+// FUNCTION: CServiceBase::ServiceCtrlHandler(DWORD)
|
|
|
+//
|
|
|
+// PURPOSE: The function is called by the SCM whenever a control code is
|
|
|
+// sent to the service.
|
|
|
+//
|
|
|
+// PARAMETERS:
|
|
|
+// * dwCtrlCode - the control code. This parameter can be one of the
|
|
|
+// following values:
|
|
|
+//
|
|
|
+// SERVICE_CONTROL_CONTINUE
|
|
|
+// SERVICE_CONTROL_INTERROGATE
|
|
|
+// SERVICE_CONTROL_NETBINDADD
|
|
|
+// SERVICE_CONTROL_NETBINDDISABLE
|
|
|
+// SERVICE_CONTROL_NETBINDREMOVE
|
|
|
+// SERVICE_CONTROL_PARAMCHANGE
|
|
|
+// SERVICE_CONTROL_PAUSE
|
|
|
+// SERVICE_CONTROL_SHUTDOWN
|
|
|
+// SERVICE_CONTROL_STOP
|
|
|
+//
|
|
|
+// This parameter can also be a user-defined control code ranges from 128
|
|
|
+// to 255.
|
|
|
+//
|
|
|
+void WINAPI CServiceBase::ServiceCtrlHandler(DWORD dwCtrl)
|
|
|
+{
|
|
|
+ switch (dwCtrl)
|
|
|
+ {
|
|
|
+ case SERVICE_CONTROL_STOP: s_service->Stop(); break;
|
|
|
+ case SERVICE_CONTROL_PAUSE: s_service->Pause(); break;
|
|
|
+ case SERVICE_CONTROL_CONTINUE: s_service->Continue(); break;
|
|
|
+ case SERVICE_CONTROL_SHUTDOWN: s_service->Shutdown(); break;
|
|
|
+ case SERVICE_CONTROL_INTERROGATE: break;
|
|
|
+ default: break;
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+#pragma endregion
|
|
|
+
|
|
|
+
|
|
|
+#pragma region Service Constructor and Destructor
|
|
|
+
|
|
|
+//
|
|
|
+// FUNCTION: CServiceBase::CServiceBase(PWSTR, BOOL, BOOL, BOOL)
|
|
|
+//
|
|
|
+// PURPOSE: The constructor of CServiceBase. It initializes a new instance
|
|
|
+// of the CServiceBase class. The optional parameters (fCanStop,
|
|
|
+/// fCanShutdown and fCanPauseContinue) allow you to specify whether the
|
|
|
+// service can be stopped, paused and continued, or be notified when system
|
|
|
+// shutdown occurs.
|
|
|
+//
|
|
|
+// PARAMETERS:
|
|
|
+// * pszServiceName - the name of the service
|
|
|
+// * fCanStop - the service can be stopped
|
|
|
+// * fCanShutdown - the service is notified when system shutdown occurs
|
|
|
+// * fCanPauseContinue - the service can be paused and continued
|
|
|
+//
|
|
|
+CServiceBase::CServiceBase(PSTR pszServiceName,
|
|
|
+ BOOL fCanStop,
|
|
|
+ BOOL fCanShutdown,
|
|
|
+ BOOL fCanPauseContinue)
|
|
|
+{
|
|
|
+ // Service name must be a valid string and cannot be NULL.
|
|
|
+ m_name = (pszServiceName == NULL) ? "" : pszServiceName;
|
|
|
+
|
|
|
+ m_statusHandle = NULL;
|
|
|
+
|
|
|
+ // The service runs in its own process.
|
|
|
+ m_status.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
|
|
|
+
|
|
|
+ // The service is starting.
|
|
|
+ m_status.dwCurrentState = SERVICE_START_PENDING;
|
|
|
+
|
|
|
+ // The accepted commands of the service.
|
|
|
+ DWORD dwControlsAccepted = 0;
|
|
|
+ if (fCanStop)
|
|
|
+ dwControlsAccepted |= SERVICE_ACCEPT_STOP;
|
|
|
+ if (fCanShutdown)
|
|
|
+ dwControlsAccepted |= SERVICE_ACCEPT_SHUTDOWN;
|
|
|
+ if (fCanPauseContinue)
|
|
|
+ dwControlsAccepted |= SERVICE_ACCEPT_PAUSE_CONTINUE;
|
|
|
+ m_status.dwControlsAccepted = dwControlsAccepted;
|
|
|
+
|
|
|
+ m_status.dwWin32ExitCode = NO_ERROR;
|
|
|
+ m_status.dwServiceSpecificExitCode = 0;
|
|
|
+ m_status.dwCheckPoint = 0;
|
|
|
+ m_status.dwWaitHint = 0;
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+//
|
|
|
+// FUNCTION: CServiceBase::~CServiceBase()
|
|
|
+//
|
|
|
+// PURPOSE: The virtual destructor of CServiceBase.
|
|
|
+//
|
|
|
+CServiceBase::~CServiceBase(void)
|
|
|
+{
|
|
|
+}
|
|
|
+
|
|
|
+#pragma endregion
|
|
|
+
|
|
|
+
|
|
|
+#pragma region Service Start, Stop, Pause, Continue, and Shutdown
|
|
|
+
|
|
|
+//
|
|
|
+// FUNCTION: CServiceBase::Start(DWORD, PWSTR *)
|
|
|
+//
|
|
|
+// PURPOSE: The function starts the service. It calls the OnStart virtual
|
|
|
+// function in which you can specify the actions to take when the service
|
|
|
+// starts. If an error occurs during the startup, the error will be logged
|
|
|
+// in the Application event log, and the service will be stopped.
|
|
|
+//
|
|
|
+// PARAMETERS:
|
|
|
+// * dwArgc - number of command line arguments
|
|
|
+// * lpszArgv - array of command line arguments
|
|
|
+//
|
|
|
+void CServiceBase::Start(DWORD dwArgc, PSTR *pszArgv)
|
|
|
+{
|
|
|
+ try
|
|
|
+ {
|
|
|
+ // Tell SCM that the service is starting.
|
|
|
+ SetServiceStatus(SERVICE_START_PENDING);
|
|
|
+
|
|
|
+ // Perform service-specific initialization.
|
|
|
+ OnStart(dwArgc, pszArgv);
|
|
|
+
|
|
|
+ // Tell SCM that the service is started.
|
|
|
+ SetServiceStatus(SERVICE_RUNNING);
|
|
|
+ }
|
|
|
+ catch (DWORD dwError)
|
|
|
+ {
|
|
|
+ // Log the error.
|
|
|
+ WriteErrorLogEntry("Service Start", dwError);
|
|
|
+
|
|
|
+ // Set the service status to be stopped.
|
|
|
+ SetServiceStatus(SERVICE_STOPPED, dwError);
|
|
|
+ }
|
|
|
+ catch (...)
|
|
|
+ {
|
|
|
+ // Log the error.
|
|
|
+ WriteEventLogEntry("Service failed to start.", EVENTLOG_ERROR_TYPE);
|
|
|
+
|
|
|
+ // Set the service status to be stopped.
|
|
|
+ SetServiceStatus(SERVICE_STOPPED);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+//
|
|
|
+// FUNCTION: CServiceBase::OnStart(DWORD, PWSTR *)
|
|
|
+//
|
|
|
+// PURPOSE: When implemented in a derived class, executes when a Start
|
|
|
+// command is sent to the service by the SCM or when the operating system
|
|
|
+// starts (for a service that starts automatically). Specifies actions to
|
|
|
+// take when the service starts. Be sure to periodically call
|
|
|
+// CServiceBase::SetServiceStatus() with SERVICE_START_PENDING if the
|
|
|
+// procedure is going to take long time. You may also consider spawning a
|
|
|
+// new thread in OnStart to perform time-consuming initialization tasks.
|
|
|
+//
|
|
|
+// PARAMETERS:
|
|
|
+// * dwArgc - number of command line arguments
|
|
|
+// * lpszArgv - array of command line arguments
|
|
|
+//
|
|
|
+void CServiceBase::OnStart(DWORD dwArgc, PSTR *pszArgv)
|
|
|
+{
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+//
|
|
|
+// FUNCTION: CServiceBase::Stop()
|
|
|
+//
|
|
|
+// PURPOSE: The function stops the service. It calls the OnStop virtual
|
|
|
+// function in which you can specify the actions to take when the service
|
|
|
+// stops. If an error occurs, the error will be logged in the Application
|
|
|
+// event log, and the service will be restored to the original state.
|
|
|
+//
|
|
|
+void CServiceBase::Stop()
|
|
|
+{
|
|
|
+ DWORD dwOriginalState = m_status.dwCurrentState;
|
|
|
+ try
|
|
|
+ {
|
|
|
+ // Tell SCM that the service is stopping.
|
|
|
+ SetServiceStatus(SERVICE_STOP_PENDING);
|
|
|
+
|
|
|
+ // Perform service-specific stop operations.
|
|
|
+ OnStop();
|
|
|
+
|
|
|
+ // Tell SCM that the service is stopped.
|
|
|
+ SetServiceStatus(SERVICE_STOPPED);
|
|
|
+ }
|
|
|
+ catch (DWORD dwError)
|
|
|
+ {
|
|
|
+ // Log the error.
|
|
|
+ WriteErrorLogEntry("Service Stop", dwError);
|
|
|
+
|
|
|
+ // Set the orginal service status.
|
|
|
+ SetServiceStatus(dwOriginalState);
|
|
|
+ }
|
|
|
+ catch (...)
|
|
|
+ {
|
|
|
+ // Log the error.
|
|
|
+ WriteEventLogEntry("Service failed to stop.", EVENTLOG_ERROR_TYPE);
|
|
|
+
|
|
|
+ // Set the orginal service status.
|
|
|
+ SetServiceStatus(dwOriginalState);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+//
|
|
|
+// FUNCTION: CServiceBase::OnStop()
|
|
|
+//
|
|
|
+// PURPOSE: When implemented in a derived class, executes when a Stop
|
|
|
+// command is sent to the service by the SCM. Specifies actions to take
|
|
|
+// when a service stops running. Be sure to periodically call
|
|
|
+// CServiceBase::SetServiceStatus() with SERVICE_STOP_PENDING if the
|
|
|
+// procedure is going to take long time.
|
|
|
+//
|
|
|
+void CServiceBase::OnStop()
|
|
|
+{
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+//
|
|
|
+// FUNCTION: CServiceBase::Pause()
|
|
|
+//
|
|
|
+// PURPOSE: The function pauses the service if the service supports pause
|
|
|
+// and continue. It calls the OnPause virtual function in which you can
|
|
|
+// specify the actions to take when the service pauses. If an error occurs,
|
|
|
+// the error will be logged in the Application event log, and the service
|
|
|
+// will become running.
|
|
|
+//
|
|
|
+void CServiceBase::Pause()
|
|
|
+{
|
|
|
+ try
|
|
|
+ {
|
|
|
+ // Tell SCM that the service is pausing.
|
|
|
+ SetServiceStatus(SERVICE_PAUSE_PENDING);
|
|
|
+
|
|
|
+ // Perform service-specific pause operations.
|
|
|
+ OnPause();
|
|
|
+
|
|
|
+ // Tell SCM that the service is paused.
|
|
|
+ SetServiceStatus(SERVICE_PAUSED);
|
|
|
+ }
|
|
|
+ catch (DWORD dwError)
|
|
|
+ {
|
|
|
+ // Log the error.
|
|
|
+ WriteErrorLogEntry("Service Pause", dwError);
|
|
|
+
|
|
|
+ // Tell SCM that the service is still running.
|
|
|
+ SetServiceStatus(SERVICE_RUNNING);
|
|
|
+ }
|
|
|
+ catch (...)
|
|
|
+ {
|
|
|
+ // Log the error.
|
|
|
+ WriteEventLogEntry("Service failed to pause.", EVENTLOG_ERROR_TYPE);
|
|
|
+
|
|
|
+ // Tell SCM that the service is still running.
|
|
|
+ SetServiceStatus(SERVICE_RUNNING);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+//
|
|
|
+// FUNCTION: CServiceBase::OnPause()
|
|
|
+//
|
|
|
+// PURPOSE: When implemented in a derived class, executes when a Pause
|
|
|
+// command is sent to the service by the SCM. Specifies actions to take
|
|
|
+// when a service pauses.
|
|
|
+//
|
|
|
+void CServiceBase::OnPause()
|
|
|
+{
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+//
|
|
|
+// FUNCTION: CServiceBase::Continue()
|
|
|
+//
|
|
|
+// PURPOSE: The function resumes normal functioning after being paused if
|
|
|
+// the service supports pause and continue. It calls the OnContinue virtual
|
|
|
+// function in which you can specify the actions to take when the service
|
|
|
+// continues. If an error occurs, the error will be logged in the
|
|
|
+// Application event log, and the service will still be paused.
|
|
|
+//
|
|
|
+void CServiceBase::Continue()
|
|
|
+{
|
|
|
+ try
|
|
|
+ {
|
|
|
+ // Tell SCM that the service is resuming.
|
|
|
+ SetServiceStatus(SERVICE_CONTINUE_PENDING);
|
|
|
+
|
|
|
+ // Perform service-specific continue operations.
|
|
|
+ OnContinue();
|
|
|
+
|
|
|
+ // Tell SCM that the service is running.
|
|
|
+ SetServiceStatus(SERVICE_RUNNING);
|
|
|
+ }
|
|
|
+ catch (DWORD dwError)
|
|
|
+ {
|
|
|
+ // Log the error.
|
|
|
+ WriteErrorLogEntry("Service Continue", dwError);
|
|
|
+
|
|
|
+ // Tell SCM that the service is still paused.
|
|
|
+ SetServiceStatus(SERVICE_PAUSED);
|
|
|
+ }
|
|
|
+ catch (...)
|
|
|
+ {
|
|
|
+ // Log the error.
|
|
|
+ WriteEventLogEntry("Service failed to resume.", EVENTLOG_ERROR_TYPE);
|
|
|
+
|
|
|
+ // Tell SCM that the service is still paused.
|
|
|
+ SetServiceStatus(SERVICE_PAUSED);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+//
|
|
|
+// FUNCTION: CServiceBase::OnContinue()
|
|
|
+//
|
|
|
+// PURPOSE: When implemented in a derived class, OnContinue runs when a
|
|
|
+// Continue command is sent to the service by the SCM. Specifies actions to
|
|
|
+// take when a service resumes normal functioning after being paused.
|
|
|
+//
|
|
|
+void CServiceBase::OnContinue()
|
|
|
+{
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+//
|
|
|
+// FUNCTION: CServiceBase::Shutdown()
|
|
|
+//
|
|
|
+// PURPOSE: The function executes when the system is shutting down. It
|
|
|
+// calls the OnShutdown virtual function in which you can specify what
|
|
|
+// should occur immediately prior to the system shutting down. If an error
|
|
|
+// occurs, the error will be logged in the Application event log.
|
|
|
+//
|
|
|
+void CServiceBase::Shutdown()
|
|
|
+{
|
|
|
+ try
|
|
|
+ {
|
|
|
+ // Perform service-specific shutdown operations.
|
|
|
+ OnShutdown();
|
|
|
+
|
|
|
+ // Tell SCM that the service is stopped.
|
|
|
+ SetServiceStatus(SERVICE_STOPPED);
|
|
|
+ }
|
|
|
+ catch (DWORD dwError)
|
|
|
+ {
|
|
|
+ // Log the error.
|
|
|
+ WriteErrorLogEntry("Service Shutdown", dwError);
|
|
|
+ }
|
|
|
+ catch (...)
|
|
|
+ {
|
|
|
+ // Log the error.
|
|
|
+ WriteEventLogEntry("Service failed to shut down.", EVENTLOG_ERROR_TYPE);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+//
|
|
|
+// FUNCTION: CServiceBase::OnShutdown()
|
|
|
+//
|
|
|
+// PURPOSE: When implemented in a derived class, executes when the system
|
|
|
+// is shutting down. Specifies what should occur immediately prior to the
|
|
|
+// system shutting down.
|
|
|
+//
|
|
|
+void CServiceBase::OnShutdown()
|
|
|
+{
|
|
|
+}
|
|
|
+
|
|
|
+#pragma endregion
|
|
|
+
|
|
|
+
|
|
|
+#pragma region Helper Functions
|
|
|
+
|
|
|
+//
|
|
|
+// FUNCTION: CServiceBase::SetServiceStatus(DWORD, DWORD, DWORD)
|
|
|
+//
|
|
|
+// PURPOSE: The function sets the service status and reports the status to
|
|
|
+// the SCM.
|
|
|
+//
|
|
|
+// PARAMETERS:
|
|
|
+// * dwCurrentState - the state of the service
|
|
|
+// * dwWin32ExitCode - error code to report
|
|
|
+// * dwWaitHint - estimated time for pending operation, in milliseconds
|
|
|
+//
|
|
|
+void CServiceBase::SetServiceStatus(DWORD dwCurrentState,
|
|
|
+ DWORD dwWin32ExitCode,
|
|
|
+ DWORD dwWaitHint)
|
|
|
+{
|
|
|
+ static DWORD dwCheckPoint = 1;
|
|
|
+
|
|
|
+ // Fill in the SERVICE_STATUS structure of the service.
|
|
|
+
|
|
|
+ m_status.dwCurrentState = dwCurrentState;
|
|
|
+ m_status.dwWin32ExitCode = dwWin32ExitCode;
|
|
|
+ m_status.dwWaitHint = dwWaitHint;
|
|
|
+
|
|
|
+ m_status.dwCheckPoint =
|
|
|
+ ((dwCurrentState == SERVICE_RUNNING) ||
|
|
|
+ (dwCurrentState == SERVICE_STOPPED)) ?
|
|
|
+ 0 : dwCheckPoint++;
|
|
|
+
|
|
|
+ // Report the status of the service to the SCM.
|
|
|
+ ::SetServiceStatus(m_statusHandle, &m_status);
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+//
|
|
|
+// FUNCTION: CServiceBase::WriteEventLogEntry(PWSTR, WORD)
|
|
|
+//
|
|
|
+// PURPOSE: Log a message to the Application event log.
|
|
|
+//
|
|
|
+// PARAMETERS:
|
|
|
+// * pszMessage - string message to be logged.
|
|
|
+// * wType - the type of event to be logged. The parameter can be one of
|
|
|
+// the following values.
|
|
|
+//
|
|
|
+// EVENTLOG_SUCCESS
|
|
|
+// EVENTLOG_AUDIT_FAILURE
|
|
|
+// EVENTLOG_AUDIT_SUCCESS
|
|
|
+// EVENTLOG_ERROR_TYPE
|
|
|
+// EVENTLOG_INFORMATION_TYPE
|
|
|
+// EVENTLOG_WARNING_TYPE
|
|
|
+//
|
|
|
+void CServiceBase::WriteEventLogEntry(PSTR pszMessage, WORD wType)
|
|
|
+{
|
|
|
+ HANDLE hEventSource = NULL;
|
|
|
+ LPCSTR lpszStrings[2] = { NULL, NULL };
|
|
|
+
|
|
|
+ hEventSource = RegisterEventSource(NULL, m_name);
|
|
|
+ if (hEventSource)
|
|
|
+ {
|
|
|
+ lpszStrings[0] = m_name;
|
|
|
+ lpszStrings[1] = pszMessage;
|
|
|
+
|
|
|
+ ReportEvent(hEventSource, // Event log handle
|
|
|
+ wType, // Event type
|
|
|
+ 0, // Event category
|
|
|
+ 0, // 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);
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
+
|
|
|
+//
|
|
|
+// FUNCTION: CServiceBase::WriteErrorLogEntry(PWSTR, DWORD)
|
|
|
+//
|
|
|
+// PURPOSE: Log an error message to the Application event log.
|
|
|
+//
|
|
|
+// PARAMETERS:
|
|
|
+// * pszFunction - the function that gives the error
|
|
|
+// * dwError - the error code
|
|
|
+//
|
|
|
+void CServiceBase::WriteErrorLogEntry(PSTR pszFunction, DWORD dwError)
|
|
|
+{
|
|
|
+ char szMessage[260];
|
|
|
+ StringCchPrintf(szMessage, ARRAYSIZE(szMessage),
|
|
|
+ "%s failed w/err 0x%08lx", pszFunction, dwError);
|
|
|
+ WriteEventLogEntry(szMessage, EVENTLOG_ERROR_TYPE);
|
|
|
+}
|
|
|
+
|
|
|
+#pragma endregion
|