Click here to Skip to main content
65,938 articles
CodeProject is changing. Read more.
Articles
(untagged)

CNTService v1.06 - NT Service Framework

0.00/5 (No votes)
3 Mar 2000 3  
A class framework for developing NT services in MFC.
  • Download source files - 41 Kb
  • Introduction

    Welcome to CNTService, a collection of freeware MFC classes which provide a class framework for developing NT services in MFC.

    For detailed information about NT services, how to develop them and their relationship to other NT subsystems, I would suggest you thoroughly read the relevant documentation which comes with the Platform SDK.


    Features
    Usage
    History
    Class Framework Reference
    Planned Enhancements
    References
    Contacting the Author


    Features

    • Simple and clean C++ interface using virtual functions.
    • All the code is Unicode enabled and build configurations are provided.
    • All code compiles cleanly at the highest warning level of 4. This is the case with all of my other code on my web site as well.
    • Built in persistence functions which provide support similar to the build in MFC registry / ini functions.
    • A simple test service has been provided to help you get started developing your own NT services.
    • Comprehensive documentation is provided for all the classes.


    Usage

    • Bear in mind that these classes are very NT specific and none of this code will work correctly on 95/98. Both of these operating systems do provide some support for services but in a completely incompatible manner with NT services.
    • To use the classes in your code simple include ntserv.cpp in your project and #include ntserv.h in which ever of your modules needs to make calls to the class and derive your own service class from CNTService and override the necessary functions.
    • You will also need to include the compiled form of ntserv_msg.mc into your service executable's resource file. For further information on this check on the history details for v1.06 below.
    • To see the class in action, have a look at the code in InitInstance() in the module "app.cpp".
    • Your code will need to include MFC either statically or dynamically.


    History

    V1.0 (17 July 1998)
    • Initial public release.

    24 August 1998

    • Minor update to the demo program (app.cpp) to get rid of a compiler error.

    V1.01 (17 May 1999)

    • Addition of a number of ASSERTs statements to aid in debugging.
    • Fixed a bug in CNTEventLogSource::Report() as reported by Marin Kunev.
    • Fixed a compiler warning when compiled with VC 6.

    V1.02 (5 September 1999)

    • Addition of more ASSERT's statements to aid in debugging.

    V1.03 (3 October 1999)

    • Addition of GetProfileStringArray(), WriteProfileStringArray(), GetProfileBinary() and WriteProfileBinary() methods to the CNTService class.
    • Renamed some module names.

    V1.04 (5 October 1999)

    • Fixed a problem compiling the mc file for release and Unicode build configurations.
    • Fixed a level 4 warning when built using VC++ 6.

    V1.05 (10 October 1999)

    • Added support for the description field which services can have on Windows 2000.
    • Added accessor functions for the service name, friendly name and the description text.

    V1.06 (24 January 2000)

    • Modified the way the mc file is included into the TestSrv.exe sample service. The mc file is now compiled into an intermediate ntserv_msg.rc file which is #included into the final rc file testsrv.rc. This is done so that the testsrc.rc file can be edited by the resource designer inside Visual C++. In previous versions of CNTService, if your tried to edit the rc file (which was generated by the MC command line compiler), you would end up corrupting the file. If you are developing your own service using CNTService, then I would suggest you take this approach. What you need to do is create a resource script inside VC++, adding whatever resources you want to be in your services resources (e.g. version info, strings etc), then bring up the resource includes dialog and modify the Compile-Time directives to #include "ntserv_msg.rc" or your version of rc file which was generated by MC by compiling your .mc file. You should also check out the project settings in the demo service provided with CNTService to see how it handles compilation of the .mc file via a batch file (right mouse click on ntserv_msg.mc and select settings).


    Class Framework Reference

    The framework consists of the following classes:

    CNTServiceCommandLineInfo
    CNTEventLogSource
    CNTService
    CNTScmService
    CNTServiceControlManager
    CEventLogRecord
    CNTEventLog


    CNTServiceCommandLineInfo

    The CNTServiceCommandLineInfo class aids in parsing the command line at application startup. It is based almost exactly upon the way that the CCommandLineInfo class in MFC works.

    A service application will typically create a local instance of this class in your main/wmain or InitInstance() function. This object is then passed to CNTService::ParseCommandLine(), which fills the CNTServiceCommandLineInfo object. The CNTServiceCommandLineInfo object is then passed to CNTService::ProcessShellCommand() to handle the command-line arguments and flags.

    You can use this object to encapsulate the following command-line options and parameters:

    Command-line argument Command executed
    app /install Installs the service.
    app /remove | /uninstall Uninstalls the service.
    app /help Calls the virtual CNTService::OnHelp() function.

    Derive a new class from CCommandLineInfo to handle other flags and parameter values.


    CNTEventLogSource

    CNTEventLogSource provides a wrapper class for writing events to the NT event log. You could consider this as the server side to the Event log APIs.

    Functions this class provides include:

    CNTEventLogSource
    ~CNTEventLogSource
    operator HANDLE
    Attach
    Detach
    Register
    Report
    Deregister
    Install
    Uninstall


    CNTEventLogSource::CNTEventLogSource

    CNTEventLogSource();

    Remarks:
    This is the default constructor which just initialises all internal variables to a safe state.

    See Also:
    ~CNTEventLogSource


    CNTEventLogSource::~CNTEventLogSource

    ~CNTEventLogSource();

    Remarks:
    This is the standard destructor for the class. Internally it will call Deregister to ensure that any handle that is opened by this instance is closed.

    See Also:
    CNTEventLogSource, Deregister


    CNTEventLogSource::operator HANDLE

    operator HANDLE() const;

    Return Value:
    The underlying SDK handle representing this event log source.

    Remarks:
    This function exposes the underlying handle which the CNTEventLogSource class wraps. This function is provided for integration with legacy code which uses the handle directly.


    CNTEventLogSource::Attach

    BOOL Attach(HANDLE hEventSource);

    Return Value:
    TRUE if the function was successful, otherwise FALSE. To get extended error information, call GetLastError().

    Parameters:

    • hEventSource -- An SDK event log source handle returned from ::RegisterEventSource().

    Remarks:
    Use this member function to attach an existing SDK handle to a CNTEventLogSource.

    See Also:
    Detach


    CNTEventLogSource::Detach

    HANDLE Detach();

    Return Value:
    The SDK event log source handle.

    Remarks:
    Call this function to detach m_hEventLogSource from the CNTEventLogSource object and set m_hEventLogSource to NULL.

    See Also:
    Attach


    CNTEventLogSource::Register

    BOOL Register(LPCTSTR lpUNCServerName, LPCTSTR lpSourceName);

    Return Value:
    TRUE if the function was successful, otherwise FALSE. To get extended error information, call GetLastError().

    Parameters:

    • lpUNCServerName -- Pointer to a null-terminated string that specifies the Universal Naming Convention (UNC) name of the server on which this operation is to be performed. If this parameter is NULL, the operation is performed on the local computer.
    • lpSourceName -- Pointer to a null-terminated string that specifies the name of the source referenced by the returned handle. The source name must be a subkey of a logfile entry under the EventLog key in the registry. For example, WinApp is a valid source name if the registry has the following key:

      HKEY_LOCAL_MACHINE
        System
          CurrentControlSet
            Services
              EventLog
                Application
                  WinApp
                Security
                System
      

    Remarks:
    Use this function to register a source of logging into the event log. Internally the CNTService class contains a member variable (m_EventLogSource) of type CNTEventLogSource which calls this function in its construction.

    See Also:
    Deregister


    CNTEventLogSource::Report

    BOOL Report(WORD wType, WORD wCategory, DWORD dwEventID, PSID lpUserSid, WORD wNumStrings, DWORD dwDataSize, LPCTSTR* lpStrings, LPVOID lpRawData) const;
    BOOL Report(WORD wType, DWORD dwEventID, LPCTSTR lpszString) const;
    BOOL Report(WORD wType, DWORD dwEventID, LPCTSTR lpszString1, LPCTSTR lpszString2) const;
    BOOL Report(WORD wType, DWORD dwEventID, DWORD dwCode) const;

    Return Value:
    TRUE if the function was successful, otherwise FALSE. To get extended error information, call GetLastError().

    Parameters:

    • wType -- Specifies the type of event being logged. This parameter can be one of the following values:
      Value Meaning
      EVENTLOG_ERROR_TYPE Error event
      EVENTLOG_WARNING_TYPE Warning event
      EVENTLOG_INFORMATION_TYPE Information event
      EVENTLOG_AUDIT_SUCCESS Success Audit event
      EVENTLOG_AUDIT_FAILURE Failure Audit event
    • wCategory -- Specifies the event category. This is source-specific information; the category can have any value.
    • dwEventID -- Specifies the event. The event identifier specifies the message that goes with this event as an entry in the message file associated with the event source.
    • lpUserSid -- Pointer to the current user's security identifier. This parameter can be NULL if the security identifier is not required.
    • wNumStrings -- Specifies the number of strings in the array pointed to by the lpStrings parameter. A value of zero indicates that no strings are present.
    • dwDataSize -- Specifies the number of bytes of event-specific raw (binary) data to write to the log. If this parameter is zero, no event-specific data is present.
    • lpStrings -- Pointer to a buffer containing an array of null-terminated strings that are merged into the message from the message file before Event Viewer displays the string to the user. This parameter must be a valid pointer (or NULL), even if wNumStrings is zero.
    • lpRawData -- Pointer to the buffer containing the binary data. This parameter must be a valid pointer (or NULL), even if the dwDataSize parameter is zero.
    • lpszString, lpszString1, lpszString2 -- Specifies a single string which will be merged into the message from the message file before Event Viewer displays the string to the user.

    Remarks:
    These 4 versions of Report report a message to the event log. The 4 versions are provided to allow the programmer to use the one most suitable for the particular situation at hand.


    CNTEventLogSource::Deregister

    BOOL Deregister();

    Return Value:
    TRUE if the function was successful, otherwise FALSE. To get extended error information, call GetLastError().

    Remarks:
    Call this function to close the handle to the event log. This function will be called in the destructor in case you forget to close the handle yourself.

    See Also:
    Register


    CNTEventLogSource::Install

    static BOOL Install(LPCTSTR lpSourceName, LPCTSTR lpEventMessageFile, DWORD dwTypesSupported);

    Return Value:
    TRUE if the function was successful, otherwise FALSE. To get extended error information, call GetLastError().

    Parameters:

    • lpSourceName -- The name of the service which you want to install an event log source as.
    • lpEventMessageFile -- The location of the binary where the Message table resource can be located. This can be a standard exe or dll.
    • dwTypesSupported -- Specifies a bitmask of supported types. It can be one or more of the following values:
      • EVENTLOG_ERROR_TYPE
      • EVENTLOG_WARNING_TYPE
      • EVENTLOG_INFORMATION_TYPE
      • EVENTLOG_AUDIT_SUCCESS
      • EVENTLOG_AUDIT_FAILURE

    Remarks:
    Call this function to setup the necessary entries in the registry so that the Event Viewer can correctly locate the message file for messages displayed in the event log. This function is called as part of CNTService::Install() using appropriate values.

    See Also:
    Uninstall


    CNTEventLogSource::Uninstall

    static BOOL Uninstall(LPCTSTR lpSourceName);

    Return Value:
    TRUE if the function was successful, otherwise FALSE. To get extended error information, call GetLastError().

    Remarks:
    Call this function to remove the entries from the registry which were setup by the method Install().

    See Also:
    Install



    CNTService

    CNTService is the class which provides a C++ framework upon which you can develop your own MFC C++ based services. The class makes heavy use of virtual functions which your service class should override.

    Functions this class provides include:

    CNTService
    ~CNTService
    WriteProfileString
    WriteProfileInt
    WriteProfileBinary
    WriteProfileStringArray
    GetProfileString
    GetProfileInt
    GetProfileBinary
    GetProfileStringArray
    ParseCommandLine
    ProcessShellCommand
    ReportStatustoSCM
    RegisterCtrlHandler
    ServiceCtrlHandler
    ServiceMain
    OnStop
    OnPause
    OnContinue
    OnInterrogate
    OnShutdown
    OnUserDefinedRequest
    Run
    Install
    Uninstall
    Debug
    ShowHelp


    CNTService::CNTService

    CNTService(LPCTSTR lpszServiceName, LPCTSTR lpszDisplayName, DWORD dwControlsAccepted, LPCTSTR lpszDescription = NULL);

    Parameters:

    • lpszServiceName -- Pointer to a null-terminated string that is the internal name of the service.
    • lpszDisplayName -- Pointer to a null-terminated string that is to be used by user interface programs to identify this service.
    • dwControlsAccepted -- Specifies the control codes that the service will accept and process. Any or all of the following flags can be specified to enable the other control codes.
    • lpszDescription -- The textual description of the service. This appears in the new service's MMC snapin in Windows 2000 as the "Description" column. Using this value just means that administrators will see a comment associated with your service. The default value is NULL which will not insert a description into the registry.
      Value Meaning
      SERVICE_ACCEPT_STOP The service can be stopped. This enables the SERVICE_CONTROL_STOP value.
      SERVICE_ACCEPT_PAUSE_CONTINUE The service can be paused and continued. This enables the SERVICE_CONTROL_PAUSE and SERVICE_CONTROL_CONTINUE values.
      SERVICE_ACCEPT_SHUTDOWN The service is notified when system shutdown occurs. This enables the system to send a SERVICE_CONTROL_SHUTDOWN value to the service. The ControlService function cannot send this control code.

    Remarks:
    This is the standard constructor which initializes a number of internal variables based on the parameters sent in.

    See Also:
    ~CNTService


    CNTService::~CNTService

    ~CNTService();

    Remarks:
    Standard destructor for the class.

    See Also:
    CNTService


    CNTService::WriteProfileString

    BOOL WriteProfileString(LPCTSTR lpszSection, LPCTSTR lpszEntry, LPCTSTR lpszValue);

    Return Value:
    TRUE if successful; otherwise FALSE.

    Parameters:

    • lpszSection -- Points to a null-terminated string that specifies the section containing the entry. If the section does not exist, it is created. The name of the section is case independent; the string may be any combination of uppercase and lowercase letters.
    • lpszEntry -- Points to a null-terminated string that contains the entry into which the value is to be written. If the entry does not exist in the specified section, it is created.
    • lpszValue -- Points to the string to be written. If this parameter is NULL, the entry specified by the lpszEntry parameter is deleted.

    Remarks:
    Call this member function to write the specified string into the registry where Services are meant to store their configuration setting i.e. HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\ServiceName\Parameters.


    CNTService::WriteProfileInt

    BOOL WriteProfileInt(LPCTSTR lpszSection, LPCTSTR lpszEntry, int nValue);

    Return Value:
    TRUE if successful; otherwise FALSE.

    Parameters:

    • lpszSection -- Points to a null-terminated string that specifies the section containing the entry. If the section does not exist, it is created. The name of the section is case independent; the string may be any combination of uppercase and lowercase letters.
    • lpszEntry -- Points to a null-terminated string that contains the entry into which the value is to be written. If the entry does not exist in the specified section, it is created.
    • nValue -- Contains the value to be written.

    Remarks:
    Call this member function to write the specified value into the registry where Services are meant to store their configuration setting i.e. HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\ServiceName\Parameters.


    CNTService::WriteProfileBinary

    BOOL WriteProfileBinary(LPCTSTR lpszSection, LPCTSTR lpszEntry, LPBYTE pData, UINT nBytes);

    Return Value:
    TRUE if successful; otherwise FALSE.

    Parameters:

    • lpszSection -- Points to a null-terminated string that specifies the section containing the entry. If the section does not exist, it is created. The name of the section is case independent; the string may be any combination of uppercase and lowercase letters.
    • lpszEntry -- Points to a null-terminated string that contains the entry into which the value is to be written. If the entry does not exist in the specified section, it is created.
    • pData -- Points to the binary data to be written.
    • nBytes -- The size of "pData" in bytes.

    Remarks:
    Call this member function to write the specified binart data into the registry where Services are meant to store their configuration setting i.e. HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\ServiceName\Parameters.


    CNTService::GetProfileString

    CString GetProfileString(LPCTSTR lpszSection, LPCTSTR lpszEntry, LPCTSTR lpszDefault = NULL);

    Return Value:
    The return value is the string from the registry or lpszDefault if the string cannot be found. The maximum string length supported by the framework is _MAX_PATH. If lpszDefault is NULL, the return value is an empty string.

    Parameters:

    • lpszSection -- Points to a null-terminated string that specifies the section containing the entry.
    • lpszEntry -- Points to a null-terminated string that contains the entry into which the value is to be written. This value must not be NULL.
    • lpszDefault -- Points to the default string value for the given entry if the entry cannot be found in the registry.

    Remarks:
    Call this member function to retrieve the string associated with an entry within the specified section in the registry.


    CNTService::GetProfileInt

    UINT GetProfileInt(LPCTSTR lpszSection, LPCTSTR lpszEntry, int nDefault);

    Return Value:
    The integer value of the string that follows the specified entry if the function is successful. The return value is the value of the nDefault parameter if the function does not find the entry. The return value is 0 if the value that corresponds to the specified entry is not an integer.

    Parameters:

    • lpszSection -- Points to a null-terminated string that specifies the section containing the entry.
    • lpszEntry -- Points to a null-terminated string that contains the entry whose value is to be retrieved.
    • nDefault -- Specifies the default value to return if the framework cannot find the entry. This value can be an unsigned value in the range 0 through 65,535 or a signed value in the range -32,768 through 32,767.

    Remarks:
    Call this member function to retrieve the value of an integer from an entry within a specified section in the registry.

    This member function is not case sensitive, so the strings in the lpszSection and lpszEntry parameters may differ in case.


    CNTService::GetProfileBinary

    BOOL GetProfileBinary(LPCTSTR lpszSection, LPCTSTR lpszEntry, LPBYTE* ppData, UINT* pBytes);

    Return Value:
    TRUE if successful; otherwise FALSE.

    Parameters:

    • lpszSection -- Points to a null-terminated string that specifies the section containing the entry.
    • lpszEntry -- Points to a null-terminated string that contains the entry whose binary data is to be retrieved. This value must not be NULL.
    • ppData -- Upon successful return, this pointer will contain the binary data read from the registry.
    • nBytes -- Upon successful return, this pointer will contain the size of the binary data read from the registry.

    Remarks:
    Call this member function to set a binary value associated with an entry within the specified section in the registry. Internally the data is stored in the registry as a REG_BINARY value. Note that the caller of the function is responsible for freeing the memory associated with the data in ppData. This can be achieved using: delete [] *ppData.


    CNTService::GetProfileStringArray

    BOOL GetProfileStringArray(LPCTSTR lpszSection, LPCTSTR lpszEntry, CStringArray& array);

    Return Value:
    TRUE if successful; otherwise FALSE.

    Parameters:

    • lpszSection -- Points to a null-terminated string that specifies the section containing the entry.
    • lpszEntry -- Points to a null-terminated string that contains the entry whose binary data is to be retrieved. This value must not be NULL.
    • array -- Upon successful return this will contain the CStringArray.

    Remarks:
    Call this member function to retrieve a string array associated with an entry within the specified section in the registry. The value is stored as a MULTI_SZ string in the registry.


    CNTService::ParseCommandLine

    void ParseCommandLine(CNTServiceCommandLineInfo& rCmdInfo);

    Parameters:

    Remarks:
    Call this member function to parse the command line and send the parameters, one at a time, to CNTServiceCommandLineInfo::ParseParam().


    CNTService::ProcessShellCommand

    BOOL ProcessShellCommand(CNTServiceCommandLineInfo& rCmdInfo);

    Return Value:
    TRUE if the shell command is processed successfully otherwise FALSE.

    Parameters:

    Remarks:
    This member function is called by your InitInstance(), main or wmain to accept the parameters passed from the CNTServiceCommandLineInfo object identified by rCmdInfo, and perform the indicated action.

    The data members of the CNTServiceCommandLineInfo object, identified by CNTServiceCommandLineInfo::m_nShellCommand, are of the following enumerated type, which is defined within the CNTServiceCommandLineInfo class.

    enum {
       RunAsService,
       InstallService, 
       UninstallService,
       DebugService, 
       ShowServiceHelp, 
    };
    


    CNTService::ReportStatusToSCM

    BOOL ReportStatusToSCM();
    BOOL ReportStatusToSCM(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwServiceSpecificExitCode, DWORD dwCheckPoint, DWORD dwWaitHint);

    Return Value:
    TRUE if the SCM was notified successfully of this services state otherwise FALSE. To get extended error information, call GetLastError().

    Parameters:

    • dwCurrentState -- Indicates the current state of the service. One of the following values is specified:
      Value Meaning
      SERVICE_STOPPED The service is not running.
      SERVICE_START_PENDING The service is starting.
      SERVICE_STOP_PENDING The service is stopping.
      SERVICE_RUNNING The service is running.
      SERVICE_CONTINUE_PENDING The service continue is pending.
      SERVICE_PAUSE_PENDING The service pause is pending.
      SERVICE_PAUSED The service is paused.
    • dwWin32ExitCode -- Specifies an Win32 error code that the service uses to report an error that occurs when it is starting or stopping. To return an error code specific to the service, the service must set this value to ERROR_SERVICE_SPECIFIC_ERROR to indicate that the dwServiceSpecificExitCode member contains the error code. The service should set this value to NO_ERROR when it is running and on normal termination.
    • dwServiceSpecificExitCode -- Specifies a service specific error code that the service returns when an error occurs while the service is starting or stopping. This value is ignored unless the dwWin32ExitCode member is set to ERROR_SERVICE_SPECIFIC_ERROR.
    • dwCheckPoint -- Specifies a value that the service increments periodically to report its progress during a lengthy start, stop, pause, or continue operation. For example, the service should increment this value as it completes each step of its initialisation when it is starting up. The user interface program that invoked the operation on the service uses this value to track the progress of the service during a lengthy operation. This value is not valid and should be zero when the service does not have a start, stop, pause, or continue operation pending.
    • dwWaitHint -- Specifies an estimate of the amount of time, in milliseconds, that the service expects a pending start, stop, pause, or continue operation to take before the service makes its next call to the SetServiceStatus() function with either an incremented dwCheckPoint value or a change in dwCurrentState. If the amount of time specified by dwWaitHint passes, and dwCheckPoint has not been incremented, or dwCurrentState has not changed, the service control manager or service control program can assume that an error has occurred.

    Remarks:
    These two functions report the current state of the service back to the service control manager. The first versions uses the parameters specified and as well as updated the services own internal state will report it to the SCM. The second version uses the existing state of the service when reporting to the SCM.


    CNTService::RegisterCtrlHandler

    BOOL RegisterCtrlHandler();

    Return Value:
    TRUE if the Control handler for this service was successfully registered otherwise FALSE. To get extended error information, call GetLastError().

    Remarks:
    You would call this at the beginning of your derived classes ServiceMain to report to the SCM which function to callback on when making requests to the service. Internally when a request is made it will be routed to the appropriate virtual function.

    See Also:
    ServiceCtrlHandler


    CNTService::ServiceCtrlHandler

    virtual void WINAPI ServiceCtrlHandler(DWORD dwControl);

    Return Value:
    TRUE if successful; otherwise FALSE.

    Parameters:

    • dwControl -- Specifies the requested control code. This value can be one of the standard control codes in the following table:
      Value Meaning
      SERVICE_CONTROL_STOP Requests the service to stop.
      SERVICE_CONTROL_PAUSE Requests the service to pause.
      SERVICE_CONTROL_CONTINUE Requests the paused service to resume.
      SERVICE_CONTROL_INTERROGATE Requests the service to update immediately its current status information to the service control manager.
      SERVICE_CONTROL_SHUTDOWN Requests the service to perform cleanup tasks, because the system is shutting down.

      This value can also be a user-defined control code, as described in the following table:

      Value Meaning
      Range 128 to 255. The service defines the action associated with the control code. The hService handle must have SERVICE_USER_DEFINED_CONTROL access.

    Remarks:
    This function is called into by the SCM and internally it delegates to the appropriate virtual function. For example if a  SERVICE_CONTROL_STOP request arrives then this function will call the virtual OnStop() function. This function will not normally have to be overridden in your derived class. Please bear in mind that this function will be called in the context on the main thread on your service and not the thread in which your service does it main work (its ServiceMain() handler).


    CNTService::ServiceMain

    virtual void WINAPI ServiceMain(DWORD dwArgc, LPTSTR* lpszArgv);

    Return Value:
    TRUE if successful; otherwise FALSE.

    Parameters:

    • dwArgc -- Specifies the number of arguments in the lpszArgv array.
    • lpszArgv -- Pointer to an array of pointers that point to null-terminated argument strings. The first argument in the array is the name of the service, and subsequent arguments are any strings passed to the service by the process that called the CScmService::Start() function to start the service.

    Remarks:
    In your derived class you are responsible for writing your own ServiceMain() function for your service.

    When a service control program requests that a new service run, the SCM starts the service and sends a start request to the control dispatcher. The control dispatcher creates a new thread to execute the ServiceMain() function for the service.

    The ServiceMain() function should perform the following tasks:

    1. Call the RegisterServiceCtrlHandler() function immediately to register a handler function to handle control requests for the service.
    2. Perform initialization. If the execution time of the initialisation code is expected to be very short (less than one second), initialisation can be performed directly in ServiceMain().
    3. When initialization is complete, call SetServiceStatus(), specifying the SERVICE_RUNNING state in the SERVICE_STATUS structure.
    4. Perform the service tasks, or, if there are no pending tasks, return. Any change in the state of the service warrants a call to ReportStatusToSCM to report new status information.
    5. If an error occurs while the service is initializing or running, the service should call, specifying the SERVICE_STOP_PENDING state, if cleanup will be lengthy. Once cleanup is complete, call ReportStatusToSCM() from the last thread to terminate, specifying SERVICE_STOPPED in the SERVICE_STATUS structure. Be sure to set the dwServiceSpecificExitCode and dwWin32ExitCode members of the SERVICE_STATUS structure to identify the error.


    CNTService::OnStop

    virtual void OnStop();

    Remarks:
    This function will be called whenever a SERVICE_CONTROL_STOP request comes in from the SCM. Your derived class should do whatever is necessary to cause your service to stop.


    CNTService::OnPause

    virtual void OnPause();

    Remarks:
    This function will be called whenever a SERVICE_CONTROL_PAUSE request comes in from the SCM. Your derived class should do whatever is necessary to cause your service to pause.


    CNTService::OnContinue

    virtual void OnContinue();

    Remarks:
    This function will be called whenever a SERVICE_CONTROL_CONTINUE request comes in from the SCM. Your derived class should do whatever is necessary to cause your service to continue.


    CNTService::OnInterrogate

    virtual void OnInterrogate();

    Remarks:
    This function will be called whenever a SERVICE_CONTROL_INTERROGATE request comes in from the SCM. The default implementation just calls ReportStatusToSCM to inform the SCM.


    CNTService::OnShutdown

    virtual void OnShutdown();

    Remarks:
    This function will be called whenever a SERVICE_CONTROL_SHUTDOWN comes in from the SCM. Your derived class should do whatever is necessary to cause your service to shutdown.


    CNTService::OnUserDefinedRequest

    virtual void OnUserDefinedRequest(DWORD dwControl);

    Remarks:
    This function will be called whenever a user defined request comes in from the SCM. Your derived class should do whatever is appropriate for its service. In the example service provided, it simply changes the frequency of beeps emitted by the service.


    CNTService::Run

    virtual BOOL Run();

    Remarks:
    Calling this function will cause a service to start running. Internally it will set up an appropriate SERVICE_TABLE_ENTRY array and call StartServiceCtrlDispatcher to kick of the service. You would normally call this in your main, wmain or InitInstance. If you are using the CNTServiceCommandLineInfo class and ParseCommandLine() and ProcessShellCommand() member functions of CNTService then there is no need to call this function.


    CNTService::Install

    virtual BOOL Install();

    Remarks:
    This will install a service. Internally it will call into the SCM API to set this service up as an on demand service with no dependencies. In future versions of CNTService, virtual functions will be provided to allow more customisation in this area. It will also install the service so that it can report events to the event log as well as letting Event Viewer filter using the friendly name of the service. This function will be called internally by the CNTServiceCommandLineInfo if "-install" is specified on the command line.


    CNTService::Uninstall

    virtual BOOL Uninstall();

    Remarks:
    The is the corollary function of Install and will remove the service from the SCM database and remove it event log registry entries. Please bear in mind that once this is done, event viewer will no longer be able to correctly display any messages the service generated while it was installed. the CNTServiceCommandLineInfo if "-uninstall" or "-remove" is specified on the command line.


    CNTService::Debug

    virtual void Debug();

    Remarks:
    This will run a service without interacting with the SCM, in effect a "debug" mode. This helps when testing your application as it will stop the SCM from timing out your service as it is being debugged. Internally this function will just call the ServiceMain function of your class. Remember that in this case your service code will be running in the same thread as the main thread so it may mask problems which only arise when the code is executed as a real service. This function will be called internally by CNTServiceCommandLineInfo if "-debug" is specified on the command line.


    CNTService::ShowHelp

    virtual void ShowHelp();

    Remarks:
    This function will be called internally by CNTServiceCommandLineInfo if "-help" or "-?" is specified on the command line. It is up to you to either print some message to the console if you are developing a console mode service or display some helpful window if its a GUI app. The sample service simply displays a message using AfxMessageBox() as it was developed using the GUI subsystem.



    CNTScmService

    CNTScmService is a class which encapsulates a service as returned from the Service Control Manager, in effect a SC_HANDLE. An instance of a CNTScmService is usually acquired by a call to CNTServiceControlManager::Open. Once retrieved the class allows you to control the service, change its configuration and query a service's state.

    Functions this class provides include:

    CNTScmService
    ~CNTScmService
    Close
    operator SC_HANDLE
    Attach
    Detach
    ChangeConfig
    Control
    Stop
    Pause
    Continue
    Interrogate
    Start
    AcceptStop
    AcceptPauseContinue
    AcceptShutdown
    QueryStatus
    QueryConfig
    Create
    Delete
    EnumDependents
    QueryObjectSecurity
    SetObjectSecurity


    CNTScmService::CNTScmService

    CNTScmService();

    Remarks:
    This is the default constructor which just initialises all internal variables to a safe state.

    See Also:
    ~CNTScmService()


    CNTScmService::~CNTScmService

    ~CNTScmService();

    Remarks:
    This is the standard destructor for the class. Internally it will call Close() to ensure that any handle that is opened by this instance is closed.

    See Also:
    CNTScmService(), Close().


    CNTScmService::Close

    void Close();

    Remarks:
    This frees the SC_HANDLE by internally calling CloseServiceHandle which this class encapsulates.


    CNTScmService::operator SC_HANDLE

    operator SC_HANDLE() const;

    Return Value:
    The underlying SDK service handle representing this class.

    Remarks:
    This function exposes the underlying handle which the CNTScmService class wraps. This function is provided for integration with legacy code which uses the handle directly.


    CNTScmService::Attach

    BOOL Attach(SC_HANDLE hService);

    Return Value:
    TRUE if the function was successful, otherwise FALSE. To get extended error information, call GetLastError().

    Parameters:

    • hService -- An SDK service handle returned from SDK calls to the SCM APIs

    Remarks:
    Use this member function to attach an existing SDK handle to a CNTScmService.

    See Also:
    Detach.


    CNTScmService::Detach

    SC_HANDLE Detach();

    Return Value:
    The SDK service handle.

    Remarks:
    Call this function to detach m_hService from the CNTScmService object and set m_hService to NULL.

    See Also:
    Attach.


    CNTScmService::ChangeConfig

    BOOL ChangeConfig(DWORD dwServiceType, DWORD dwStartType, DWORD dwErrorControl, LPCTSTR lpBinaryPathName, LPCTSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCTSTR lpDependencies, LPCTSTR lpServiceStartName, LPCTSTR lpPassword, LPCTSTR lpDisplayName) const;

    Remarks:
    This is a simple wrapper for the SDK call ChangeServiceConfig(). See the SDK for full details on this function.


    CNTScmService::Control

    BOOL Control(DWORD dwControl);

    Parameters:

    • dwControl -- Specifies the control code to send to this service. This value can be one of the standard control codes in the following table:
      Value Meaning
      SERVICE_CONTROL_STOP Requests the service to stop.
      SERVICE_CONTROL_PAUSE Requests the service to pause.
      SERVICE_CONTROL_CONTINUE Requests the paused service to resume.
      SERVICE_CONTROL_INTERROGATE Requests the service to update immediately its current status information to the service control manager.
      SERVICE_CONTROL_SHUTDOWN Requests the service to perform cleanup tasks, because the system is shutting down.

      This value can also be a user-defined control code, as described in the following table:

      Value Meaning
      Range 128 to 255. The service defines the action associated with the control code. The hService handle must have SERVICE_USER_DEFINED_CONTROL access.

    Remarks:
    This is a simple wrapper for the SDK call ControlService() SDK Call.


    CNTScmService::Stop

    BOOL Stop() const;

    Remarks:
    This is a simple wrapper for calling Control() with the parameter SERVICE_CONTROL_STOP.


    CNTScmService::Pause

    BOOL Pause() const;

    Remarks:
    This is a simple wrapper for calling Control() with the parameter SERVICE_CONTROL_PAUSE.


    CNTScmService::Continue

    BOOL Continue() const;

    Remarks:
    This is a simple wrapper for calling Control() with the parameter SERVICE_CONTROL_CONTINUE.


    CNTScmService::Interrogate

    BOOL Interrogate() const;

    Remarks:
    This is a simple wrapper for calling Control() with the parameter SERVICE_CONTROL_INTERROGATE.


    CNTScmService::Start

    BOOL Start(DWORD dwNumServiceArgs, LPCTSTR* lpServiceArgVectors) const;

    Return Value:
    TRUE If the function succeeds otherwise FALSE. To get extended error information, call GetLastError().

    Parameters:

    • dwNumServiceArgs -- Specifies the number of argument strings in the lpServiceArgVectors array. If lpServiceArgVectors is NULL, this parameter can be zero.
    • lpServiceArgVectors -- Pointer to an array of pointers that point to null-terminated argument strings passed to a service. Driver services do not receive these arguments. If no arguments are passed to the service being started, this parameter can be NULL.

    Remarks:
    Starts this service with the specified parameters.


    CNTScmService::AcceptStop

    BOOL AcceptStop(BOOL& bStop);

    Return Value:
    TRUE If the function succeeds otherwise FALSE. To get extended error information, call GetLastError().

    Parameters:

    • bStop -- Upon a successful return from this function, bStop will indicate whether this service can be stopped.

    Remarks:
    Queries this service to determine if this service can currently be stopped.


    CNTScmService::AcceptPauseContinue

    BOOL AcceptPauseContinue(BOOL& bPauseContinue);

    Return Value:
    TRUE If the function succeeds otherwise FALSE. To get extended error information, call GetLastError().

    Parameters:

    • bPauseContinue -- Upon a successful return from this function, bPauseContinue will indicate whether this service can be paused and continued.

    Remarks:
    Queries this service to determine if this service can currently be paused / continued.


    CNTScmService::AcceptShutdown

    BOOL AcceptShutdown(BOOL& bShutdown);

    Return Value:
    TRUE If the function succeeds otherwise FALSE. To get extended error information, call GetLastError().

    Parameters:

    • bShutdown -- Upon a successful return from this function, bShutdown will indicate whether this service handles the shutdown request.

    Remarks:
    Queries this service to determine if this service handles the shutdown request.


    CNTScmService::QueryStatus

    BOOL QueryStatus(LPSERVICE_STATUS lpServiceStatus) const;

    Return Value:
    TRUE If the function succeeds otherwise FALSE. To get extended error information, call GetLastError().

    Parameters:

    • lpServiceStatus -- Upon a successful return from this function, lpServiceStatus will contain the current status of this service.

    Remarks:
    Queries this service for its current status.


    CNTScmService::QueryConfig

    BOOL QueryConfig(LPQUERY_SERVICE_CONFIG& lpServiceConfig) const;

    Return Value:
    TRUE If the function succeeds otherwise FALSE. To get extended error information, call GetLastError().

    Parameters:

    • lpServiceConfig -- Upon a successful return from this function, lpServiceConfig will contain the current configuration of this service.

    Remarks:
    Queries this service for its current configuration. Bear in mind that since the QUERY_SERVICE_CONFIG is a variable sized structure, internally this function will allocate the required memory for lpServiceConfig, it is the responsibility of the client to delete this structure. This can be done as follows:

    LPQUERY_SERVICE_CONFIG lpConfig = NULL;
    service.QueryConfig(lpConfig);
    delete [] (BYTE*) lpConfig;
    


    CNTScmService::Create

    BOOL Create(CNTServiceControlManager& Manager, LPCTSTR lpServiceName, LPCTSTR lpDisplayName, DWORD dwDesiredAccess, DWORD dwServiceType, DWORD dwStartType, DWORD dwErrorControl, LPCTSTR lpBinaryPathName, LPCTSTR lpLoadOrderGroup, LPDWORD lpdwTagId, LPCTSTR lpDependencies, LPCTSTR lpServiceStartName, LPCTSTR lpPassword);

    Remarks:
    This is a simple wrapper for the SDK call CreateService(). See the SDK for full details on this function.


    CNTScmService::Delete

    BOOL Delete() const;

    Remarks:
    This is a simple wrapper for the SDK call DeleteService(). See the SDK for full details on this function.


    CNTScmService::EnumDependents

    BOOL EnumDependents(DWORD dwServiceState, DWORD dwUserData, ENUM_SERVICES_PROC lpEnumServicesFunc) const;

    Parameters:

    • dwServiceState -- Specifies the services to enumerate based on their running state. It must be one or both of the following values:
      Value Meaning
      SERVICE_ACTIVE Enumerates services that are in the following states: SERVICE_START_PENDING, SERVICE_STOP_PENDING, SERVICE_RUNNING, SERVICE_CONTINUE_PENDING, SERVICE_PAUSE_PENDING, and SERVICE_PAUSED.
      SERVICE_INACTIVE Enumerates services that are in the SERVICE_STOPPED state.
      SERVICE_STATE_ALL Combines the following states: SERVICE_ACTIVE and SERVICE_INACTIVE.
    • dwUserData -- Any user defined DWORD which you want to send to the callback function.
    • lpEnumServicesFunc -- Pointer to a callback function to use to enumerate the dependent services.

    Remarks:
    This function allows you to enumerate the services upon which this service is dependent. Internally this calls EnumDependentServices() and calls the callback function for each service. The format of the callback function is:

    BOOL CALLBACK ENUM_SERVICES_PROC(DWORD dwData, ENUM_SERVICE_STATUS& ServiceStatus);

    • dwData -- This is the value as send into the Enumeration function.
    • ServiceStatus -- Contains the information related to the enumerated service. See the SDK documentation for further details.

    Return TRUE from the function to continue enumeration and FALSE to stop enumeration.


    CNTScmService::QueryObjectSecurity

    BOOL QueryObjectSecurity(SECURITY_INFORMATION dwSecurityInformation, PSECURITY_DESCRIPTOR& lpSecurityDescriptor) const;

    Remarks:
    This is a simple wrapper for the SDK call QueryServiceObjectSecurity(). See the SDK for full details on this function.


    CNTScmService::SetObjectSecurity

    BOOL SetObjectSecurity(SECURITY_INFORMATION dwSecurityInformation, PSECURITY_DESCRIPTOR& lpSecurityDescriptor) const;

    Remarks:
    This is a simple wrapper for the SDK call SetServiceObjectSecurity(). See the SDK for full details on this function. Bear in mind that since the PSECURITY_DESCRIPTOR is a variable sized structure, internally this function will allocate the required memory for lpSecurityDescriptor, it is the responsibility of the client to delete this structure. This can be done as follows:

    PSECURITY_DESCRIPTOR lpDescriptor = NULL;
    service.QueryObjectSecurity(whatever, lpDescriptor);
    delete [] (BYTE*) lpDescriptor;
    



    CNTServiceControlManager

    CNTServiceControlManager is a class which encapsulates a connection to a Service Control Manager (SCM) on some machine. Functionality provided includes enumeration, database locking and service access.

    Functions this class provides include:

    CNTServiceControlManager
    ~CNTServiceControlManager
    operator HANDLE
    Attach
    Detach
    Open
    Close
    QueryLockStatus
    EnumServices
    OpenService
    Lock
    Unlock


    CNTServiceControlManager::CNTServiceControlManager

    CNTServiceControlManager();

    Remarks:
    This is the default constructor which just initialises all internal variables to a safe state.

    See Also:
    ~CNTServiceControlManager().


    CNTServiceControlManager::~CNTServiceControlManager

    ~CNTServiceControlManager();

    Remarks:
    This is the standard destructor for the class. Internally it will call Close() to ensure that any handle that is opened by this instance is closed.

    See Also:
    CNTServiceControlManager(), Close().


    CNTServiceControlManager::operator HANDLE

    operator SC_HANDLE() const;

    Return Value:
    The underlying SDK service handle representing this class.

    Remarks:
    This function exposes the underlying handle which the CNTServiceControlManager class wraps. This function is provided for integration with legacy code which uses the handle directly.


    CNTServiceControlManager::Attach

    BOOL Attach(SC_HANDLE hSCM);

    Return Value:
    TRUE if the function was successful, otherwise FALSE. To get extended error information, call GetLastError().

    Parameters:

    • hSCM -- An SDK service control manager handle returned from SDK calls to the SCM APIs.

    Remarks:
    Use this member function to attach an existing SDK handle to a CNTServiceControlManager.

    See Also:
    Detach


    CNTServiceControlManager::Detach

    SC_HANDLE Detach();

    Return Value:
    The SDK service control manager handle.

    Remarks:
    Call this function to detach m_hSCM from the CNTServiceControlManager object and set m_hSCM to NULL.

    See Also:
    Attach


    CNTServiceControlManager::Open

    BOOL Open(LPCTSTR pszMachineName, DWORD dwDesiredAccess);

    Remarks:
    This is a simple wrapper for the SDK call OpenSCManager(). See the SDK for full details on this function.


    CNTServiceControlManager::Close

    void Close();

    Remarks:
    This frees the SC_HANDLE by internally calling CloseServiceHandle() which this class encapsulates.


    CNTServiceControlManager::Close

    void Close();

    Remarks:
    This frees the SC_HANDLE by internally calling CloseServiceHandle() which this class encapsulates.


    CNTServiceControlManager::QueryLockStatus

    BOOL QueryLockStatus(LPQUERY_SERVICE_LOCK_STATUS& lpLockStatus) const;

    Remarks:
    This is a simple wrapper for the SDK call QueryServiceLockStatus(). See the SDK for full details on this function. Bear in mind that since the LPQUERY_SERVICE_LOCK_STATUS is a variable sized structure, internally this function will allocate the required memory for lpLockStatus, it is the responsibility of the client to delete this structure. This can be done as follows:

    LPQUERY_SERVICE_LOCK_STATUS lpLockStatus = NULL;
    scm.QueryLockStatus(lpLockStatus);
    delete [] (BYTE*) lpLockStatus;
    


    CNTServiceControlManager::EnumServices

    BOOL EnumServices(DWORD dwServiceType, DWORD dwServiceState, DWORD dwUserData, ENUM_SERVICES_PROC lpEnumServicesFunc) const;

    Parameters:

    • dwServiceType -- Specifies the type of services to enumerate. It must be one or both of the following values:
      Value Meaning
      SERVICE_WIN32 Enumerates services of type SERVICE_WIN32_OWN_PROCESS and SERVICE_WIN32_SHARE_PROCESS.
      SERVICE_DRIVER Enumerates services of type SERVICE_KERNEL_DRIVER and SERVICE_FILE_SYSTEM_DRIVER.
    • dwServiceState -- Specifies the services to enumerate based on their running state. It must be one or both of the following values:
      Value Meaning
      SERVICE_ACTIVE Enumerates services that are in the following states: SERVICE_START_PENDING, SERVICE_STOP_PENDING, SERVICE_RUNNING, SERVICE_CONTINUE_PENDING, SERVICE_PAUSE_PENDING, and SERVICE_PAUSED.
      SERVICE_INACTIVE Enumerates services that are in the SERVICE_STOPPED state.
      SERVICE_STATE_ALL Combines the following states: SERVICE_ACTIVE and SERVICE_INACTIVE.
    • dwUserData -- Any user defined DWORD which you want to send to the callback function.
    • lpEnumServicesFunc -- Pointer to a callback function to use to enumerate the dependent services.

    Remarks:
    This function allows you to enumerate the services which in the SCM. Internally this calls EnumServicesStatus() and calls the callback function for each service. The format of the callback function is:

    typedef BOOL CALLBACK ENUM_SERVICES_PROC(DWORD dwData, ENUM_SERVICE_STATUS& ServiceStatus);

    • dwData -- This is the value as send into the Enumeration function.
    • ServiceStatus -- Contains the information related to the enumerated service. See the SDK documentation for further details.

    Return TRUE from the function to continue enumeration and FALSE to stop enumeration.


    CNTServiceControlManager::OpenService

    BOOL OpenService(LPCTSTR lpServiceName, DWORD dwDesiredAccess, CNTScmService& service) const;

    Remarks:
    This is a simple wrapper for the SDK call of the same name. See the SDK for full details on this function.


    CNTServiceControlManager::Lock

    BOOL Lock();

    Remarks:
    This is a simple wrapper for the SDK call LockServiceDatabase(). See the SDK for full details on this function.


    CNTServiceControlManager::Unlock

    BOOL Unlock();

    Remarks:
    This is a simple wrapper for the SDK call UnlockServiceDatabase(). See the SDK for full details on this function.



    CEventLogRecord

    CEventLogRecord is a C++ wrapper class for the EVENTLOGRECORD structure as provided in the SDK. For anyone who has had to use this class using raw SDK calls, you will appreciate the easier access which the class provides.

    Functions and members this class provides include:

    CEventLogRecord
    operator=
    m_dwRecordNumber
    m_TimeGenerated
    m_TimeWritten
    m_dwEventID
    m_wEventTypes
    m_wEventCategory
    m_UserSID
    m_Strings
    m_Data
    m_sSourceName
    m_sComputerName


    CEventLogRecord::CEventLogRecord

    CEventLogRecord();
    CEventLogRecord(const CEventLogRecord& record);
    CEventLogRecord(const EVENTLOGRECORD* pRecord);

    Parameters:

    • record -- An existing CEventLogRecord.
    • pRecord -- An existing SDK EVENTLOGRECORD structure.


    CEventLogRecord::operator=

    CEventLogRecord& operator=(const CEventLogRecord& record);

    Remarks:
    The standard copy constructor.


    CEventLogRecord::m_dwRecordNumber

    DWORD m_dwRecordNumber;

    Remarks:
    Contains the record number for this event log entry.


    CEventLogRecord::m_TimeGenerated

    CTime m_TimeGenerated;

    Remarks:
    The CTime representation of when this entry was submitted.


    CEventLogRecord::m_TimeWritten

    CTime m_TimeWritten;

    Remarks:
    The CTime representation of when this entry was written to the event log.


    CEventLogRecord::m_dwEventID

    DWORD m_dwEventID;

    Remarks:
    Specifies the event. This is specific to the source that generated the event log entry, and is used, together with SourceName, to identify a message in a message file that is presented to the user while viewing the log.


    CEventLogRecord::m_wEventTypes

    WORD m_wEventType;

    Remarks:
    Specifies the type of event. This member can be one of the following values:

    Value Meaning
    EVENTLOG_ERROR_TYPE Error event
    EVENTLOG_WARNING_TYPE Warning event
    EVENTLOG_INFORMATION_TYPE Information event
    EVENTLOG_AUDIT_SUCCESS Success Audit event
    EVENTLOG_AUDIT_FAILURE Failure Audit event


    CEventLogRecord::m_UserSID

    CByteArray m_UserSID;

    Remarks:
    A CByteArray representation of the security identifier of the active user at the time this event was logged.


    CEventLogRecord::m_Strings

    CStringArray m_Strings;

    Remarks:
    A CStringArray representation of the strings which are merged into the message before it is displayed to the user.


    CEventLogRecord::m_Data

    CByteArray m_Data;

    Remarks:
    A CByteArray representation of the event-specific information within this event record.


    CEventLogRecord::m_sSourceName

    CString m_sSourceName;

    Remarks:
    Contains the string specifying the name of the source (application, service, driver, subsystem) that generated the entry.


    CEventLogRecord::m_sComputerName

    CString m_sComputerName;

    Remarks:
    Contains the string specifying the name of the computer that generated this event.



    CNTEventLog

    CNTEventLog is a C++ wrapper class for accessing the NT Event Logs. You can consider this as the client side to the Event Log APIs.

    Functions this class provides include:

    CNTEventLog
    ~CNTEventLog
    operator HANDLE
    Attach
    Detach
    Open
    OpenBackup
    OpenApplication
    OpenSystem
    OpenSecurity
    Close
    Backup
    Clear
    GetNumberOfRecords
    GetOldestRecord
    NotifyChange
    ReadNext
    ReadPrev


    CNTEventLog::CNTEventLog

    CNTEventLog();

    Remarks:
    This is the default constructor which just initialises all internal variables to a safe state.

    See Also:
    ~CNTEventLog().


    CNTEventLog::~CNTEventLog

    ~CNTEventLog();

    Remarks:
    This is the standard destructor for the class. Internally it will call Close() to ensure that any handle that is opened by this instance is closed.

    See Also:
    CNTEventLog(), Close().


    CNTEventLog::operator HANDLE

    operator HANDLE() const;

    Return Value:
    The underlying SDK event log handle representing this class.

    Remarks:
    This function exposes the underlying handle which CNTEventLog class wraps. This function is provided for integration with legacy code which uses the handle directly.


    CNTEventLog::Attach

    BOOL Attach(HANDLE hEventLog);

    Return Value:
    TRUE if the function was successful, otherwise FALSE. To get extended error information, call GetLastError().

    Parameters:

    • hEventLog -- An SDK event log handle returned from SDK calls to the Event log APIs.

    Remarks:
    Use this member function to attach an existing SDK handle to a CNTEventLog.

    See Also:
    Detach


    CNTEventLog::Detach

    HANDLE Detach();

    Return Value:
    The SDK event log handle.

    Remarks:
    Call this function to detach m_hEventLog from the CNTEventLog object and set m_hEventLog to NULL.

    See Also:
    Attach


    CNTEventLog::Open

    BOOL Open(LPCTSTR lpUNCServerName, LPCTSTR lpSourceName);

    Remarks:
    This is a simple wrapper for the SDK call OpenEventLog(). See the SDK for full details on this function.


    CNTEventLog::OpenBackup

    BOOL OpenBackup(LPCTSTR lpUNCServerName, LPCTSTR lpFileName);

    Remarks:
    This is a simple wrapper for the SDK call OpenBackupEventLog(). See the SDK for full details on this function.


    CNTEventLog::OpenApplication

    BOOL OpenApplication(LPCTSTR lpUNCServerName);

    Remarks:
    This is a sample wrapper for opening the "Application" event log on the specified computer, internally it just calls Open() with the appropriate string "Application".


    CNTEventLog::OpenSystem

    BOOL OpenSystem(LPCTSTR lpUNCServerName);

    Remarks:
    This is a sample wrapper for opening the "system" event log on the specified computer, internally it just calls Open() with the appropriate string "System".


    CNTEventLog::OpenSecurity

    BOOL OpenSecurity(LPCTSTR lpUNCServerName);

    Remarks:
    This is a sample wrapper for opening the "Security" event log on the specified computer, internally it just calls Open() with the appropriate string "Security".


    CNTEventLog::Close

    BOOL Close();

    Remarks:
    This frees the HANDLE by internally calling CloseEventLog which this class encapsulates.


    CNTEventLog::Backup

    BOOL Backup(LPCTSTR lpBackupFileName) const;

    Remarks:
    This is a simple wrapper for the SDK call BackupeventLog(). See the SDK for full details on this function.


    CNTEventLog::Clear

    BOOL Clear(LPCTSTR lpBackupFileName) const;

    Remarks:
    This is a simple wrapper for the SDK call ClearEventLog(). See the SDK for full details on this function.


    CNTEventLog::GetNumberOfRecords

    BOOL GetNumberOfRecords(DWORD& dwNumberOfRecords) const;

    Return Value:
    TRUE if the function was successful, otherwise FALSE. To get extended error information, call GetLastError().

    Parameters:

    • dwNumberOfRecords -- Upon successful return this will contain the number of records in the event log.

    Remarks:
    This is a simple wrapper for the SDK call GetNumberOfEventLogRecords(). See the SDK for full details on this function.


    CNTEventLog::GetOldestRecord

    BOOL GetOldestRecord(DWORD& dwOldestRecord) const;

    Return Value:
    TRUE if the function was successful, otherwise FALSE. To get extended error information, call GetLastError().

    Parameters:

    • dwOldestRecord -- Upon successful return this will contain the record number of the oldest record in the event log.

    Remarks:
    This is a simple wrapper for the SDK call GetOldestEventLogRecord(). See the SDK for full details on this function.


    CNTEventLog::NotifyChange

    BOOL NotifyChange(HANDLE hEvent) const;

    Remarks:
    This is a simple wrapper for the SDK call NotifyChangeEventLog(). See the SDK for full details on this function.


    CNTEventLog::ReadNext

    BOOL ReadNext(CEventLogRecord& record) const;

    Return Value:
    TRUE if the function was successful, otherwise FALSE. To get extended error information, call GetLastError().

    Parameters:

    • record -- Upon successful return this will contain the next record in the event log.

    Remarks:
    Reads the next record in forward chronological order from the event log. When this function returns successfully, the read position is incremented by one ready for the next read to occur.


    CNTEventLog::ReadPrev

    BOOL ReadPrev(CEventLogRecord& record) const;

    Return Value:
    TRUE if the function was successful, otherwise FALSE. To get extended error information, call GetLastError().

    Parameters:

    • record -- Upon successful return this will contain the previous record in the event log.

    Remarks:
    Reads the next record in reverse chronological order from the event log. When this function returns successfully, the read position is decremented by one ready for the next read to occur.



    Planned Enhancements

    • Review all classes to determine which parameters each member function requires can have default values.
    • If you have any suggested improvements, please let me know so that I can incorporate them into the next release.


    References

    • "Creating a Simple Windows NT Service in C++" by Nigel Thompson on the MSDN.
    • Win32 Foundation Classes developed by Sam Blackburn.
    • There are numerous articles in the Platform SDK which anyone contemplating writing a service should read. Areas covered include: Writing to the NT Event Log, Reading from the Event Log, How a simple C/SDK style service is structured, the Service Control Manager (SCM), reporting your status back to the SCM, using the message compiler (MC), etc, etc.


    Contacting the Author

    PJ Naughter
    Email: pjn@indigo.ie
    Web: http://www.naughter.com
    24 January 2000


    License

    This article has no explicit license attached to it but may contain usage terms in the article text or the download files themselves. If in doubt please contact the author via the discussion board below.

    A list of licenses authors might use can be found here