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;
}
Esempio n. 2
0
// For each registered event logger, print out the current contents of
// the buffer.  This is normally called when the JVM is crashing.
void Events::print_all(outputStream* out) {
    EventLog* log = _logs;
    while (log != NULL) {
        log->print_log_on(out);
        log = log->next();
    }
}
Esempio n. 3
0
int BufSize(EventLog& TheLog)
{
       int nBufSize = sizeof(int);
       EventLog::iterator i;

       for (i = TheLog.begin(); i != TheLog.end(); i++)
       {
               nBufSize += (*i).strGUID.size() + sizeof(char);
               nBufSize += sizeof(int) + sizeof(long);
       }
       return nBufSize;
}
Esempio n. 4
0
bool LoggerPlugin::processEvent(Event *e)
{
    if (e->type() == eEventLog){
        EventLog *l = static_cast<EventLog*>(e);
        if (((l->packetID() == 0) && (l->logLevel() & getLogLevel())) ||
                (l->packetID() && ((getLogLevel() & L_PACKETS) || isLogType(l->packetID())))){
            QString s;
            s = EventLog::make_packet_string(*l);
            if (m_file){
#if defined(Q_OS_WIN) || defined(__OS2__)
                s += "\r\n";
#else
                s += "\n";
#endif
                m_file->writeBlock(s.local8Bit(), s.local8Bit().length());
            }
#ifdef Q_OS_WIN
            QStringList slist = QStringList::split('\n',s);
            for (unsigned i = 0 ; i < slist.count() ; i++){
                QString out = slist[i];
                if (out.length() > 256){
                    while (!out.isEmpty()){
                        QString l;
                        if (out.length() < 256){
                            l = out;
                            out = QString::null;
                        }else{
                            l = out.left(256);
                            out = out.mid(256);
                        }
                        OutputDebugStringA(l.local8Bit().data());
                    }
                }else{
                    OutputDebugStringA(out.local8Bit().data());
                }
                OutputDebugStringA("\n");
            }
#else
            fprintf(stderr, "%s\n", s.local8Bit().data());
#endif
        }
    }
    return false;
}
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 Stop()
{
	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"), SERVICE_ALL_ACCESS);
	if (svc == NULL) {
		log.LogLastError("Unable to open service");
		_tprintf(_T("Unable to open service!\n"));
		CloseServiceHandle(scMgr);
		return FALSE;
	}
	SERVICE_STATUS stat;
	if (ControlService(svc, SERVICE_CONTROL_STOP, &stat) != TRUE) {
		log.LogLastError("Unable to stop service");
		_tprintf(_T("Unable to stop service!\n"));
		CloseServiceHandle(svc);
		CloseServiceHandle(scMgr);
		return FALSE;
	}

	if (!QueryServiceStatus(svc, &stat)){
		log.LogLastError("Unable to query service status");
		_tprintf(_T("Unable to query status!\n"));
		CloseServiceHandle(svc);
		CloseServiceHandle(scMgr);
		return FALSE;
	}

	int tries = 5;

	while (stat.dwCurrentState == SERVICE_STOP_PENDING  &&  tries > 0) 
	{ 
		tries--;
		Sleep(2000);
 
		if (!QueryServiceStatus(svc, &stat)) {
			log.LogLastError("Unable to query service status");
			_tprintf(_T("Unable to query status!\n"));
			CloseServiceHandle(svc);
			CloseServiceHandle(scMgr);
			return FALSE;
		}
	}			

	CloseServiceHandle(svc);

	// close SCManager
	CloseServiceHandle(scMgr);

	return TRUE;
}
Esempio n. 7
0
void ToBuffer(EventLog& TheLog, char* pBuffer, int& nBuffUsed)
{
       int nNumEntries = TheLog.size();
       int nOffset = sizeof(int);
       memcpy(pBuffer, &nNumEntries, sizeof(int));
       EventLog::iterator i;
       int nTemp = 0;

       for (i = TheLog.begin(); i != TheLog.end(); i++)
       {
               nTemp = (*i).strGUID.size();
               memcpy(&pBuffer[nOffset], (*i).strGUID.c_str(), nTemp);
               nOffset += nTemp;
               pBuffer[nOffset] = '\0';
               nOffset += sizeof(char);
               memcpy(&pBuffer[nOffset], &((*i).nEventType), sizeof(int));
               nOffset += sizeof(int);
               memcpy(&pBuffer[nOffset], &((*i).lTimeStamp), sizeof(long));
               nOffset += sizeof(long);
       }
       
       nBuffUsed = nOffset;
}
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;
}
Esempio n. 9
0
int main()
{
  EventLog eventLog;
  eventLog.AddEvent("Make your bed");
  eventLog.AddEvent("Do your homework");
  eventLog.AddEvent("Go to the gym");
  eventLog.AddEvent("Pay the bills");
  eventLog.AddEvent("Eat some food");

  cout << eventLog << endl;

  eventLog.Clear();
  cout << eventLog << endl;

  eventLog.AddEvent("Go running");
  cout << eventLog;
  return 0;
}
Esempio n. 10
0
void FromBuffer(EventLog& TheLog, char* pBuffer, int& nBuffUsed)
{
       int nOffset = sizeof(int);
       int nNumEntries = 0;
       memcpy(&nNumEntries, pBuffer, sizeof(int));
       int i = 0;
       //int nTemp;
       EventRecord     TheRecord;
       for (i = 0; i < nNumEntries; i++)
       {
               TheRecord.strGUID = &pBuffer[nOffset];
               nOffset += TheRecord.strGUID.size() + sizeof(char);
               memcpy(&(TheRecord.nEventType), &pBuffer[nOffset], sizeof(int));
               nOffset += sizeof(int);
               memcpy(&(TheRecord.lTimeStamp), &pBuffer[nOffset], sizeof(long));
               nOffset += sizeof(long);
               TheLog.push_back(TheRecord);
       }
       nBuffUsed = nOffset;
}
Esempio n. 11
0
/*
 * Command line syntax:
 *
 *    ./demo-slave-cpp [remote-dnp3] [local-dnp3] [local-ip] [local-port]
 *
 * Defaults:
 *
 *    remote-dnp3    100
 *    local-dnp3     1
 *    local-ip       127.0.0.1
 *    local-port     4999
 */
int main(int argc, char* argv[])
{
	// Default values
	unsigned remote_dnp3 = 100;
	unsigned local_dnp3  = 1;
	string   local_ip    = "127.0.0.1";
	unsigned local_port  = 4999;

	// Parse the command line arguments using a "fall-through"
	// switch statement.
	if (argc > 1 && std::strcmp("help", argv[1]) == 0) {
		cout << argv[0] << " [remote-dnp3] [local-dnp3] [local-ip] [local-port]" << endl;
		return -1;
	}

	switch (argc) {
	case 5:
		{
			istringstream iss(argv[4]);
			iss >> local_port;
		}
	case 4:
		local_ip = argv[3];
	case 3:
		{
			istringstream iss(argv[2]);
			iss >> local_dnp3;
		}
	case 2:
		{
			istringstream iss(argv[1]);
			iss >> remote_dnp3;
		}
	}

	// Create a log object for the stack to use and configure it
	// with a subscriber that print alls messages to the stdout
	EventLog log;
	log.AddLogSubscriber(LogToStdio::Inst());

	// Specify a FilterLevel for the stack/physical layer to use.
	// Log statements with a lower priority will not be logged.
	const FilterLevel LOG_LEVEL = LEV_INFO;

	// create our demo application that handles commands and
	// demonstrates how to publish data give it a loffer with a
	// unique name and log level
	SlaveDemoApp app(log.GetLogger(LOG_LEVEL, "demoapp"));

	// This is the main point of interaction with the stack. The
	// AsyncStackManager object instantiates master/slave DNP
	// stacks, as well as their physical layers
	AsyncStackManager mgr(log.GetLogger(LOG_LEVEL, "dnp"));

	// Add a TCPv4Server to the manager with the name "tcpserver".
	// The server will wait 3000 ms in between failed bind calls.
	mgr.AddTCPv4Server(
		"tcpserver",
		PhysLayerSettings(LOG_LEVEL, 3000),
		local_ip,
		local_port
	);

	// The master config object for a slave. The default are
	// useable, but understanding the options are important.
	SlaveStackConfig stackConfig;

	// Override the default link addressing
	stackConfig.link.LocalAddr  = local_dnp3;
	stackConfig.link.RemoteAddr = remote_dnp3;

	// The DeviceTemplate struct specifies the structure of the
	// slave's database, as well as the index range of controls and
	// setpoints it accepts.
	DeviceTemplate device(5, 5, 5, 5, 5, 5, 5);
	stackConfig.device = device;

	// Create a new slave on a previously declared port, with a
	// name, log level, command acceptor, and config info This
	// returns a thread-safe interface used for updating the slave's
	// database.
	IDataObserver* pDataObserver = mgr.AddSlave("tcpserver", "slave", LOG_LEVEL, app.GetCmdAcceptor(), stackConfig);

	// Tell the app where to write opdates
	app.SetDataObserver(pDataObserver);

	// Configure signal handlers so we can exit gracefully
	SetDemo(&app);
	signal(SIGTERM, &Terminate);
	signal(SIGABRT, &Terminate);
	signal(SIGINT,  &Terminate);

	app.Run();

	SetDemo(NULL);

	return 0;
}
Esempio n. 12
0
/*
 * Command line syntax:
 *
 *    master2 --help
 *
 */
int main(int argc, char* argv[])
{
	// Check command line options

	cOptions options;
	options.set_master_defaults();
	if( options.decode( argc, argv ) != 0 )
		return 1;

	try {

	// Create a log object for the stack to use and configure it
	// with a subscriber that print alls messages to the stdout.
	EventLog log;
	log.AddLogSubscriber(LogToStdio::Inst());

	// Specify a FilterLevel for the stack/physical layer to use.
	// Log statements with a lower priority will not be logged.
	const FilterLevel LOG_LEVEL = LEV_INFO;

	// Create our demo application that handles commands and
	// demonstrates how to publish data give it a logger with a
	// unique name and log level.
	MasterDemoApp app(log.GetLogger(LOG_LEVEL, "demoapp"));

	// This is the main point of interaction with the stack. The
	// AsyncStackManager object instantiates master/slave DNP
	// stacks, as well as their physical layers.
	AsyncStackManager mgr(log.GetLogger(LOG_LEVEL, "dnp"));

	if( ! options.flagcom ) {
		// Connect via a TCPClient socket to a slave.  The server will
		// wait 3000 ms in between failed bind calls.
		mgr.AddTCPClient(
			options.PortName,
			PhysLayerSettings(LOG_LEVEL, 3000),
			options.ip.c_str(),
			options.port
			);
	} else {

		// Con nect to slave over serial COM port
		mgr.AddSerial(
			options.PortName,
			PhysLayerSettings(LOG_LEVEL, 3000),
			options.serialsets 
			);
	}

	// The master config object for a master. The default are
	// useable, but understanding the options are important.
	MasterStackConfig stackConfig;

	// Override the default link addressing
	stackConfig.link.LocalAddr  = options.local_dnp3;
	stackConfig.link.RemoteAddr = options.remote_dnp3;

	// Set the app instance as a callback for state change notices
	stackConfig.master.mpObserver = &app;

	// Create a new master on a previously declared port, with a
	// name, log level, command acceptor, and config info This
	// returns a thread-safe interface used for processing Master
	// messages.
	app.SetCommandAcceptor(
		mgr.AddMaster(
			options.PortName,      // port name
			"master",              // stack name
			LOG_LEVEL,             // log filter level
			app.GetDataObserver(), // callback for data processing
			stackConfig            // stack configuration
		)
	);

	// Configure signal handlers so we can exit gracefully
	SetDemo(&app);
	signal(SIGTERM, &Terminate);
	signal(SIGABRT, &Terminate);
	signal(SIGINT,  &Terminate);

	app.Run();

	SetDemo(NULL);

	}

	// sometime the dnp3 code will raise an exception
	// for example if you try to connect to a non-existent COM port
	// this catches the exception, preventing a crash,
	// and prints out a hint as to what went wrong

	catch ( Exception & e ) {
		printf("Exception raised by DNP3 code\n%s\n",e.GetErrorString().c_str());
	}




	return 0;
}
Esempio n. 13
0
/*
 * Command line syntax:
 *
 *    ./demo-master-cpp [local-dnp3] [remote-dnp3] [remote-ip] [remote-port]
 *
 * Defaults:
 *
 *    local-dnp3     100
 *    remote-dnp3    1
 *    remote-ip      127.0.0.1
 *    remote-port    4999
 */
int main(int argc, char* argv[])
{
	// Default values
	unsigned local_dnp3  = 100;
	unsigned remote_dnp3 = 1;
	string   remote_ip   = "127.0.0.1";
	unsigned remote_port = 4999;

	// Parse the command line arguments using a "fall-through"
	// switch statement.
	if (argc > 1 && strcmp("help", argv[1]) == 0) {
		cout << argv[0] << " [local-dnp3] [remote-dnp3] [remote-ip] [remote-port]" << endl;
		return -1;
	}

	switch (argc) {
	case 5:
		{
			istringstream iss(argv[4]);
			iss >> remote_port;
		}
	case 4:
		remote_ip = argv[3];
	case 3:
		{
			istringstream iss(argv[2]);
			iss >> remote_dnp3;
		}
	case 2:
		{
			istringstream iss(argv[1]);
			iss >> local_dnp3;
		}
	}

	// Create a log object for the stack to use and configure it
	// with a subscriber that print alls messages to the stdout.
	EventLog log;
	log.AddLogSubscriber(LogToStdio::Inst());

	// Specify a FilterLevel for the stack/physical layer to use.
	// Log statements with a lower priority will not be logged.
	const FilterLevel LOG_LEVEL = LEV_INFO;

	// Create our demo application that handles commands and
	// demonstrates how to publish data give it a logger with a
	// unique name and log level.
	MasterDemoApp app(log.GetLogger(LOG_LEVEL, "demoapp"));

	// This is the main point of interaction with the stack. The
	// AsyncStackManager object instantiates master/slave DNP
	// stacks, as well as their physical layers.
	AsyncStackManager mgr(log.GetLogger(LOG_LEVEL, "dnp"));

	// Connect via a TCPv4Client socket to a slave.  The server will
	// wait 3000 ms in between failed bind calls.
	mgr.AddTCPv4Client(
		"tcpclient",
		PhysLayerSettings(LOG_LEVEL, 3000),
		TcpSettings(remote_ip.c_str(), remote_port)
	);

	// The master config object for a master. The default are
	// useable, but understanding the options are important.
	MasterStackConfig stackConfig;

	// Override the default link addressing
	stackConfig.link.LocalAddr  = local_dnp3;
	stackConfig.link.RemoteAddr = remote_dnp3;

	// Set the app instance as a callback for state change notices
	stackConfig.master.mpObserver = &app;

	// Create a new master on a previously declared port, with a
	// name, log level, command acceptor, and config info This
	// returns a thread-safe interface used for processing Master
	// messages.
	app.SetCommandAcceptor(
		mgr.AddMaster(
			"tcpclient",           // port name
			"master",              // stack name
			LOG_LEVEL,             // log filter level
			app.GetDataObserver(), // callback for data processing
			stackConfig            // stack configuration
		)
	);

	// Configure signal handlers so we can exit gracefully
	SetDemo(&app);
	signal(SIGTERM, &Terminate);
	signal(SIGABRT, &Terminate);
	signal(SIGINT,  &Terminate);

	app.Run();

	SetDemo(NULL);

	return 0;
}
int _tmain(int argc, _TCHAR* argv[])
{
	EventLog::SetSourceName(_T("EasyDynamicDNS"));

	if (argc >= 2) {
		TCHAR cmd[20];
		_tcsncpy(cmd, argv[1], 19);
		cmd[19] = 0;
		_tcslwr(cmd);
		if (_tcscmp(cmd, "/install") == 0) {
			if (Install() != TRUE)
				_tprintf(_T("Installation error.\n"));
			return 0;
		}
		else if (_tcscmp(cmd, "/uninstall") == 0) {
			if (Uninstall() != TRUE)
				_tprintf(_T("Remove error.\n"));
			return 0;
		}
		else if (_tcscmp(cmd, "/start") == 0) {
			if (Start() != TRUE)
				_tprintf(_T("Start error.\n"));
			return 0;
		}
		else if (_tcscmp(cmd, "/stop") == 0) {
			if (Stop() != TRUE)
				_tprintf(_T("Stop error.\n"));
			return 0;
		}
		else if (_tcscmp(cmd, "/config") == 0) {
			if (Config(argc - 2, &argv[2]) != TRUE)
				_tprintf(_T("Config error\n"));
			return 0;
		}
		else if (_tcscmp(cmd, "/run") == 0) {
			if (Run() != TRUE)
				_tprintf(_T("Run error\n"));
			return 0;
		}
		else if (_tcscmp(cmd, "/help") == 0) {
			Usage();
			return 0;
		}
		else {
			_tprintf ("Syntax error\n");
			Usage();
			return 1;
		}
	}

	// run service

	SERVICE_TABLE_ENTRY DispatchTable[] = 
	{
		{ _T("EasyDynamicDNS"), (LPSERVICE_MAIN_FUNCTION) EasyDynamicDNSStart },
		{ NULL, NULL }
	};

	if (!StartServiceCtrlDispatcher(DispatchTable)) {
		EventLog log;
		log.LogLastError("Service run error");
	}

	return 0;
}
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; 
} 
BOOL Config(int argc, _TCHAR* argv[])
{
	EventLog log;
	HKEY key;
	LONG result = RegOpenKeyEx(HKEY_LOCAL_MACHINE, _T("SYSTEM\\CurrentControlSet\\Services\\EasyDynamicDNS"), 0, KEY_READ | KEY_WRITE, &key);
	if (result == ERROR_SUCCESS) {
		tstring command = _T("show");
		if (argc > 0)
			command = argv[0];
		if (_tcsicmp(command.c_str(), _T("show")) == 0) {
			if (argc > 1)
				_tprintf(_T("Syntax error; use \"/config help\" for more information.\n"));
			else {
				DWORD timeout = LoadTimeout(key);
				_tprintf(_T("Update dynamic DNS domains every %d minutes.\n\n"), timeout / (1000 * 60));
				int i = 0;
				BOOL found;
				do {
					DomainInfo info;
					found = LoadConfig(key, i, info);
					if (found == TRUE) {
						_tprintf(_T("Entry #%d\n"), i);
						_tprintf(_T("  Host Name:        %s\n"), info.hostname.c_str());
						_tprintf(_T("  Top Level Domain: %s\n"), info.tld.c_str());
						_tprintf(_T("  My IP Address:    %s\n"), (info.myip.length() > 0 ? info.myip.c_str() : _T("<my PC's address>")));
						_tprintf(_T("  MX:               %s\n"), info.mx.c_str());
						_tprintf(_T("  Back MX:          %s\n"), info.backmx.c_str());
						_tprintf(_T("  Wildcard:         %s\n"), info.wildcard.c_str());
						_tprintf(_T("  easyDNS URL:      %s\n"), (info.easydnsurl.length() > 0 ? info.easydnsurl.c_str() : _T("http://members.easydns.com/dyn/dyndns.php")));
						_tprintf(_T("  HTTP Timeout:     %d sec\n"), info.httpTimeout / 1000);
						_tprintf(_T("  Username:         %s\n"), info.username.c_str());
						_tprintf(_T("  Password:         ********\n"));
						_tprintf(_T("  Proxy:            %s\n"), info.proxy.c_str());
						_tprintf(_T("  Proxy Port:       %d\n"), info.proxyPort);
					}
					i++;
				}
				while (i < 100);
			}
		}
		else if (_tcsicmp(command.c_str(), _T("add")) == 0) {
			if (argc != 13)
				_tprintf(_T("Syntax error; use \"/config help\" for more information.\n"));
			else {
				int i = 0;
				BOOL found;
				do {
					DomainInfo info;
					found = LoadConfig(key, i, info);
					if (found != TRUE) {
						info.hostname = argv[1];
						info.tld = argv[2];
						info.myip = argv[3];
						info.mx = argv[4];
						info.backmx = argv[5];
						info.wildcard = argv[6];
						if (argv[7][0] != 0)
							info.easydnsurl = argv[7];
						info.httpTimeout = atoi(argv[8]) * 1000;
						info.username = argv[9];
						info.password = argv[10];
						//info.domain = argv[11];
						info.proxy = argv[11];
						info.proxyPort = atoi(argv[12]);
						if (AddConfig(key, i, info) != TRUE) {
							TCHAR x[50];
							wsprintf(x, _T("DomainInfo%03d"), i);
							_tprintf(_T("Error saving to registry\n"));
							RegDeleteKey(key, x);
						}
					}
					i++;
				}
				while (i < 100 && found == TRUE);
				if (found == TRUE)
					_tprintf(_T("There is not room for another entry.\n"));
			}
		}
		else if (_tcsicmp(command.c_str(), _T("prompt")) == 0) {
			if (argc != 1)
				_tprintf(_T("Syntax error; use \"/config help\" for more information.\n"));
			else {
				int i = 0;
				BOOL found;
				do {
					DomainInfo info;
					found = LoadConfig(key, i, info);
					if (found != TRUE) {
						TCHAR buf[256];
						_tprintf("Enter your setup as described below. This program does not do much validation;\n"
							"please follow the instructions carefully.\n\n");
						_tprintf("Host Name = the full hostname being updated (REQUIRED)\n");
						info.hostname = _getts(buf);
						_tprintf("Top Level Domain = the root domain of your hostname, for example if your\n"
							"hostname is \"example.co.uk\" you should set \"tld\" to \"co.uk\". This field\n"
							"can be omitted in cases of second level domains like example.com\n");
						info.tld = _getts(buf);
						_tprintf("My IP Address = the IP address of the client to be updated. Send \"0.0.0.0\"\n"
							"to set record to an offline state (sets record to \"offline.easydns.com\"). If\n"
							"you are behind a firewall or NAT set this to 1.1.1.1 and our system will detect\n"
							"your remote IP for you. Leave blank to use your PC's address.\n");
						info.myip = _getts(buf);
						_tprintf("MX = use this parameter as the MX handler for the domain being updated, it\n"
							"defaults to preference 5. (OPTIONAL)\n");
						info.mx = _getts(buf);
						_tprintf("Back MX = either \"YES\" or \"NO\", if \"YES\" we set smtp.easydns.com to\n"
							"be a backup mail spool for domain being updated at preference 100. (OPTIONAL)\n");
						info.backmx = _getts(buf);
						_tprintf("Wildcard = either \"ON\" or \"OFF\", if \"ON\" sets a wildcard host record for\n"
							"the domain being updated equal to the IP address specified in \"myip\" (OPTIONAL)\n");
						info.wildcard = _getts(buf);

						_tprintf("easyDNS URL = the url to send the update to; defaults to\n"
							"http://members.easydns.com/dyn/dyndns.php (OPTIONAL)\n");
						info.easydnsurl = _getts(buf);
						_tprintf("HTTP Timeout = Number of seconds to allow the request to complete. 0 for\n"
							"no timeout.\n");
						info.httpTimeout = atoi(_getts(buf)) * 1000;
						_tprintf("Username = easyDNS user name (REQUIRED)\n");
						info.username = _getts(buf);
						_tprintf("Password = easyDNS password (which is stored securely) (REQUIRED)\n");
						info.password = _getts(buf);
						_tprintf("Proxy = proxy server (leave blank if you don't have one)\n");
						info.proxy = _getts(buf);
						_tprintf("Proxy Port = proxy port; 0 if you don't have one\n");
						info.proxyPort = atoi(_getts(buf));

						if (AddConfig(key, i, info) != TRUE) {
							TCHAR x[50];
							wsprintf(x, _T("DomainInfo%03d"), i);
							_tprintf(_T("Error saving to registry\n"));
							RegDeleteKey(key, x);
						}
					}
					i++;
				}
				while (i < 100 && found == TRUE);
				if (found == TRUE)
					_tprintf(_T("There is not room for another entry.\n"));
			}
		}
		else if (_tcsicmp(command.c_str(), _T("delete")) == 0) {
			if (argc != 2)
				_tprintf(_T("Syntax error; use \"/config help\" for more information.\n"));
			else {
				int i = atoi(argv[1]);
				TCHAR x[50];
				wsprintf(x, _T("DomainInfo%03d"), i);
				if (RegDeleteKey(key, x) != ERROR_SUCCESS)
					_tprintf(_T("Item %d not found.\n"), i);
			}
		}
		else if (_tcsicmp(command.c_str(), _T("clear")) == 0) {
			if (argc != 1)
				_tprintf(_T("Syntax error; use \"/config help\" for more information.\n"));
			else {
				for (int i = 0; i < 100; i++) {
					TCHAR x[50];
					wsprintf(x, _T("DomainInfo%03d"), i);
					RegDeleteKey(key, x);
				}
			}
		}
		else if (_tcsicmp(command.c_str(), _T("timeout")) == 0) {
			if (argc != 2)
				_tprintf(_T("Syntax error; use \"/config help\" for more information.\n"));
			else {
				int i = atoi(argv[1]) * 1000 * 60;
				if (SaveTimeout(key, i) != TRUE)
					_tprintf(_T("Unable to set timeout.\n"));
			}
		}
		else {
			_tprintf(_T("Subcommands:\n"));
			_tprintf(_T("\tprompt: prompt for setup with help\n"));
			_tprintf(_T("\tadd hostname tld myip mx backmx wildcard easydnsurl httpTimeoutSec username password proxy proxyPort\n"));
			_tprintf(_T("\tdelete n: delete entry number n\n"));
			_tprintf(_T("\tclear: erase the entired configuration (be careful!)\n"));
			_tprintf(_T("\ttimeout n: set the timeout to n minutes\n"));
			_tprintf(_T("\thelp: show this text\n"));
			_tprintf(_T("\tshow: display the configuration\n"));
		}
		RegCloseKey(key);
	}
	else {
		log.LogLastError("Unable to open registry, please install first");
		_tprintf(_T("Unable to open registry\n"));
		return FALSE;
	}
	return TRUE;
}