Hi Wim,

finally I got around to looking into the configuration options for the
Windows Service to be able to automatically restart it.
If I knew that nothing else is required other than writing the options
to C:\witty\whttpd   I would have done that a lot earlier.
So, the WWindowsService is already ready for review without further
modifications.
Attached are the files <WWindowsService> and its required <SfBase.h>
>From how I understand the notes in SfBase, it should be no problem to
include in the library.
It's not like Wt in the spirit of modern C++, but I don't know if it's
worth the effort to rewrite.

Rgds
Richard

Rgds
Richard

On Tue, 2009-04-14 at 17:16 +0200, Wim Dumon wrote:
> > Also what is not sactisfactory at the moment is that I have to pass
the
> > arguments everytime I start the service.
> 
> Wt can read its startup options from a configuration file. The
> configuration file is in boost.option format, e.g.:
> docroot = .
> http-address = 0.0.0.0
> http-port = 8080


On Wed, 2009-06-10 at 18:55 +0200, Wim Dumon wrote:
> Richard,
> 
> I'll make sure the change makes it into our git repository. Let me
> know if you see other problems.
> 
> Wim.
> 
> 2009/6/10 Richard Ulrich <[email protected]>:
> > Hi Wim,
> >
> > I didn't test it extensively, but what I've seen so far, it works
> > perfectly.
> >
> > I had to add the #ifdef HTTP_WITH_SSL in startAccept() as well, as I'm
> > building without ssl.
> >
> > So, now I can move on to the startup configuration...
> >
> > Thanks a lot.
> > Richard
> >
> > On Wed, 2009-06-10 at 14:56 +0200, Wim Dumon wrote:
> >> Richard,
> >>
> >> Ah! We finally got the bastard :)
> >>
> >> Could you try the applied patch? It causes the asynchronous accept to
> >> be called from within one of the threads of the http threadpool. Then
> >> it shouldn't matter anymore if the thread starting the server exits or
> >> not. It's less hackish than the solution you propose, even though I
> >> believe it would also work.
> >>
> >> Regards,
> >> Wim.
> >
> >
> >
> 
/////////////////////////////////////////////////////////////////////////////
//
//  Windows Service Framework Library (SFL)
//
//  Version 2.0
//
//
//  SflBase.h
//
//  Last update: Nov 05 2007
//
//
//
//  Copyright (c) 2004,2007 Igor Vartanov
//
//  mailto: [email protected]
//  downloaded from
//  http://www.codeguru.com/cpp/w-p/system/services/article.php/c14503
//
/////////////////////////////////////////////////////////////////////////////

#ifndef IV_SFLBASE_H
#define IV_SFLBASE_H

#include "crtdbg.h"
#include "tchar.h"
#include "malloc.h"

#define _SFL_VER 0x0200

#ifdef _MSC_VER
#pragma comment( lib, "advapi32.lib" )
#endif

#if defined(_MSC_VER) && (_MSC_VER < 1300)
#pragma warning(push)
#pragma warning(disable : 4100 4127 4511 4512 4555 4710)
#endif

#ifndef SFLASSERT
#define SFLASSERT(x)   _ASSERTE(x)
#endif

#ifndef ARRAYSIZE
#define ARRAYSIZE(x)  (sizeof(x)/sizeof(x[0]))
#endif

namespace SFL {
	class CServiceRoot;

	enum
	{
		SFL_SERVICESTYLE_NT4 = 0,
		SFL_SERVICESTYLE_NT5
	};
	template <int> class X;
	typedef X<SFL_SERVICESTYLE_NT4> XNT4;
	typedef X<SFL_SERVICESTYLE_NT5> XNT5;

	/////////////////////////////////////////////////////////////////////////////
	//
	//  structure CServiceInfo
	//
	//  Version 2.0 (Jul 15 2007)
	//
	//
	/////////////////////////////////////////////////////////////////////////////

	struct CServiceInfo
	{
		LPCTSTR                 m_pszServiceName;
		LPSERVICE_MAIN_FUNCTION m_pfnServiceMain;
		DWORD                   m_style;
	};

	/////////////////////////////////////////////////////////////////////////////
	//
	//  class CServiceProxyT<TService,t_szServiceName>
	//
	//  Version 2.0 (Sep 28 2007)
	//
	//
	/////////////////////////////////////////////////////////////////////////////
	template<class TService, DWORD t_serviceId>
	class CServiceProxyT: protected TService
	{
		typedef CServiceProxyT<TService, t_serviceId> CServiceProxyClass;
		template <class T> void SetHandler(T*);
		template <> void SetHandler<XNT4>(XNT4*) { m_pfnHandler   = _Handler;   }
		template <> void SetHandler<XNT5>(XNT5*) { m_pfnHandlerEx = _HandlerEx; }

	protected:
		CServiceProxyT()
		{
			m_pThis = this;
			SetHandler((X<serviceStyle>*)NULL);
		}

	public:
		static CServiceRoot* Construct(TService* pDummy = NULL)
		{
			static TCHAR szServiceName[256] = {0};
			HMODULE hmod = ::GetModuleHandle(NULL);
			SFLASSERT(hmod);
			BOOL res = ::LoadString(hmod, t_serviceId, szServiceName, ARRAYSIZE(szServiceName));
			SFLASSERT(res);
			return Construct2(pDummy, szServiceName);
		}

		static CServiceRoot* Construct2(TService* pDummy = NULL, LPCTSTR pszName = NULL)
		{
			pDummy; // to prevent warning C4100
			static CServiceProxyClass theService;
			static CServiceInfo si = { pszName, theService._ServiceMain, theService.serviceStyle };
			theService.m_pServiceInfo = &si;
			return static_cast<CServiceRoot*>(&theService);
		}

	protected:
		static CServiceProxyClass* m_pThis;

		static void WINAPI _ServiceMain(DWORD dwArgc, LPTSTR* lpszArgv)
		{
			SFLASSERT(m_pThis || !"SFLServiceProxyT<TService>::_ServiceMain");
			m_pThis->ServiceMain(dwArgc, lpszArgv);
		}

		static void WINAPI _Handler(DWORD dwCtrl)
		{
			SFLASSERT(m_pThis || !"SFLServiceProxyT<TService>::_Handler");
			m_pThis->Handler(dwCtrl);
		}

		static DWORD WINAPI _HandlerEx(DWORD dwCtrl, DWORD dwEventType, LPVOID lpEventData, LPVOID lpContext)
		{
			SFLASSERT(m_pThis || !"SFLServiceProxyT<TService>::_HandlerEx");
			return m_pThis->HandlerEx(dwCtrl, dwEventType, lpEventData, lpContext);
		}
	};

	template<class TService, DWORD t_szServiceId>
		CServiceProxyT<TService, t_szServiceId>* CServiceProxyT<TService, t_szServiceId>::m_pThis = NULL;


    /////////////////////////////////////////////////////////////////////////////
    //
    //  class CServiceStatusObject
    //
    //  Version 2.0 (Jul 01 2006)
    //
    //
    /////////////////////////////////////////////////////////////////////////////

    class CServiceStatusObject: public SERVICE_STATUS
    {
    private:
        SERVICE_STATUS_HANDLE m_handle;

    public:
        CServiceStatusObject(): m_handle(NULL)
		{
			ZeroMemory(static_cast<LPSERVICE_STATUS>(this), sizeof(SERVICE_STATUS));
		}

        operator LPSERVICE_STATUS()
        {
            return static_cast<LPSERVICE_STATUS>(this);
        }

        SERVICE_STATUS& operator=( SERVICE_STATUS& status )
        {
            *static_cast<LPSERVICE_STATUS>(this) = status;
            return *this;
        }

        SERVICE_STATUS_HANDLE GetHandle() const
        {
            return m_handle;
        }

        SERVICE_STATUS_HANDLE SetHandle( SERVICE_STATUS_HANDLE handle )
        {
            m_handle = handle;
            return m_handle;
        }
    };


    /////////////////////////////////////////////////////////////////////////////
    //
    //  class CServiceRoot
    //
    //  Version 2.0 (Jul 15 2007)
    //
    //
    /////////////////////////////////////////////////////////////////////////////

    class CServiceRoot
    {
    protected:
        CServiceInfo*  m_pServiceInfo;
        CServiceStatusObject m_status;

	protected:
		CServiceRoot(): m_pServiceInfo(NULL) {}

    private:
        CServiceRoot( const CServiceRoot& ) {}
        CServiceRoot& operator=( const CServiceRoot& ) {}

    public:
        virtual ~CServiceRoot() {}

        DWORD GetCurrentState() const
        {
            return m_status.dwCurrentState;
        }

        LPCTSTR GetServiceName() const
        {
            return m_pServiceInfo->m_pszServiceName;
        }

		LPSERVICE_MAIN_FUNCTION GetServiceMain() const
		{
			return m_pServiceInfo->m_pfnServiceMain;
		}

		DWORD GetServiceStyle() const
		{
			return m_pServiceInfo->m_style;
		}

        void SetServiceType( DWORD dwType )
        {
			if(0 == m_status.dwServiceType)  // can be set only once
				m_status.dwServiceType = dwType;
        }

        DWORD GetControlsAccepted() const
        {
            return m_status.dwControlsAccepted;
        }

	protected:
        void SetControlsAccepted( DWORD dwAccept )
        {
            m_status.dwControlsAccepted = dwAccept;
        }

        BOOL SetServiceStatus( LPSERVICE_STATUS pStatus = NULL )
        {
            SFLASSERT( m_status.GetHandle() || !"SFL: Handler not registered yet" );

            if( pStatus )
                m_status = *pStatus;

            switch( m_status.dwCurrentState )
            {
            case SERVICE_START_PENDING:
            case SERVICE_STOP_PENDING:
            case SERVICE_CONTINUE_PENDING:
            case SERVICE_PAUSE_PENDING:
                break;

            default:
                m_status.dwCheckPoint = m_status.dwWaitHint = 0;
                break;
            }

            if( ( ERROR_SUCCESS != m_status.dwServiceSpecificExitCode ) &&
                ( ERROR_SERVICE_SPECIFIC_ERROR != m_status.dwWin32ExitCode ) )
                m_status.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;

            return ::SetServiceStatus( m_status.GetHandle(), m_status );
        }

        BOOL SetServiceStatus( DWORD dwState, DWORD dwWin32ExitCode = ERROR_SUCCESS )
        {
            m_status.dwCurrentState  = dwState;
            m_status.dwWin32ExitCode = dwWin32ExitCode;
            m_status.dwServiceSpecificExitCode = 0;

            return SetServiceStatus();
        }

        BOOL SetServiceStatusSpecific( DWORD dwState, DWORD dwSpecificExitCode )
        {
            if( ERROR_SUCCESS == dwSpecificExitCode )
                return SetServiceStatus( dwState );

            m_status.dwServiceSpecificExitCode = dwSpecificExitCode;
            return SetServiceStatus( dwState, ERROR_SERVICE_SPECIFIC_ERROR );
        }

        BOOL CheckPoint( DWORD dwWaitHint, DWORD dwCheckPoint = DWORD(-1) )
        {
            switch( m_status.dwCurrentState )
            {
            case SERVICE_START_PENDING:
            case SERVICE_STOP_PENDING:
            case SERVICE_CONTINUE_PENDING:
            case SERVICE_PAUSE_PENDING:
                {
                    if( DWORD(-1) == dwCheckPoint )
                        m_status.dwCheckPoint++;
                    else
                        m_status.dwCheckPoint = dwCheckPoint;

                    m_status.dwWaitHint = dwWaitHint;
                }
                break;

            default:
                SFLASSERT( !"SFL: Checking the point in nonpending state" );
                m_status.dwCheckPoint = m_status.dwWaitHint = 0;
                break;
            }

            return SetServiceStatus();
        }
    };


    /////////////////////////////////////////////////////////////////////////////
    //
    //  class CServiceBaseT<T,t_dwControlAccepted>
    //
    //  Version 2.0 (Nov 05 2007)
    //
    //
    /////////////////////////////////////////////////////////////////////////////

    template<class TService, DWORD t_dwControlsAccepted>
    class CServiceBaseT: public CServiceRoot
    {
    protected:
        typedef CServiceBaseT<TService, t_dwControlsAccepted> CServiceBaseClass;

        CServiceBaseT(){}

		union
		{
			LPHANDLER_FUNCTION    m_pfnHandler;
			LPHANDLER_FUNCTION_EX m_pfnHandlerEx;
		};

		template <class T> SERVICE_STATUS_HANDLE RegisterHandler(T*);
		template <> SERVICE_STATUS_HANDLE RegisterHandler<XNT4>(XNT4*)
		{
			return ::RegisterServiceCtrlHandler( GetServiceName(), m_pfnHandler );
		}

		template <> SERVICE_STATUS_HANDLE RegisterHandler<XNT5>(XNT5*)
		{
			TService* pThis = static_cast<TService*>(this);
			SFLASSERT( pThis || "CServiceBaseClass::ServiceMain" );
			return ::RegisterServiceCtrlHandlerEx( GetServiceName(), m_pfnHandlerEx, pThis->GetServiceContext() );
		}

        void ServiceMain( DWORD dwArgc, LPTSTR* lpszArgv )
        {
            TService* pThis = static_cast<TService*>(this);
            SFLASSERT( pThis || "CServiceBaseClass::ServiceMain" );

            BOOL  bRes;
            DWORD dwSpecific = 0;

            SetControlsAccepted( t_dwControlsAccepted );

			m_status.SetHandle( pThis->RegisterHandler( (X<TService::serviceStyle>*)NULL ) );
            SFLASSERT( m_status.GetHandle() || !"SFL: Handler registration failed" );

            SetServiceStatus( SERVICE_START_PENDING );

            bRes = pThis->InitInstance( dwArgc, lpszArgv, dwSpecific );
            if( !bRes )
            {
                SetServiceStatusSpecific( SERVICE_STOPPED, dwSpecific );
                return;
            }

            bRes = SetServiceStatus( SERVICE_RUNNING );
            SFLASSERT( bRes || !"SFL: Failed to set RUNNING status" );
        }

        BOOL InitInstance( DWORD dwArgc, LPTSTR* lpszArgv, DWORD& dwSpecific )
        {
            dwArgc; lpszArgv; dwSpecific; // prevent warning C4100

            return TRUE;
        }

		LPVOID GetServiceContext()
		{
			return NULL;
		}
    };


    /////////////////////////////////////////////////////////////////////////////
    //
    //  class CServiceAppT<T>
    //
    //  Version 2.0 (Jul 15 2007)
    //
    //
    /////////////////////////////////////////////////////////////////////////////
    template <class T>
    class CServiceAppT
    {
    private:
        size_t m_nServiceCount;
        CServiceRoot** m_pServices;

    protected:
        typedef CServiceAppT<T> CAppBaseClass;

        CServiceAppT(): m_nServiceCount(0), m_pServices(NULL)
        {
        }

        BOOL Run( LPSERVICE_TABLE_ENTRY pTable )
        {
            T* pThis = static_cast<T*>(this);

            if( !pThis->InitApp() )
                return FALSE;

            BOOL bRes = ::StartServiceCtrlDispatcher( pTable );
            SFLASSERT( bRes || !"SFL: StartServiceCtrlDispatcher() failed" );

            pThis->ExitApp();

            return bRes;
        }

    public:
        int GetServiceCount() const
        {
            return m_nServiceCount;
        }

        CServiceInfo** GetServices() const
        {
            return m_pServices;
        }

        BOOL InitApp()
        {
            return TRUE;
        }

        void ExitApp()
        {
        }

        BOOL PreMain( int argc, LPTSTR* argv )
        {
            argc; // to prevent warning C4100
            argv; // to prevent warning C4100
            return TRUE;
        }

        void PostMain()
        {
        }

        int Main( int argc, LPTSTR* argv, CServiceRoot** pMap, size_t nTableSize )
        {
            argc; argv; // prevent warning C4100
            LPSERVICE_TABLE_ENTRY pTable = NULL;
            BOOL bRes       = 0;

            m_pServices     = pMap;
            m_nServiceCount = nTableSize - 1;  // because nTableSize includes final NULL item

            size_t nSize = sizeof(SERVICE_TABLE_ENTRY) * nTableSize;
            __try
            {
                pTable = (LPSERVICE_TABLE_ENTRY)_alloca( nSize );
                ::ZeroMemory( pTable, nSize );

                // fill service table with service map objects data
                for( size_t i = 0; i < m_nServiceCount; i++ )
                {
                    SFLASSERT( pMap[i]->GetServiceName() || !"SFL: Service NULL name not allowed" );
                    pTable[i].lpServiceName = (LPTSTR)pMap[i]->GetServiceName();
					pTable[i].lpServiceProc = pMap[i]->GetServiceMain();
                    pMap[i]->SetServiceType( (m_nServiceCount > 1)? SERVICE_WIN32_SHARE_PROCESS : SERVICE_WIN32_OWN_PROCESS );
                }

                T* pThis = static_cast<T*>(this);
                bRes = pThis->Run( pTable );
            }
            __except( STATUS_STACK_OVERFLOW == GetExceptionCode() )
            {
                SFLASSERT(!"SFL: Stack overflow in CServiceAppT<>::Main()");
            }
            return !bRes;
        }
    };

} // namespace SFL

#if defined(_MSC_VER) && (_MSC_VER < 1300)
#pragma warning(pop)
#endif

#ifdef SFL_USE_NAMESPACE_EXPLICITLY
#define SFL_NS  SFL::
#else
#define SFL_NS
using namespace SFL;
#endif // SFL_USE_NAMESPACE_EXPLICITLY

/////////////////////////////////////////////////////////////////////////////
//
//  The set of macros
//
//  Version 2.0 (Sep 28 2007)
//
/////////////////////////////////////////////////////////////////////////////

//////////// SERVICE APPLICATION  ///////////////////////////////////////////
//
#define SFL_DECLARE_SERVICEAPP(T) class T; namespace SFL{ const T* SflGetServiceApp(void); }

//////////// SERVICE MAP ////////////////////////////////////////////////////
//
#define SFL_BEGIN_SERVICE_MAP(T)                                            \
namespace SFL{ const T* SflGetServiceApp(void) { static T theApp; return &theApp; } } \
    int _tmain( int argc, LPTSTR* argv )                                    \
    {                                                                       \
        T* pApp = const_cast<T*>( SFL_NS SflGetServiceApp() );              \
        SFL::CServiceRoot* pServiceMap[] = {                                \

#define SFL_SERVICE_ENTRY( TService, idRes )                                \
	SFL::CServiceProxyT< TService, idRes >::Construct( (TService*)NULL ),   \

#define SFL_SERVICE_ENTRY2( TService, id, name )                            \
    SFL::CServiceProxyT< TService, id >::Construct2( (TService*)NULL, TEXT( name ) ), \

#define SFL_END_SERVICE_MAP()                                               \
			NULL                                                            \
        };                                                                  \
        int retMain = -1;                                                   \
        if( pApp->PreMain( argc, argv ) )                                   \
            retMain = pApp->Main( argc, argv, pServiceMap, ARRAYSIZE(pServiceMap) ); \
        pApp->PostMain();                                                   \
        return retMain;                                                     \
        }

//////////// CONTROL HANDLING MAP ///////////////////////////////////////////
//
#define SFL_BEGIN_CONTROL_MAP(T)                                            \
public:	                                                                    \
    enum { serviceStyle = SFL_NS SFL_SERVICESTYLE_NT4 };                    \
protected:                                                                  \
    void Handler( DWORD dwControl )                                         \
    {                                                                       \
        BOOL    bHandled       = FALSE;                                     \
        DWORD   dwState        = m_status.dwCurrentState;                   \
        DWORD   dwWin32Err     = 0;                                         \
        DWORD   dwSpecificErr  = 0;                                         \
typedef T THandlerClass;                                                    \
typedef DWORD (T::*t_handler)(DWORD&, DWORD&, BOOL&);                       \
typedef DWORD (T::*t_handler_range)(DWORD, DWORD&, DWORD&, BOOL&);          \
        do {                                                                \

#define SFL_END_CONTROL_MAP()                                               \
        } while(0);                                                         \
        if( bHandled )                                                      \
        {   m_status.dwCurrentState = dwState;                              \
            m_status.dwWin32ExitCode = dwWin32Err;                          \
            m_status.dwServiceSpecificExitCode = dwSpecificErr;             \
            SetServiceStatus();                                             \
        }                                                                   \
    }                                                                       \

#define SFL_HANDLE_CONTROL( code, handler )                                 \
        if( code == dwControl )                                             \
        {   t_handler pfnHandler = static_cast<t_handler>(&THandlerClass:: handler); \
            dwState = (this->*pfnHandler)( dwWin32Err, dwSpecificErr,       \
                                           bHandled ); break;               \
        }

#define SFL_HANDLE_CONTROL_RANGE( codeMin, codeMax, handler )               \
        if( (codeMin <= dwControl) && (codeMax >= dwControl ) )             \
        {   t_handler_range pfnHandler =                                    \
                static_cast<t_handler_range>(&THandlerClass:: handler);     \
            dwState = (this->*pfnHandler)( dwControl, dwWin32Err,           \
                                           dwSpecificErr, bHandled );       \
            break;                                                          \
        }

#define SFL_HANDLE_CONTROL_CONTINUE()    SFL_HANDLE_CONTROL( SERVICE_CONTROL_CONTINUE, OnContinue )
#define SFL_HANDLE_CONTROL_PAUSE()       SFL_HANDLE_CONTROL( SERVICE_CONTROL_PAUSE, OnPause )
#define SFL_HANDLE_CONTROL_STOP()        SFL_HANDLE_CONTROL( SERVICE_CONTROL_STOP, OnStop )
#define SFL_HANDLE_CONTROL_SHUTDOWN()    SFL_HANDLE_CONTROL( SERVICE_CONTROL_SHUTDOWN, OnShutdown )
#define SFL_HANDLE_CONTROL_INTERROGATE() SFL_HANDLE_CONTROL( SERVICE_CONTROL_INTERROGATE, OnInterrogate )


//////////// EXTENDED CONTROL HANDLING MAP //////////////////////////////////
//
#define SFL_BEGIN_CONTROL_MAP_EX(T)                                         \
public:	                                                                    \
    enum { serviceStyle = SFL_NS SFL_SERVICESTYLE_NT5 };                    \
protected:                                                                  \
    DWORD HandlerEx( DWORD  dwControl,   DWORD  dwEventType,                \
                     LPVOID lpEventData, LPVOID lpContext )                 \
    {                                                                       \
        BOOL    bHandled       = FALSE;                                     \
        DWORD   dwRet          = NO_ERROR;                                  \
        DWORD   dwState        = m_status.dwCurrentState;                   \
        DWORD   dwWin32Err     = 0;                                         \
        DWORD   dwSpecificErr  = 0;                                         \
typedef T THandlerClass;                                                    \
typedef DWORD (T::*t_handler)(DWORD&, DWORD&, BOOL&);                       \
typedef DWORD (T::*t_handler_range)(DWORD, DWORD&, DWORD&, BOOL&);          \
typedef DWORD (T::*t_handler_ex)(DWORD&, DWORD&, DWORD&, BOOL&, DWORD, LPVOID, LPVOID); \
typedef DWORD (T::*t_handler_range_ex)(DWORD, DWORD&, DWORD&, DWORD&, BOOL&, DWORD, LPVOID, LPVOID); \
	    dwEventType; lpEventData; lpContext;  /* preventing 4100 */         \
        do {                                                                \

#define SFL_END_CONTROL_MAP_EX()                                            \
        } while(0);                                                         \
        if( bHandled )                                                      \
        {   m_status.dwCurrentState = dwState;                              \
            m_status.dwWin32ExitCode = dwWin32Err;                          \
            m_status.dwServiceSpecificExitCode = dwSpecificErr;             \
            SetServiceStatus();                                             \
            return dwRet; }                                                 \
        return ERROR_CALL_NOT_IMPLEMENTED;                                  \
    }                                                                       \

#define SFL_HANDLE_CONTROL_EX( code, handler )                              \
        if( code == dwControl )                                             \
        {   t_handler_ex pfnHandler = static_cast<t_handler_ex>(&THandlerClass:: handler); \
            dwRet = (this->*pfnHandler)( dwState, dwWin32Err, dwSpecificErr,\
                                         bHandled, dwEventType,             \
                                         lpEventData, lpContext ); break; }

#define SFL_HANDLE_CONTROL_RANGE_EX( codeMin, codeMax, handler )            \
        if( (codeMin <= dwControl) && (codeMax >= dwControl ) )             \
        {   t_handler_range_ex pfnHandler =                                 \
                static_cast<t_handler_range_ex>(&THandlerClass:: handler);  \
            dwRet = (this->*pfnHandler)( dwControl, dwState, dwWin32Err,    \
                                         dwSpecificErr, bHandled,           \
                                         dwEventType, lpEventData,          \
                                         lpContext ); break; }

//////////// SFL CLASS DECLARATION //////////////////////////////////////////
//
#define SFL_DECLARE_SERVICECLASS_FRIENDS(TService)                          \
    friend class CServiceBaseClass;                                         \

#define SFL_DECLARE_SIMPLESERVICEAPP_CLASS(TAppClass) class TAppClass: public CServiceAppT<TAppClass> {};

namespace SFL {
	typedef class _TSimpleApp: public CServiceAppT<_TSimpleApp>
	{
	} CSimpleServiceApp;
}

#endif // IV_SFLBASE_H
 #ifndef WT_WWINDOWSSERVICE_INCLUDED
 #define WT_WWINDOWSSERVICE_INCLUDED

// windows stuff
#include "SflBase.h"
#include <ioevent.h>
#include <Dbt.h>
// witty
#include <Wt/WServer>
#include <Wt/WApplication>
#include <Wt/WEnvironment>
// boost
#include <boost/filesystem.hpp>
#include <boost/filesystem/fstream.hpp>
#include <boost/date_time/posix_time/posix_time.hpp>
// standard library
#include <iomanip>
#include <string>


template<class WtApplicationT>
class WWindowsService : public CServiceBaseT<WWindowsService<WtApplicationT>, 
SERVICE_ACCEPT_STOP/* |  SERVICE_ACCEPT_HARDWAREPROFILECHANGE*/>
{
        SFL_DECLARE_SERVICECLASS_FRIENDS(WWindowsService)

        SFL_BEGIN_CONTROL_MAP_EX(WWindowsService)
                SFL_HANDLE_CONTROL_STOP()
        SFL_END_CONTROL_MAP_EX()

        static void log(const std::string &msg)
        {
        boost::filesystem::ofstream ofs(boost::filesystem::path(getenv("TEMP")) 
/ "WWindowsService.log", std::ios_base::app);
        ofs << boost::posix_time::second_clock::local_time() << " " << msg << 
std::endl;
        }

        DWORD OnStop(DWORD& dwWin32Err, DWORD& dwSpecificErr, BOOL& bHandled)
        {
        wtsrv_->stop();

        log("Service stopped");

        bHandled =  TRUE;
        return SERVICE_STOPPED;
    }



#if defined(_MSC_VER) && (_MSC_VER < 1300)
public:
#endif
        LPVOID GetServiceContext() { return this; }

        BOOL InitInstance(DWORD dwArgc, LPTSTR* lpszArgv, DWORD& dwSpecificErr)
        {
        try
        {
            log("initializing");
            for(int i=0; i<dwArgc; ++i)
                log(std::string("  -> ") + lpszArgv[i]);


            // redirect stdout and stderr
            boost::filesystem::path tmpdir(getenv("TEMP"));
            stdout_redirect = freopen((tmpdir / 
"WWindowsService_stdout.log").string().c_str(), "w", stdout);
            stderr_redirect = freopen((tmpdir / 
"WWindowsService_stderr.log").string().c_str(), "w", stderr);

            delete wtsrv_;
            wtsrv_ = new Wt::WServer(lpszArgv[0]);
            //  WServer server(argv[0], getWtConfigXml(argc, argv));

            // WTHTTP_CONFIGURATION is e.g. "/etc/wt/wthttpd"
            wtsrv_->setServerConfiguration(dwArgc, lpszArgv, 
WTHTTP_CONFIGURATION);

            // add a single entry point, at the default location (as determined
            // by the server configuration's deploy-path)
            wtsrv_->addEntryPoint(Wt::WServer::Application, 
&WWindowsService<WtApplicationT>::createApplication);
            wtsrv_->start();

            log("Service started");

            if(wtsrv_->isRunning())
                log("is running");
            else
                log("is not running");

        }
        catch(Wt::WServer::Exception& e)
        {
            std::cerr << e.what() << "\n";
            log(e.what());
            return FALSE;
        }
        catch (std::exception& e)
        {
            std::cerr << "exception: " << e.what() << "\n";
            log(e.what());
            return FALSE;
        }

        return TRUE;
        }

        WWindowsService() : wtsrv_(NULL) {};

        virtual ~WWindowsService()
        {
        log("~WWindowsService()");
        fclose(stdout_redirect);
        fclose(stderr_redirect);
        delete wtsrv_;
    };

private:

    // callback function is called everytime when a user enters the page. Can 
be used to authenticate.
    static Wt::WApplication *createApplication(const Wt::WEnvironment& env)
    {
        log("creating application");

        WtApplicationT *wtapp = new WtApplicationT(env);

        log("application created");

        return wtapp;
    }

    Wt::WServer *wtsrv_;
    FILE *stdout_redirect, *stderr_redirect;
};



#endif
------------------------------------------------------------------------------
Enter the BlackBerry Developer Challenge  
This is your chance to win up to $100,000 in prizes! For a limited time, 
vendors submitting new applications to BlackBerry App World(TM) will have
the opportunity to enter the BlackBerry Developer Challenge. See full prize  
details at: http://p.sf.net/sfu/Challenge
_______________________________________________
witty-interest mailing list
[email protected]
https://lists.sourceforge.net/lists/listinfo/witty-interest

Reply via email to