www.pudn.com > tdi_fw.zip > main.c


// $Id: main.c,v 1.1.1.1 2002/09/24 11:12:16 dev Exp $ 
 
#include  
#include  
#include  
 
#include "tdi_fw_svc.h" 
 
#define CONFIG_SUBKEY	"SYSTEM\\CurrentControlSet\\Services\\tdi_fw_svc" 
 
BOOL g_console = TRUE; 
 
static SERVICE_STATUS          ssStatus;       // current status of the service 
static SERVICE_STATUS_HANDLE   sshStatusHandle; 
 
static void		AddEventSource(const char *ident); 
 
static void		install_service(const char *config); 
static void		remove_service(void); 
 
static VOID WINAPI service_main(DWORD dwArgc, LPTSTR *lpszArgv); 
static VOID WINAPI service_ctrl(DWORD dwCtrlCode); 
 
static BOOL ReportStatusToSCMgr(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint); 
 
static BOOL add_config_info(HANDLE schService, const char *config); 
 
int 
main(int argc, char **argv) 
{ 
    static SERVICE_TABLE_ENTRY dispatch_table[] = { 
        {"tdi_fw_svc", service_main}, 
        {NULL, NULL} 
    }; 
 
	_LEAK_CHECK; 
 
	if (argc >= 2) { 
		const char *param = argv[1]; 
		 
		if (strcmp(param, "install") == 0) { 
			if (argc < 3) { 
				fprintf(stderr, "Use: tdi_fw_svc install \n"); 
				return -1; 
			} 
		 
			install_service(argv[2]); 
		 
		} else if (strcmp(param, "remove") == 0) 
			remove_service(); 
		else if (strcmp(param, "debug") == 0) { 
 
			if (argc < 3) { 
				fprintf(stderr, "Use: tdi_fw_svc debug \n"); 
				return -1; 
			} 
 
			if (start(argv[2])) { 
				printf("press any key to exit...\n"); 
				getch(); 
				printf("exiting...\n"); 
 
				stop(); 
			} 
 
		} else { 
			fprintf(stderr, "Use: tdi_fw_svc install|remove|debug\n"); 
		} 
	} else { 
 
		g_console = FALSE; 
 
		// run as service 
		if (!StartServiceCtrlDispatcher(dispatch_table)) 
			winerr("main: StartServiceCtrlDispatcher"); 
 
	} 
 
	return 0; 
} 
 
void 
install_service(const char *config) 
{ 
	SC_HANDLE	schService; 
	SC_HANDLE	schSCManager; 
 
	CHAR szPath[MAX_PATH]; 
 
	AddEventSource("tdi_fw_svc"); 
 
	if (GetModuleFileName(NULL, szPath, sizeof(szPath)) == 0) { 
		winerr("install_service: GetModuleFileName"); 
		return; 
	} 
 
	schSCManager = OpenSCManager( 
						NULL,					// machine (NULL == local) 
						NULL,					// database (NULL == default) 
						SC_MANAGER_ALL_ACCESS);	// access required 
 
	if (schSCManager != NULL) { 
 
		schService = CreateService( 
			schSCManager,				// SCManager database 
			"tdi_fw_svc",				// name of service 
			"tdi_fw_svc",				// name to display 
			SERVICE_ALL_ACCESS, 		// desired access 
			SERVICE_WIN32_OWN_PROCESS,	// service type 
			SERVICE_AUTO_START,		    // start type 
			SERVICE_ERROR_NORMAL,		// error control type 
			szPath, 					// service's binary 
			NULL,						// no load ordering group 
			NULL,						// no tag identifier 
			NULL,						// dependencies 
			NULL,						// LocalSystem account 
			NULL);						// no password 
 
		if (schService != NULL) { 
			printf("tdi_fw_svc service has been installed\n"); 
 
			if (!add_config_info(schService, config)) 
				fprintf(stderr, "Can't store config info! Service will use defaults.\n"); 
 
			CloseServiceHandle(schService); 
		} else 
			winerr("install_service: CreateService"); 
 
		CloseServiceHandle(schSCManager); 
	} 
	else 
		winerr("install_service: OpenSCManager"); 
} 
 
void 
remove_service(void) 
{ 
	SC_HANDLE	schService; 
	SC_HANDLE	schSCManager; 
 
	schSCManager = OpenSCManager( 
						NULL,					// machine (NULL == local) 
						NULL,					// database (NULL == default) 
						SC_MANAGER_ALL_ACCESS); // access required 
	 
	if (schSCManager != NULL) { 
		schService = OpenService(schSCManager, "tdi_fw_svc", SERVICE_ALL_ACCESS); 
 
		if (schService != NULL) { 
 
			// try to stop the service 
			if (ControlService(schService, SERVICE_CONTROL_STOP, &ssStatus)) { 
				printf("stopping..."); 
				Sleep(1000); 
 
				while(QueryServiceStatus( schService, &ssStatus)) { 
					if (ssStatus.dwCurrentState == SERVICE_STOP_PENDING) { 
						printf("."); 
						Sleep( 1000 ); 
					} 
					else 
						break; 
				} 
 
				printf("\n"); 
 
				if (ssStatus.dwCurrentState == SERVICE_STOPPED) 
					printf("stopped\n"); 
				else 
					printf("failed to stop\n"); 
			} 
 
			// now remove the service 
			if (DeleteService(schService)) 
				printf("service has been removed\n"); 
			else 
				winerr("install_service: DeleteService"); 
 
			CloseServiceHandle(schService); 
		} 
		else 
			winerr("install_service: OpenService"); 
 
		CloseServiceHandle(schSCManager); 
	} 
	else 
		winerr("install_service: OpenSCManager"); 
} 
 
VOID WINAPI 
service_main(DWORD dwArgc, LPTSTR *lpszArgv) 
{ 
	HKEY hkey = NULL; 
	char *config = NULL; 
	DWORD type, config_size, status; 
 
	// register our service control handler: 
	// 
	sshStatusHandle = RegisterServiceCtrlHandler("tdi_fw_svc", service_ctrl); 
	if (sshStatusHandle == 0) { 
		winerr("install_service: RegisterServiceCtrlHandler"); 
		goto cleanup; 
	} 
 
	// SERVICE_STATUS members that don't change in example 
	// 
	ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS; 
	ssStatus.dwServiceSpecificExitCode = 0; 
 
	// report the status to the service control manager. 
	// 
	if (!ReportStatusToSCMgr( 
		SERVICE_START_PENDING, // service state 
		NO_ERROR,			   // exit code 
		3000))				   // wait hint 
		goto cleanup; 
 
	/* get config name from registry */ 
 
	if ((status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, CONFIG_SUBKEY, 0, KEY_QUERY_VALUE, 
		&hkey)) != ERROR_SUCCESS) { 
		SetLastError(status); 
		winerr("RegOpenKeyEx"); 
		goto cleanup; 
	} 
 
	if ((status = RegQueryValueEx(hkey, "config", 0, &type, NULL, &config_size)) != ERROR_SUCCESS) { 
		SetLastError(status); 
		winerr("RegOpenKeyEx"); 
		goto cleanup; 
	} 
 
	if (type != REG_SZ) { 
		error("Invalid type for config value in registry"); 
		SetLastError(ERROR_INVALID_DATA); 
		goto cleanup; 
	} 
 
	config = (char *)malloc(config_size); 
	if (config == NULL) { 
		liberr("malloc"); 
		goto cleanup; 
	} 
 
	if ((status = RegQueryValueEx(hkey, "config", 0, NULL, config, &config_size)) != ERROR_SUCCESS) { 
		SetLastError(status); 
		winerr("RegOpenKeyEx"); 
		goto cleanup; 
	} 
 
	if (start(config)) { 
 
		// start success 
 
		// report the status to the service control manager. 
		// 
		if (!ReportStatusToSCMgr( 
			SERVICE_RUNNING,       // service state 
			NO_ERROR,              // exit code 
			0))                    // wait hint 
			goto cleanup; 
 
		wait(); 
 
		SetLastError(0); 
	} 
	 
cleanup: 
 
	// try to report the stopped status to the service control manager. 
	// 
	if (sshStatusHandle != 0) 
		ReportStatusToSCMgr(SERVICE_STOPPED, GetLastError(), 0); 
 
	if (hkey != NULL) 
		RegCloseKey(hkey); 
	free(config); 
} 
 
// 
//  FUNCTION: ReportStatusToSCMgr() 
// 
//  PURPOSE: Sets the current status of the service and 
//           reports it to the Service Control Manager 
// 
//  PARAMETERS: 
//    dwCurrentState - the state of the service 
//    dwWin32ExitCode - error code to report 
//    dwWaitHint - worst case estimate to next checkpoint 
// 
//  RETURN VALUE: 
//    TRUE  - success 
//    FALSE - failure 
// 
//  COMMENTS: 
// 
BOOL 
ReportStatusToSCMgr(DWORD dwCurrentState, DWORD dwWin32ExitCode, DWORD dwWaitHint) 
{ 
    static DWORD dwCheckPoint = 1; 
 
    if (dwCurrentState == SERVICE_START_PENDING) 
        ssStatus.dwControlsAccepted = 0; 
    else 
        ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP; 
 
    ssStatus.dwCurrentState = dwCurrentState; 
    ssStatus.dwWin32ExitCode = dwWin32ExitCode; 
    ssStatus.dwWaitHint = dwWaitHint; 
 
    if (dwCurrentState == SERVICE_RUNNING || dwCurrentState == SERVICE_STOPPED) 
        ssStatus.dwCheckPoint = 0; 
    else 
        ssStatus.dwCheckPoint = dwCheckPoint++; 
 
    // Report the status of the service to the service control manager. 
    // 
 
    if (!SetServiceStatus(sshStatusHandle, &ssStatus)) { 
        winerr("install_service: SetServiceStatus"); 
		return FALSE; 
	} 
 
    return TRUE; 
} 
 
// 
//  FUNCTION: service_ctrl 
// 
//  PURPOSE: This function is called by the SCM whenever 
//           ControlService() is called on this service. 
// 
//  PARAMETERS: 
//    dwCtrlCode - type of control requested 
// 
//  RETURN VALUE: 
//    none 
// 
//  COMMENTS: 
// 
VOID WINAPI 
service_ctrl(DWORD dwCtrlCode) 
{ 
	// Handle the requested control code. 
	// 
	switch(dwCtrlCode) { 
		// Stop the service. 
		// 
		// SERVICE_STOP_PENDING should be reported before 
		// setting the Stop Event - hServerStopEvent - in 
		// ServiceStop().  This avoids a race condition 
		// which may result in a 1053 - The Service did not respond... 
		// error. 
		case SERVICE_CONTROL_STOP: 
			ReportStatusToSCMgr(SERVICE_STOP_PENDING, NO_ERROR, 0); 
			 
			// stop it! 
			stop(); 
			 
			return; 
 
		// Update the service status. 
		// 
		case SERVICE_CONTROL_INTERROGATE: 
			break; 
 
		// invalid control code 
		// 
		default: 
			break; 
 
	} 
 
	ReportStatusToSCMgr(ssStatus.dwCurrentState, NO_ERROR, 0); 
} 
 
/* Taken from MSDN. */ 
void 
AddEventSource(const char *ident) 
{ 
	HKEY hk;  
	DWORD dwData;  
	char szFilePath[_MAX_PATH]; 
	char key[_MAX_PATH]; 
	 
	// Add your source name as a subkey under the Application  
	// key in the EventLog registry key.  
	_snprintf(key, sizeof(key), "SYSTEM\\CurrentControlSet\\Services\\EventLog\\Application\\%s", ident); 
 
	if (RegCreateKey(HKEY_LOCAL_MACHINE, key, &hk)) { 
		printf("Could not create the registry key.");  
		exit(-1); 
	} 
  
	// Set the name of the message file.  
	GetModuleFileName(NULL, szFilePath, sizeof(szFilePath)); 
	// Add the name to the EventMessageFile subkey.  
  
	if (RegSetValueEx(hk,			  // subkey handle  
			"EventMessageFile", 	  // value name  
			0,						  // must be zero  
			REG_EXPAND_SZ,			  // value type  
			(LPBYTE) szFilePath,		   // pointer to value data  
			strlen(szFilePath) + 1)) {		 // length of value data  
		printf("Could not set the event message file.");  
		exit(-1); 
	} 
  
	// Set the supported event types in the TypesSupported subkey.  
  
	dwData = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE |  
		EVENTLOG_INFORMATION_TYPE | EVENTLOG_AUDIT_SUCCESS | EVENTLOG_AUDIT_FAILURE;  
  
	if (RegSetValueEx(hk,	   // subkey handle  
			"TypesSupported",  // value name  
			0,				   // must be zero  
			REG_DWORD,		   // value type  
			(LPBYTE) &dwData,  // pointer to value data  
			sizeof(DWORD))){	// length of value data  
		printf("Could not set the supported types.");  
		exit(-1); 
	} 
  
	RegCloseKey(hk);  
} 
 
BOOL 
add_config_info(HANDLE schService, const char *config) 
{ 
	BOOL result = FALSE; 
	HKEY hkey = NULL; 
	DWORD status; 
 
	if ((status = RegOpenKeyEx(HKEY_LOCAL_MACHINE, CONFIG_SUBKEY, 
		0, KEY_SET_VALUE, &hkey)) != ERROR_SUCCESS) { 
		SetLastError(status); 
		winerr("RegOpenKeyEx"); 
		goto done; 
	} 
 
	if ((status = RegSetValueEx(hkey, "config", 0, REG_SZ, config, 
		strlen(config) + 1)) != ERROR_SUCCESS) { 
		SetLastError(status); 
		winerr("RegSetValueEx"); 
		goto done; 
	} 
 
	result = TRUE; 
 
done: 
	if (hkey != NULL) 
		RegCloseKey(hkey); 
	return result; 
}