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)); } }
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)); } } }