void SevenCryptLibrary::Load( const TString& libraryPath ) { Free(); m_dll = ::LoadLibrary( libraryPath.c_str() ); if ( m_dll == NULL ) { throw SevenZipException( GetWinErrMsg( _T( "LoadLibrary" ), GetLastError() ) ); } m_md5Init = reinterpret_cast< TMD5Init >( ::GetProcAddress( m_dll, "MD5Init" ) ); if ( m_md5Init == NULL ) { Free(); throw SevenZipException( _T( "Loaded library is missing required MD5Init function" ) ); } m_md5Update = reinterpret_cast< TMD5Update >( ::GetProcAddress( m_dll, "MD5Update" ) ); if ( m_md5Update == NULL ) { Free(); throw SevenZipException( _T( "Loaded library is missing required MD5Update function" ) ); } m_md5Final = reinterpret_cast< TMD5Final >( ::GetProcAddress( m_dll, "MD5Final" ) ); if ( m_md5Final == NULL ) { Free(); throw SevenZipException( _T( "Loaded library is missing required MD5Final function" ) ); } }
bool ServiceController::removeService( const std::wstring& serviceName ) { SC_HANDLE schSCManager = ::OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS ); if ( schSCManager == NULL ) { DWORD err = ::GetLastError(); cerr << "Error connecting to the Service Control Manager: " << GetWinErrMsg(err) << endl; return false; } SC_HANDLE schService = ::OpenService( schSCManager, serviceName.c_str(), SERVICE_ALL_ACCESS ); if ( schService == NULL ) { cerr << "Could not find a service named " << toUtf8String(serviceName) << " to uninstall." << endl; ::CloseServiceHandle( schSCManager ); return false; } SERVICE_STATUS serviceStatus; // stop service if its running if ( ::ControlService( schService, SERVICE_CONTROL_STOP, &serviceStatus ) ) { cerr << "Service " << toUtf8String(serviceName) << " is currently running. Stopping service." << endl; while ( ::QueryServiceStatus( schService, &serviceStatus ) ) { if ( serviceStatus.dwCurrentState == SERVICE_STOP_PENDING ) { Sleep( 1000 ); } else { break; } } cerr << "Service stopped." << endl; } cerr << "Deleting service " << toUtf8String(serviceName) << "." << endl; bool serviceRemoved = ::DeleteService( schService ); ::CloseServiceHandle( schService ); ::CloseServiceHandle( schSCManager ); if (serviceRemoved) { cerr << "Service deleted successfully." << endl; } else { cerr << "Failed to delete service." << endl; } return serviceRemoved; }
bool ServiceController::installService( const std::wstring& serviceName, const std::wstring& displayName, const std::wstring& serviceDesc, const std::wstring& serviceUser, const std::wstring& servicePassword, const std::string dbpath, int argc, char* argv[] ) { assert(argc >= 1); stringstream commandLine; if ( strchr(argv[0], ':') ) { // a crude test for fully qualified path commandLine << '"' << argv[0] << "\" "; } else { char buffer[256]; assert( _getcwd(buffer, 256) ); commandLine << '"' << buffer << '\\' << argv[0] << "\" "; } for ( int i = 1; i < argc; i++ ) { std::string arg( argv[ i ] ); // replace install command to indicate process is being started as a service if ( arg == "--install" || arg == "--reinstall" ) { arg = "--service"; } else if ( arg == "--dbpath" && i + 1 < argc ) { commandLine << arg << " \"" << dbpath << "\" "; i++; continue; } else if ( arg == "--logpath" && i + 1 < argc ) { commandLine << arg << " \"" << argv[i+1] << "\" "; i++; continue; } else if ( arg.length() > 9 && arg.substr(0, 9) == "--service" ) { // Strip off --service(Name|User|Password) arguments i++; continue; } commandLine << arg << " "; } SC_HANDLE schSCManager = ::OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS ); if ( schSCManager == NULL ) { DWORD err = ::GetLastError(); cerr << "Error connecting to the Service Control Manager: " << GetWinErrMsg(err) << endl; return false; } // Make sure servise doesn't already exist. // TODO: Check to see if service is in "Deleting" status, suggest the user close down Services MMC snap-ins. SC_HANDLE schService = ::OpenService( schSCManager, serviceName.c_str(), SERVICE_ALL_ACCESS ); if ( schService != NULL ) { cerr << "There is already a service named " << toUtf8String(serviceName) << ". Aborting" << endl; ::CloseServiceHandle( schService ); ::CloseServiceHandle( schSCManager ); return false; } std::basic_ostringstream< TCHAR > commandLineWide; commandLineWide << commandLine.str().c_str(); cerr << "Creating service " << toUtf8String(serviceName) << "." << endl; // create new service schService = ::CreateService( schSCManager, serviceName.c_str(), displayName.c_str(), SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, commandLineWide.str().c_str(), NULL, NULL, L"\0\0", NULL, NULL ); if ( schService == NULL ) { DWORD err = ::GetLastError(); cerr << "Error creating service: " << GetWinErrMsg(err) << endl; ::CloseServiceHandle( schSCManager ); return false; } cerr << "Service creation successful." << endl; cerr << "Service can be started from the command line via 'net start \"" << toUtf8String(serviceName) << "\"'." << endl; bool serviceInstalled; // TODO: If neccessary grant user "Login as a Service" permission. if ( !serviceUser.empty() ) { std::wstring actualServiceUser; if ( serviceUser.find(L"\\") == string::npos ) { actualServiceUser = L".\\" + serviceUser; } else { actualServiceUser = serviceUser; } cerr << "Setting service login credentials. User: "******"Setting service login failed. Service has 'LocalService' permissions." << endl; } } // set the service description SERVICE_DESCRIPTION serviceDescription; serviceDescription.lpDescription = (LPTSTR)serviceDesc.c_str(); serviceInstalled = ::ChangeServiceConfig2( schService, SERVICE_CONFIG_DESCRIPTION, &serviceDescription ); if ( serviceInstalled ) { SC_ACTION aActions[ 3 ] = { { SC_ACTION_RESTART, 0 }, { SC_ACTION_RESTART, 0 }, { SC_ACTION_RESTART, 0 } }; SERVICE_FAILURE_ACTIONS serviceFailure; ZeroMemory( &serviceFailure, sizeof( SERVICE_FAILURE_ACTIONS ) ); serviceFailure.cActions = 3; serviceFailure.lpsaActions = aActions; // set service recovery options serviceInstalled = ::ChangeServiceConfig2( schService, SERVICE_CONFIG_FAILURE_ACTIONS, &serviceFailure ); } else { cerr << "Could not set service description. Check the event log for more details." << endl; } ::CloseServiceHandle( schService ); ::CloseServiceHandle( schSCManager ); return serviceInstalled; }
bool ServiceController::installService( const std::wstring& serviceName, const std::wstring& displayName, const std::wstring& serviceDesc, const std::wstring& serviceUser, const std::wstring& servicePassword, const std::string dbpath, int argc, char* argv[] ) { assert(argc >= 1); stringstream commandLine; char exePath[1024]; GetModuleFileNameA( NULL, exePath, sizeof exePath ); commandLine << '"' << exePath << "\" "; for ( int i = 1; i < argc; i++ ) { std::string arg( argv[ i ] ); // replace install command to indicate process is being started as a service if ( arg == "--install" || arg == "--reinstall" ) { arg = "--service"; } else if ( arg == "--dbpath" && i + 1 < argc ) { commandLine << arg << " \"" << dbpath << "\" "; i++; continue; } else if ( arg == "--logpath" && i + 1 < argc ) { commandLine << arg << " \"" << argv[i+1] << "\" "; i++; continue; } else if ( arg == "-f" && i + 1 < argc ) { commandLine << arg << " \"" << argv[i+1] << "\" "; i++; continue; } else if ( arg == "--config" && i + 1 < argc ) { commandLine << arg << " \"" << argv[i+1] << "\" "; i++; continue; } else if ( arg == "--pidfilepath" && i + 1 < argc ) { commandLine << arg << " \"" << argv[i+1] << "\" "; i++; continue; } else if ( arg == "--repairpath" && i + 1 < argc ) { commandLine << arg << " \"" << argv[i+1] << "\" "; i++; continue; } else if ( arg == "--keyfile" && i + 1 < argc ) { commandLine << arg << " \"" << argv[i+1] << "\" "; i++; continue; } else if ( arg.length() > 9 && arg.substr(0, 9) == "--service" ) { // Strip off --service(Name|User|Password) arguments i++; continue; } commandLine << arg << " "; } SC_HANDLE schSCManager = ::OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS ); if ( schSCManager == NULL ) { DWORD err = ::GetLastError(); cerr << "Error connecting to the Service Control Manager: " << GetWinErrMsg(err) << endl; return false; } // Make sure servise doesn't already exist. // TODO: Check to see if service is in "Deleting" status, suggest the user close down Services MMC snap-ins. SC_HANDLE schService = ::OpenService( schSCManager, serviceName.c_str(), SERVICE_ALL_ACCESS ); if ( schService != NULL ) { cerr << "There is already a service named " << toUtf8String(serviceName) << ". Aborting" << endl; ::CloseServiceHandle( schService ); ::CloseServiceHandle( schSCManager ); return false; } std::basic_ostringstream< TCHAR > commandLineWide; commandLineWide << commandLine.str().c_str(); cerr << "Creating service " << toUtf8String(serviceName) << "." << endl; // create new service schService = ::CreateService( schSCManager, serviceName.c_str(), displayName.c_str(), SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS, SERVICE_AUTO_START, SERVICE_ERROR_NORMAL, commandLineWide.str().c_str(), NULL, NULL, L"\0\0", NULL, NULL ); if ( schService == NULL ) { DWORD err = ::GetLastError(); cerr << "Error creating service: " << GetWinErrMsg(err) << endl; ::CloseServiceHandle( schSCManager ); return false; } cerr << "Service creation successful." << endl; cerr << "Service can be started from the command line via 'net start \"" << toUtf8String(serviceName) << "\"'." << endl; bool serviceInstalled; // TODO: If neccessary grant user "Login as a Service" permission. if ( !serviceUser.empty() ) { std::wstring actualServiceUser; if ( serviceUser.find(L"\\") == string::npos ) { actualServiceUser = L".\\" + serviceUser; } else { actualServiceUser = serviceUser; } cerr << "Setting service login credentials. User: "******"Setting service login failed. Service has 'LocalService' permissions." << endl; } } // set the service description SERVICE_DESCRIPTION serviceDescription; serviceDescription.lpDescription = (LPTSTR)serviceDesc.c_str(); serviceInstalled = ::ChangeServiceConfig2( schService, SERVICE_CONFIG_DESCRIPTION, &serviceDescription ); #if 1 if ( ! serviceInstalled ) { #else // This code sets the mongod service to auto-restart, forever. // This might be a fine thing to do except that when mongod or Windows has a crash, the mongo.lock // file is still around, so any attempt at a restart will immediately fail. With auto-restart, we // go into a loop, crashing and restarting, crashing and restarting, until someone comes in and // disables the service or deletes the mongod.lock file. // // I'm leaving the old code here for now in case we solve this and are able to turn SC_ACTION_RESTART // back on. // if ( serviceInstalled ) { SC_ACTION aActions[ 3 ] = { { SC_ACTION_RESTART, 0 }, { SC_ACTION_RESTART, 0 }, { SC_ACTION_RESTART, 0 } }; SERVICE_FAILURE_ACTIONS serviceFailure; ZeroMemory( &serviceFailure, sizeof( SERVICE_FAILURE_ACTIONS ) ); serviceFailure.cActions = 3; serviceFailure.lpsaActions = aActions; // set service recovery options serviceInstalled = ::ChangeServiceConfig2( schService, SERVICE_CONFIG_FAILURE_ACTIONS, &serviceFailure ); } else { #endif cerr << "Could not set service description. Check the event log for more details." << endl; } ::CloseServiceHandle( schService ); ::CloseServiceHandle( schSCManager ); return serviceInstalled; } bool ServiceController::removeService( const std::wstring& serviceName ) { SC_HANDLE schSCManager = ::OpenSCManager( NULL, NULL, SC_MANAGER_ALL_ACCESS ); if ( schSCManager == NULL ) { DWORD err = ::GetLastError(); cerr << "Error connecting to the Service Control Manager: " << GetWinErrMsg(err) << endl; return false; } SC_HANDLE schService = ::OpenService( schSCManager, serviceName.c_str(), SERVICE_ALL_ACCESS ); if ( schService == NULL ) { cerr << "Could not find a service named " << toUtf8String(serviceName) << " to uninstall." << endl; ::CloseServiceHandle( schSCManager ); return false; } SERVICE_STATUS serviceStatus; // stop service if its running if ( ::ControlService( schService, SERVICE_CONTROL_STOP, &serviceStatus ) ) { cerr << "Service " << toUtf8String(serviceName) << " is currently running. Stopping service." << endl; while ( ::QueryServiceStatus( schService, &serviceStatus ) ) { if ( serviceStatus.dwCurrentState == SERVICE_STOP_PENDING ) { Sleep( 1000 ); } else { break; } } cerr << "Service stopped." << endl; } cerr << "Deleting service " << toUtf8String(serviceName) << "." << endl; bool serviceRemoved = ::DeleteService( schService ); ::CloseServiceHandle( schService ); ::CloseServiceHandle( schSCManager ); if (serviceRemoved) { cerr << "Service deleted successfully." << endl; } else { cerr << "Failed to delete service." << endl; } return serviceRemoved; }