Ejemplo n.º 1
0
bool
CArchDaemonWindows::canInstallDaemon(const char* name, bool allUsers)
{
	// if not for all users then use the user's autostart registry.
	// key.  if windows 95 family then use windows 95 services key.
	if (!allUsers || CArchMiscWindows::isWindows95Family()) {
		// check if we can open the registry key
		HKEY key = (allUsers && CArchMiscWindows::isWindows95Family()) ?
							open95ServicesKey() : openUserStartupKey();
		CArchMiscWindows::closeKey(key);
		return (key != NULL);
	}

	// windows NT family services
	else {
		// check if we can open service manager for write
		SC_HANDLE mgr = OpenSCManager(NULL, NULL, GENERIC_WRITE);
		if (mgr == NULL) {
			return false;
		}
		CloseServiceHandle(mgr);

		// check if we can open the registry key for this service
		HKEY key = openNTServicesKey();
		key      = CArchMiscWindows::openKey(key, name);
		key      = CArchMiscWindows::openKey(key, _T("Parameters"));
		CArchMiscWindows::closeKey(key);

		return (key != NULL);
	}
}
Ejemplo n.º 2
0
bool
CArchDaemonWindows::isDaemonInstalled(const char* name, bool allUsers)
{
	// if not for all users then use the user's autostart registry.
	// key.  if windows 95 family then use windows 95 services key.
	if (!allUsers || CArchMiscWindows::isWindows95Family()) {
		// check if we can open the registry key
		HKEY key = (allUsers && CArchMiscWindows::isWindows95Family()) ?
							open95ServicesKey() : openUserStartupKey();
		if (key == NULL) {
			return false;
		}

		// check for entry
		const bool installed = !CArchMiscWindows::readValueString(key,
															name).empty();

		// clean up
		CArchMiscWindows::closeKey(key);

		return installed;
	}

	// windows NT family services
	else {
		// check parameters for this service
		HKEY key = openNTServicesKey();
		key      = CArchMiscWindows::openKey(key, name);
		key      = CArchMiscWindows::openKey(key, _T("Parameters"));
		if (key != NULL) {
			const bool installed = !CArchMiscWindows::readValueString(key,
										_T("CommandLine")).empty();
			CArchMiscWindows::closeKey(key);
			if (!installed) {
				return false;
			}
		}

		// open service manager
		SC_HANDLE mgr = OpenSCManager(NULL, NULL, GENERIC_READ);
		if (mgr == NULL) {
			return false;
		}

		// open the service
		SC_HANDLE service = OpenService(mgr, name, GENERIC_READ);

		// clean up
		if (service != NULL) {
			CloseServiceHandle(service);
		}
		CloseServiceHandle(mgr);

		return (service != NULL);
	}
}
Ejemplo n.º 3
0
bool
ArchDaemonWindows::canInstallDaemon(const char* /*name*/)
{
	// check if we can open service manager for write
	SC_HANDLE mgr = OpenSCManager(NULL, NULL, GENERIC_WRITE);
	if (mgr == NULL) {
		return false;
	}
	CloseServiceHandle(mgr);

	// check if we can open the registry key
	HKEY key = openNTServicesKey();
	ArchMiscWindows::closeKey(key);

	return (key != NULL);
}
Ejemplo n.º 4
0
void
ArchDaemonWindows::installDaemon(const char* name,
				const char* description,
				const char* pathname,
				const char* commandLine,
				const char* dependencies)
{
	// open service manager
	SC_HANDLE mgr = OpenSCManager(NULL, NULL, GENERIC_WRITE);
	if (mgr == NULL) {
		// can't open service manager
		throw XArchDaemonInstallFailed(new XArchEvalWindows);
	}

	// create the service
	SC_HANDLE service = CreateService(
		mgr,
		name,
		name,
		0,
		SERVICE_WIN32_OWN_PROCESS | SERVICE_INTERACTIVE_PROCESS,
		SERVICE_AUTO_START,
		SERVICE_ERROR_NORMAL,
		pathname,
		NULL,
		NULL,
		dependencies,
		NULL,
		NULL);

	if (service == NULL) {
		// can't create service
		DWORD err = GetLastError();
		if (err != ERROR_SERVICE_EXISTS) {
			CloseServiceHandle(mgr);
			throw XArchDaemonInstallFailed(new XArchEvalWindows(err));
		}
	}
	else {
		// done with service (but only try to close if not null)
		CloseServiceHandle(service);
	}

	// done with manager
	CloseServiceHandle(mgr);

	// open the registry key for this service
	HKEY key = openNTServicesKey();
	key      = ArchMiscWindows::addKey(key, name);
	if (key == NULL) {
		// can't open key
		DWORD err = GetLastError();
		try {
			uninstallDaemon(name);
		}
		catch (...) {
			// ignore
		}
		throw XArchDaemonInstallFailed(new XArchEvalWindows(err));
	}

	// set the description
	ArchMiscWindows::setValue(key, _T("Description"), description);

	// set command line
	key = ArchMiscWindows::addKey(key, _T("Parameters"));
	if (key == NULL) {
		// can't open key
		DWORD err = GetLastError();
		ArchMiscWindows::closeKey(key);
		try {
			uninstallDaemon(name);
		}
		catch (...) {
			// ignore
		}
		throw XArchDaemonInstallFailed(new XArchEvalWindows(err));
	}
	ArchMiscWindows::setValue(key, _T("CommandLine"), commandLine);

	// done with registry
	ArchMiscWindows::closeKey(key);
}
Ejemplo n.º 5
0
void
ArchDaemonWindows::serviceMain(DWORD argc, LPTSTR* argvIn)
{
	typedef std::vector<LPCTSTR> ArgList;
	typedef std::vector<std::string> Arguments;
	const char** argv = const_cast<const char**>(argvIn);

	// create synchronization objects
	m_serviceMutex        = ARCH->newMutex();
	m_serviceCondVar      = ARCH->newCondVar();
	
	// register our service handler function
	m_statusHandle = RegisterServiceCtrlHandler(argv[0],
								&ArchDaemonWindows::serviceHandlerEntry);
	if (m_statusHandle == 0) {
		// cannot start as service
		m_daemonResult = -1;
		ARCH->closeCondVar(m_serviceCondVar);
		ARCH->closeMutex(m_serviceMutex);
		return;
	}

	// tell service control manager that we're starting
	m_serviceState = SERVICE_START_PENDING;
	setStatus(m_serviceState, 0, 10000);

	std::string commandLine;

	// if no arguments supplied then try getting them from the registry.
	// the first argument doesn't count because it's the service name.
	Arguments args;
	ArgList myArgv;
	if (argc <= 1) {
		// read command line
		HKEY key = openNTServicesKey();
		key      = ArchMiscWindows::openKey(key, argvIn[0]);
		key      = ArchMiscWindows::openKey(key, _T("Parameters"));
		if (key != NULL) {
			commandLine = ArchMiscWindows::readValueString(key,
												_T("CommandLine"));
		}

		// if the command line isn't empty then parse and use it
		if (!commandLine.empty()) {
			// parse, honoring double quoted substrings
			std::string::size_type i = commandLine.find_first_not_of(" \t");
			while (i != std::string::npos && i != commandLine.size()) {
				// find end of string
				std::string::size_type e;
				if (commandLine[i] == '\"') {
					// quoted.  find closing quote.
					++i;
					e = commandLine.find("\"", i);

					// whitespace must follow closing quote
					if (e == std::string::npos ||
						(e + 1 != commandLine.size() &&
						commandLine[e + 1] != ' ' &&
						commandLine[e + 1] != '\t')) {
						args.clear();
						break;
					}

					// extract
					args.push_back(commandLine.substr(i, e - i));
					i = e + 1;
				}
				else {
					// unquoted.  find next whitespace.
					e = commandLine.find_first_of(" \t", i);
					if (e == std::string::npos) {
						e = commandLine.size();
					}

					// extract
					args.push_back(commandLine.substr(i, e - i));
					i = e + 1;
				}

				// next argument
				i = commandLine.find_first_not_of(" \t", i);
			}

			// service name goes first
			myArgv.push_back(argv[0]);

			// get pointers
			for (size_t j = 0; j < args.size(); ++j) {
				myArgv.push_back(args[j].c_str());
			}

			// adjust argc/argv
			argc = (DWORD)myArgv.size();
			argv = &myArgv[0];
		}
	}

	m_commandLine = commandLine;

	try {
		// invoke daemon function
		m_daemonResult = m_daemonFunc(static_cast<int>(argc), argv);
	}
	catch (XArchDaemonRunFailed& e) {
		setStatusError(e.m_result);
		m_daemonResult = -1;
	}
	catch (...) {
		setStatusError(1);
		m_daemonResult = -1;
	}

	// clean up
	ARCH->closeCondVar(m_serviceCondVar);
	ARCH->closeMutex(m_serviceMutex);

	// we're going to exit now, so set status to stopped
	m_serviceState = SERVICE_STOPPED;
	setStatus(m_serviceState, 0, 10000);
}
Ejemplo n.º 6
0
void
ArchDaemonWindows::uninstallDaemon(const char* name)
{
	// remove parameters for this service.  ignore failures.
	HKEY key = openNTServicesKey();
	key      = ArchMiscWindows::openKey(key, name);
	if (key != NULL) {
		ArchMiscWindows::deleteKey(key, _T("Parameters"));
		ArchMiscWindows::closeKey(key);
	}

	// open service manager
	SC_HANDLE mgr = OpenSCManager(NULL, NULL, GENERIC_WRITE);
	if (mgr == NULL) {
		// can't open service manager
		throw XArchDaemonUninstallFailed(new XArchEvalWindows);
	}

	// open the service.  oddly, you must open a service to delete it.
	SC_HANDLE service = OpenService(mgr, name, DELETE | SERVICE_STOP);
	if (service == NULL) {
		DWORD err = GetLastError();
		CloseServiceHandle(mgr);
		if (err != ERROR_SERVICE_DOES_NOT_EXIST) {
			throw XArchDaemonUninstallFailed(new XArchEvalWindows(err));
		}
		throw XArchDaemonUninstallNotInstalled(new XArchEvalWindows(err));
	}

	// stop the service.  we don't care if we fail.
	SERVICE_STATUS status;
	ControlService(service, SERVICE_CONTROL_STOP, &status);

	// delete the service
	const bool okay = (DeleteService(service) == 0);
	const DWORD err = GetLastError();

	// clean up
	CloseServiceHandle(service);
	CloseServiceHandle(mgr);

	// give windows a chance to remove the service before
	// we check if it still exists.
	ARCH->sleep(1);

	// handle failure.  ignore error if service isn't installed anymore.
	if (!okay && isDaemonInstalled(name)) {
		if (err == ERROR_SUCCESS) {
			// this seems to occur even though the uninstall was successful.
			// it could be a timing issue, i.e., isDaemonInstalled is
			// called too soon. i've added a sleep to try and stop this.
			return;
		}
		if (err == ERROR_IO_PENDING) {
			// this seems to be a spurious error
			return;
		}
		if (err != ERROR_SERVICE_MARKED_FOR_DELETE) {
			throw XArchDaemonUninstallFailed(new XArchEvalWindows(err));
		}
		throw XArchDaemonUninstallNotInstalled(new XArchEvalWindows(err));
	}
}
Ejemplo n.º 7
0
void
CArchDaemonWindows::installDaemon(const char* name,
				const char* description,
				const char* pathname,
				const char* commandLine,
				const char* dependencies,
				bool allUsers)
{
	// if not for all users then use the user's autostart registry.
	// key.  if windows 95 family then use windows 95 services key.
	if (!allUsers || CArchMiscWindows::isWindows95Family()) {
		// open registry
		HKEY key = (allUsers && CArchMiscWindows::isWindows95Family()) ?
							open95ServicesKey() : openUserStartupKey();
		if (key == NULL) {
			// can't open key
			throw XArchDaemonInstallFailed(new XArchEvalWindows);
		}

		// construct entry
		std::string value;
		value += "\"";
		value += pathname;
		value += "\" ";
		value += commandLine;

		// install entry
		CArchMiscWindows::setValue(key, name, value);

		// clean up
		CArchMiscWindows::closeKey(key);
	}

	// windows NT family services
	else {
		// open service manager
		SC_HANDLE mgr = OpenSCManager(NULL, NULL, GENERIC_WRITE);
		if (mgr == NULL) {
			// can't open service manager
			throw XArchDaemonInstallFailed(new XArchEvalWindows);
		}

		// create the service
		SC_HANDLE service = CreateService(mgr,
								name,
								name,
								0,
								SERVICE_WIN32_OWN_PROCESS |
									SERVICE_INTERACTIVE_PROCESS,
								SERVICE_AUTO_START,
								SERVICE_ERROR_NORMAL,
								pathname,
								NULL,
								NULL,
								dependencies,
								NULL,
								NULL);
		if (service == NULL) {
			// can't create service
			// FIXME -- handle ERROR_SERVICE_EXISTS
			DWORD err = GetLastError();
			CloseServiceHandle(mgr);
			throw XArchDaemonInstallFailed(new XArchEvalWindows(err));
		}

		// done with service and manager
		CloseServiceHandle(service);
		CloseServiceHandle(mgr);

		// open the registry key for this service
		HKEY key = openNTServicesKey();
		key      = CArchMiscWindows::openKey(key, name);
		if (key == NULL) {
			// can't open key
			DWORD err = GetLastError();
			try {
				uninstallDaemon(name, allUsers);
			}
			catch (...) {
				// ignore
			}
			throw XArchDaemonInstallFailed(new XArchEvalWindows(err));
		}

		// set the description
		CArchMiscWindows::setValue(key, _T("Description"), description);

		// set command line
		key = CArchMiscWindows::openKey(key, _T("Parameters"));
		if (key == NULL) {
			// can't open key
			DWORD err = GetLastError();
			CArchMiscWindows::closeKey(key);
			try {
				uninstallDaemon(name, allUsers);
			}
			catch (...) {
				// ignore
			}
			throw XArchDaemonInstallFailed(new XArchEvalWindows(err));
		}
		CArchMiscWindows::setValue(key, _T("CommandLine"), commandLine);

		// done with registry
		CArchMiscWindows::closeKey(key);
	}
}
Ejemplo n.º 8
0
void
CArchDaemonWindows::uninstallDaemon(const char* name, bool allUsers)
{
	// if not for all users then use the user's autostart registry.
	// key.  if windows 95 family then use windows 95 services key.
	if (!allUsers || CArchMiscWindows::isWindows95Family()) {
		// open registry
		HKEY key = (allUsers && CArchMiscWindows::isWindows95Family()) ?
							open95ServicesKey() : openUserStartupKey();
		if (key == NULL) {
			// can't open key.  daemon is probably not installed.
			throw XArchDaemonUninstallNotInstalled(new XArchEvalWindows);
		}

		// remove entry
		CArchMiscWindows::deleteValue(key, name);

		// clean up
		CArchMiscWindows::closeKey(key);
	}

	// windows NT family services
	else {
		// remove parameters for this service.  ignore failures.
		HKEY key = openNTServicesKey();
		key      = CArchMiscWindows::openKey(key, name);
		if (key != NULL) {
			CArchMiscWindows::deleteKey(key, _T("Parameters"));
			CArchMiscWindows::closeKey(key);
		}

		// open service manager
		SC_HANDLE mgr = OpenSCManager(NULL, NULL, GENERIC_WRITE);
		if (mgr == NULL) {
			// can't open service manager
			throw XArchDaemonUninstallFailed(new XArchEvalWindows);
		}

		// open the service.  oddly, you must open a service to delete it.
		SC_HANDLE service = OpenService(mgr, name, DELETE);
		if (service == NULL) {
			DWORD err = GetLastError();
			CloseServiceHandle(mgr);
			if (err != ERROR_SERVICE_DOES_NOT_EXIST) {
				throw XArchDaemonUninstallFailed(new XArchEvalWindows(err));
			}
			throw XArchDaemonUninstallNotInstalled(new XArchEvalWindows(err));
		}

		// delete the service
		const bool okay = (DeleteService(service) == 0);
		const DWORD err = GetLastError();

		// clean up
		CloseServiceHandle(service);
		CloseServiceHandle(mgr);

		// handle failure.  ignore error if service isn't installed anymore.
		if (!okay && isDaemonInstalled(name, allUsers)) {
			if (err != ERROR_SERVICE_MARKED_FOR_DELETE) {
				throw XArchDaemonUninstallFailed(new XArchEvalWindows(err));
			}
			throw XArchDaemonUninstallNotInstalled(new XArchEvalWindows(err));
		}
	}
}