BOOL Run()
{
	EventLog log;
	HKEY key;
	try {
		int cnt = 0;
		DnsUpdater updater;
		updater.evLog = &log;
		LONG result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SYSTEM\\CurrentControlSet\\Services\\EasyDynamicDNS"), 0, KEY_READ, &key);
		if (result == ERROR_SUCCESS) {
			DWORD timeout = LoadTimeout(key);
			updater.SetTimeout(timeout);
			for (int i = 0; i < 100; i++) {
				DomainInfo info;
				if (LoadConfig(key, i, info) == TRUE) {
					updater.Add(info);
					cnt++;
				}
			}
			RegCloseKey(key);
			if (cnt == 0)
				throw _T("No configuration information found.");
			updater.Run();
		}
		else
			throw _T("Unable to read configuration");			
	}
	catch (const TCHAR* msg) {
		_tprintf(_T("%s\n"), msg);
		log.LogEvent(EVENTLOG_ERROR_TYPE, msg);
		return FALSE;
	}
	return TRUE;
}
BOOL Install()
{
	EventLog::RegisterEventSource();
	EventLog log;

	// open SCManager
	SC_HANDLE scMgr = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
	if (scMgr == NULL) {
		log.LogLastError("Unable to open service control manager");
		_tprintf(_T("Unable to open service manager!\n"));
		return FALSE;
	}
	// get module path
	TCHAR modulePath[MAX_PATH];
	GetModuleFileName(GetModuleHandle(NULL), modulePath, MAX_PATH);
	// create service
	SC_HANDLE svc = CreateService(scMgr, _T("EasyDynamicDNS"), _T("EasyDynamicDNS"),
		SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_DEMAND_START,
		SERVICE_ERROR_NORMAL, modulePath,
		NULL, NULL, NULL, NULL, NULL);
	if (svc == NULL) {
		log.LogLastError("Unable to install service");
		_tprintf(_T("Unable to install service!\n"));
		CloseServiceHandle(scMgr);
		return FALSE;
	}
	CloseServiceHandle(svc);

	// close SCManager
	CloseServiceHandle(scMgr);

	HKEY key;
	LONG result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SYSTEM\\CurrentControlSet\\Services\\EasyDynamicDNS"), 0, KEY_READ | KEY_WRITE, &key);
	if (result == ERROR_SUCCESS) {
		const TCHAR* desc = _T("Updates dynamic DNS for easyDNS domains");
		RegSetValueEx(key, _T("Description"), 0, REG_EXPAND_SZ, (LPBYTE) desc, (DWORD) _tcslen(desc) + 1);
		DWORD val = 2;
		RegSetValueEx(key, _T("Start"), 0, REG_DWORD, (LPBYTE) &val, (DWORD) sizeof(DWORD));
		RegCloseKey(key);
	}

	log.LogEvent(EVENTLOG_INFORMATION_TYPE, "EasyDynamicDNS installed.");
	return TRUE;
}
BOOL Uninstall()
{
	EventLog log;

	// open SCManager
	SC_HANDLE scMgr = OpenSCManager(NULL, NULL, SC_MANAGER_ALL_ACCESS);
	if (scMgr == NULL) {
		log.LogLastError("Unable to open service control manager");
		_tprintf(_T("Unable to open service manager!\n"));
		return FALSE;
	}

	// open service and delete
	SC_HANDLE svc = OpenService(scMgr, _T("EasyDynamicDNS"), DELETE);
	if (svc == NULL) {
		log.LogLastError("Unable to open service");
		_tprintf(_T("Unable to open service!\n"));
		CloseServiceHandle(scMgr);
		return FALSE;
	}
	if (DeleteService(svc) != TRUE) {
		log.LogLastError("Unable to delete service");
		_tprintf(_T("Unable to delete service!\n"));
		CloseServiceHandle(svc);
		CloseServiceHandle(scMgr);
		return FALSE;
	}
	CloseServiceHandle(svc);

	// close SCManager
	CloseServiceHandle(scMgr);

	log.LogEvent(EVENTLOG_INFORMATION_TYPE, "EasyDynamicDNS uninstalled.");
	EventLog::UnregisterEventSource();
	return TRUE;
}
void EasyDynamicDNSStart(DWORD argc, LPTSTR *argv) 
{ 
	EventLog log;
	myLog = &log;

	log.LogEvent(EVENTLOG_INFORMATION_TYPE, "Service starting...");

	EasyDynamicDNSServiceStatus.dwServiceType        = SERVICE_WIN32; 
	EasyDynamicDNSServiceStatus.dwCurrentState       = SERVICE_START_PENDING; 
	EasyDynamicDNSServiceStatus.dwControlsAccepted   = SERVICE_ACCEPT_STOP;
	EasyDynamicDNSServiceStatus.dwWin32ExitCode      = 0; 
	EasyDynamicDNSServiceStatus.dwServiceSpecificExitCode = 0; 
	EasyDynamicDNSServiceStatus.dwCheckPoint         = 0; 
	EasyDynamicDNSServiceStatus.dwWaitHint           = 0; 

	EasyDynamicDNSServiceStatusHandle = RegisterServiceCtrlHandler(_T("EasyDynamicDNS"), (LPHANDLER_FUNCTION) EasyDynamicDNSCtrlHandler); 
    if (EasyDynamicDNSServiceStatusHandle == (SERVICE_STATUS_HANDLE)0) 
    {
		log.LogLastError(_T("Could not register service control handler"));
		myLog = 0;
		return; 
    } 
 
    // Initialization complete - report running status. 
    EasyDynamicDNSServiceStatus.dwCurrentState       = SERVICE_RUNNING; 
    EasyDynamicDNSServiceStatus.dwCheckPoint         = 0; 
    EasyDynamicDNSServiceStatus.dwWaitHint           = 0; 
 
    if (!SetServiceStatus(EasyDynamicDNSServiceStatusHandle, &EasyDynamicDNSServiceStatus)) 
    {
		log.LogLastError(_T("Could not set service status"));
    } 
 
	try {
		// get settings
		DWORD timeout = 1000 * 60 * 60 * 1;
		HKEY key;
		DnsUpdater updater;
		int cnt = 0;
		updater.evLog = &log;
		LONG result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SYSTEM\\CurrentControlSet\\Services\\EasyDynamicDNS"), 0, KEY_READ, &key);
		if (result == ERROR_SUCCESS) {
			DWORD timeout = LoadTimeout(key);
			updater.SetTimeout(timeout);
			for (int i = 0; i < 100; i++) {
				DomainInfo info;
				if (LoadConfig(key, i, info) == TRUE) {
					updater.Add(info);
					cnt++;
				}
			}
			RegCloseKey(key);
			if (cnt == 0)
				throw _T("No configuration information found.");
		}
		else
			throw _T("Unable to read configuration");			

		log.LogEvent(EVENTLOG_INFORMATION_TYPE, "Service started");

		updater.Run();

		log.LogEvent(EVENTLOG_INFORMATION_TYPE, "Service stopped");
	}
	catch (const TCHAR* msg) {
		log.LogEvent(EVENTLOG_ERROR_TYPE, msg);
	}

	myLog = 0;
	myupdater = 0;

    return; 
}