//////////////////////////////////////////////////////////////////////////////
//
//  Daemon.h
//  Win32::Daemon Perl extension main header file
//
//  Copyright (c) 1998-2008 Dave Roth
//  Courtesy of Roth Consulting
//  http://www.roth.net/
//
//  This file may be copied or modified only under the terms of either 
//  the Artistic License or the GNU General Public License, which may 
//  be found in the Perl 5.0 source kit.
//
//  2008.03.24  :Date
//  20080324    :Version
//////////////////////////////////////////////////////////////////////////////

//	#include "Win32Perl.h"
 
#ifndef _DAEMON_H
#   define _DAEMON_H 

#   ifndef WIN32
#       ifdef _WIN32
#           define WIN32   
#       endif // _WIN32  
#   endif // WIN32  
  
///////////////////////////////////////////////////////////////////////////////////////////
//  Begin resource compiler macro block

    //  Include the version information...
    #include "version.h"

    #define EXTENSION_NAME          "Daemon"

    #define EXTENSION_PARENT_NAMESPACE      "Win32"
    #define EXTENSION               EXTENSION_PARENT_NAMESPACE "::" EXTENSION_NAME
    
    #define EXTENSION_FILE_NAME     EXTENSION_NAME

    #define EXTENSION_VERSION       VERSION
    #define EXTENSION_AUTHOR        "Dave Roth <rothd@roth.net>"

    #define COPYRIGHT_YEAR          "2000-2008"
    #define COPYRIGHT_NOTICE        "Copyright (c) " COPYRIGHT_YEAR

    #define COMPANY_NAME            "Roth Consulting\r\nhttp://www.roth.net/consult"

    #define VERSION_TYPE            "Beta"
//  End resource compiler macro block
///////////////////////////////////////////////////////////////////////////////////////////

///////////////////////////////////////////////////////////////////////////////
//  These are members that will be defined in the blessed Perl Object.
//  These are only intended to be used by this extension (and maybe it's
//  brethern). I would not suggest other applications rely on this since it
//  may change.
#define KEYWORD_SERVICE_NAME            TEXT( "name" )
#define KEYWORD_SERVICE_DISPLAY_NAME    TEXT( "display" )
#define KEYWORD_SERVICE_BINARY_PATH     TEXT( "path" )
#define KEYWORD_SERVICE_ACCOUNT_UID     TEXT( "user" )
#define KEYWORD_SERVICE_ACCOUNT_PWD     TEXT( "password" )
#define KEYWORD_SERVICE_PARAMETERS      TEXT( "parameters" )
#define KEYWORD_SERVICE_MACHINE         TEXT( "machine" )
#define KEYWORD_SERVICE_TYPE            TEXT( "service_type" )
#define KEYWORD_SERVICE_START_TYPE      TEXT( "start_type" )
#define KEYWORD_SERVICE_ERROR_CONTROL   TEXT( "error_control" )
#define KEYWORD_SERVICE_LOAD_ORDER      TEXT( "load_order" )
#define KEYWORD_SERVICE_TAG_ID          TEXT( "tag_id" )
#define KEYWORD_SERVICE_DEPENDENCIES    TEXT( "dependencies" )
#define KEYWORD_SERVICE_DESCRIPTION     TEXT( "description" )

#define KEYWORD_CALLBACK_COMMAND_NAME	TEXT( "command" )


///////////////////////////////////////////////////////////////////////////////
//  Keywords used in anonymous hash for State()
#define KEYWORD_STATE_STATE             TEXT( "state" )
#define KEYWORD_STATE_WAIT_HINT         TEXT( "wait_hint" )
#define KEYWORD_STATE_ERROR             TEXT( "error" )


///////////////////////////////////////////////////////////////////////////////
// Registry based keywords
#define REGISTRY_SERVICE_PATH                   TEXT( "System\\CurrentControlSet\\Services" )
#define REGISTRY_SERVICE_KEYWORD_DESCRIPTION    TEXT( "Description" )

///////////////////////////////////////////////////////////////////////////////
// Location of where to find local user's profiles
#define REG_KEY_USER_LOCAL_PROFILE          TEXT( "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList\\" )
#define REG_VALUE_USER_CENTRAL_PROFILE_PATH TEXT( "CentralProfile" )
#define REG_VALUE_USER_LOCAL_PROFILE_PATH   TEXT( "ProfileImagePath" )

///////////////////////////////////////////////////////////////////////////////
// File name of user's profile and delta in hive form
#define USER_PROFILE_HIVE_NAME              TEXT( "NTUser.dat" )
#define USER_PROFILE_HIVE_LOG_NAME          TEXT( "NTUser.log" )

///////////////////////////////////////////////////////////////////////////////
// If DEBUG is defined where does debug information get dumped to?
#define DEBUG_OUTPUT_FILE		TEXT( "\\\\.\\pipe\\syslog" )
#define DEBUG_OUTPUT_FILE_ALT	TEXT( "c:\\temp\\Win32-Daemon-debug.log" )


///////////////////////////////////////////////////////////////////////////////
// What is the largest possible size that the process's sid can
// be?
#define MAX_SID_SIZE                    128

///////////////////////////////////////////////////////////////////////////////
// Misc values
#define	MAX_SERVICE_DEPENDENCY_BUFFER_SIZE	2048
#define	DEFAULT_CALLBACK_TIMER				5000


///////////////////////////////////////////////////////////////////////////////
// Security support values
#define PERL_WIN32_PERMS_EXTENSION      "Win32::Perms"


///////////////////////////////////////////////////////////////////////////////
//  Tools to simplfy common tasks:

#define OPEN_SERVICE_CONTROL_MANAGER( pszMachine )    SC_HANDLE hSc = OpenSCManager( pszMachine, SERVICES_ACTIVE_DATABASE, SC_MANAGER_ALL_ACCESS ); \
                                        if( NULL != hSc )                                                   \
                                        {                                                                   \
                                            SC_LOCK sclLock = LockServiceDatabase( hSc );                   \
                                            if( NULL != sclLock )                                           \
                                            {

#define OPEN_SERVICE_CONTROL_MANAGER_READ( pszMachine )    SC_HANDLE hSc = OpenSCManager( pszMachine, SERVICES_ACTIVE_DATABASE, GENERIC_READ ); \
                                        if( NULL != hSc )                                                   \
                                        {                                                                   \
                                            SC_LOCK sclLock = LockServiceDatabase( hSc );                   \
                                            if( NULL != sclLock )                                           \
                                            {


#define CLOSE_SERVICE_CONTROL_MANAGER           UnlockServiceDatabase( sclLock );                           \
                                            }                                                               \
                                            else                                                            \
                                            {                                                               \
                                                gdwLastError = GetLastError();                              \
                                            }                                                               \
                                            CloseServiceHandle( hSc );                                      \
                                        }                                                                   \
                                        else                                                                \
                                        {                                                                   \
                                                gdwLastError = GetLastError();                              \
                                        }


///////////////////////////////////////////////////////////////////////////////
//  Define a method to report exceptions
#ifdef DEBUG
    #define REPORT_EXCEPTION    _tprintf( TEXT( "Error! An Exception has been caught.\n" ) )
#else   //  DEBUG
    #define REPORT_EXCEPTION    
#endif  //  DEBUG


///////////////////////////////////////////////////////////////////////////////
//  
#define SET_CALLBACK(x,y)		        {   \
                                          SV* pSvTEMP = (SV*) (y);                  \
                                          if( NULL != pSvTEMP && SvROK( pSvTEMP ) )                    \
                                          {                                         \
                                                pSvTEMP = SvRV( pSvTEMP );              \
                                          }                                          \
                                          if( NULL == pSvTEMP || SVt_PVCV == SvTYPE( pSvTEMP ) ) gCallback.Set( x, (PVOID) pSvTEMP );   \
                                        }

#if _DEBUG
    TCHAR   gszDebugOutputPath[ MAX_PATH ];
    CRITICAL_SECTION gcsDebugOutput;
#endif // _DEBUG

HINSTANCE   ghDLL = 0;
int     giThread = 0;
int     iTheList = 0;
TCHAR   gszModulePath[ MAX_PATH ];
SERVICE_STATUS_HANDLE ghService = 0;
SERVICE_STATUS gServiceStatus;
SID    *gpSid;
HANDLE  ghServiceThread;
BOOL    gfCallbackMode;
DWORD	gMainThreadId;
DWORD   gServiceThreadId;
DWORD	gServiceMainThreadID;
DWORD   gdwServiceBits;
DWORD   gdwLastError;
DWORD   gdwServiceErrorState = NO_ERROR;
DWORD   gdwState = 0;
DWORD   gdwTimeoutState = SERVICE_START_PENDING;
DWORD	gdwControlsAccepted = SERVICE_ACCEPT_STOP 
                              | SERVICE_ACCEPT_PAUSE_CONTINUE
                              | SERVICE_ACCEPT_SHUTDOWN
                              | SERVICE_ACCEPT_PARAMCHANGE  
                              | SERVICE_ACCEPT_NETBINDCHANGE;

DWORD	gdwServiceType = SERVICE_WIN32_OWN_PROCESS 
                         | SERVICE_INTERACTIVE_PROCESS;
UINT_PTR ghTimer = 0;
DWORD   gdwHandlerTimeout = DEFAULT_HANDLER_TIMEOUT_VALUE;
DWORD   gdwLastControlMessage = SERVICE_START_PENDING;
OSVERSIONINFO gsOSVerInfo;

static  CWinStation gWindowStation;
#ifdef ENABLE_CALLBACKS
	CCallbackList gCallback;
//    pTHX gpPerlObject; 
    HV *gpHvContext;
	CCallbackTimer gCallbackTimer;
#endif // ENABLE_CALLBACKS

HANDLE  ghLogFile = NULL;


#endif // _DAEMON_H

