~ubuntu-branches/ubuntu/trusty/mongodb/trusty-proposed

« back to all changes in this revision

Viewing changes to util/ntservice.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Antonin Kral
  • Date: 2010-01-29 19:48:45 UTC
  • Revision ID: james.westby@ubuntu.com-20100129194845-8wbmkf626fwcavc9
Tags: upstream-1.3.1
ImportĀ upstreamĀ versionĀ 1.3.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
// ntservice.cpp
 
2
 
 
3
/*    Copyright 2009 10gen Inc.
 
4
 *
 
5
 *    Licensed under the Apache License, Version 2.0 (the "License");
 
6
 *    you may not use this file except in compliance with the License.
 
7
 *    You may obtain a copy of the License at
 
8
 *
 
9
 *    http://www.apache.org/licenses/LICENSE-2.0
 
10
 *
 
11
 *    Unless required by applicable law or agreed to in writing, software
 
12
 *    distributed under the License is distributed on an "AS IS" BASIS,
 
13
 *    WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
14
 *    See the License for the specific language governing permissions and
 
15
 *    limitations under the License.
 
16
 */
 
17
 
 
18
#include "stdafx.h"
 
19
#include "ntservice.h"
 
20
 
 
21
#if defined(_WIN32)
 
22
 
 
23
namespace mongo {
 
24
 
 
25
        void shutdown();
 
26
 
 
27
        SERVICE_STATUS_HANDLE ServiceController::_statusHandle = null;
 
28
        std::wstring ServiceController::_serviceName;
 
29
        ServiceCallback ServiceController::_serviceCallback = null;
 
30
 
 
31
        ServiceController::ServiceController() {
 
32
    }
 
33
    
 
34
    bool ServiceController::installService( const std::wstring& serviceName, const std::wstring& displayName, const std::wstring& serviceDesc, int argc, char* argv[] ) {
 
35
        
 
36
        std::string commandLine;
 
37
        
 
38
        for ( int i = 0; i < argc; i++ ) {
 
39
                        std::string arg( argv[ i ] );
 
40
                        
 
41
                        // replace install command to indicate process is being started as a service
 
42
                        if ( arg == "--install" )
 
43
                                arg = "--service";
 
44
                                
 
45
                        commandLine += arg + " ";
 
46
                }
 
47
                
 
48
                SC_HANDLE schSCManager = ::OpenSCManager( null, null, SC_MANAGER_ALL_ACCESS );
 
49
                if ( schSCManager == null )
 
50
                        return false;
 
51
                
 
52
                std::basic_ostringstream< TCHAR > commandLineWide;
 
53
        commandLineWide << commandLine.c_str();
 
54
 
 
55
                // create new service
 
56
                SC_HANDLE schService = ::CreateService( schSCManager, serviceName.c_str(), displayName.c_str(),
 
57
                                                                                                SERVICE_ALL_ACCESS, SERVICE_WIN32_OWN_PROCESS,
 
58
                                                                                                SERVICE_AUTO_START, SERVICE_ERROR_NORMAL,
 
59
                                                                                                commandLineWide.str().c_str(), null, null, L"\0\0", null, null );
 
60
 
 
61
                if ( schService == null ) {
 
62
                        ::CloseServiceHandle( schSCManager );
 
63
                        return false;
 
64
                }
 
65
 
 
66
                SERVICE_DESCRIPTION serviceDescription;
 
67
                serviceDescription.lpDescription = (LPTSTR)serviceDesc.c_str();
 
68
                
 
69
                // set new service description
 
70
                bool serviceInstalled = ::ChangeServiceConfig2( schService, SERVICE_CONFIG_DESCRIPTION, &serviceDescription );
 
71
                
 
72
                if ( serviceInstalled ) {
 
73
                        SC_ACTION aActions[ 3 ] = { { SC_ACTION_RESTART, 0 }, { SC_ACTION_RESTART, 0 }, { SC_ACTION_RESTART, 0 } };
 
74
                        
 
75
                        SERVICE_FAILURE_ACTIONS serviceFailure;
 
76
                        ZeroMemory( &serviceFailure, sizeof( SERVICE_FAILURE_ACTIONS ) );
 
77
                        serviceFailure.cActions = 3;
 
78
                        serviceFailure.lpsaActions = aActions;
 
79
                        
 
80
                        // set service recovery options
 
81
                        serviceInstalled = ::ChangeServiceConfig2( schService, SERVICE_CONFIG_FAILURE_ACTIONS, &serviceFailure );
 
82
                }
 
83
                
 
84
                ::CloseServiceHandle( schService );
 
85
                ::CloseServiceHandle( schSCManager );
 
86
                
 
87
                return serviceInstalled;
 
88
    }
 
89
    
 
90
    bool ServiceController::removeService( const std::wstring& serviceName ) {
 
91
                SC_HANDLE schSCManager = ::OpenSCManager( null, null, SC_MANAGER_ALL_ACCESS );
 
92
                if ( schSCManager == null )
 
93
                        return false;
 
94
 
 
95
                SC_HANDLE schService = ::OpenService( schSCManager, serviceName.c_str(), SERVICE_ALL_ACCESS );
 
96
 
 
97
                if ( schService == null ) {
 
98
                        ::CloseServiceHandle( schSCManager );
 
99
                        return false;
 
100
                }
 
101
 
 
102
                SERVICE_STATUS serviceStatus;
 
103
                
 
104
                // stop service if running
 
105
                if ( ::ControlService( schService, SERVICE_CONTROL_STOP, &serviceStatus ) ) {
 
106
                        while ( ::QueryServiceStatus( schService, &serviceStatus ) ) {
 
107
                                if ( serviceStatus.dwCurrentState == SERVICE_STOP_PENDING )
 
108
                                        Sleep( 1000 );
 
109
                        }
 
110
                }
 
111
 
 
112
                bool serviceRemoved = ::DeleteService( schService );
 
113
                
 
114
                ::CloseServiceHandle( schService );
 
115
                ::CloseServiceHandle( schSCManager );
 
116
 
 
117
                return serviceRemoved;
 
118
    }
 
119
    
 
120
    bool ServiceController::startService( const std::wstring& serviceName, ServiceCallback startService ) {
 
121
        _serviceName = serviceName;
 
122
                _serviceCallback = startService;
 
123
        
 
124
        SERVICE_TABLE_ENTRY dispTable[] = {
 
125
                        { (LPTSTR)serviceName.c_str(), (LPSERVICE_MAIN_FUNCTION)ServiceController::initService },
 
126
                        { null, null }
 
127
                };
 
128
 
 
129
                return StartServiceCtrlDispatcher( dispTable );
 
130
    }
 
131
    
 
132
    bool ServiceController::reportStatus( DWORD reportState, DWORD waitHint ) {
 
133
                if ( _statusHandle == null )
 
134
                        return false;
 
135
 
 
136
                static DWORD checkPoint = 1;
 
137
                
 
138
                SERVICE_STATUS ssStatus;
 
139
 
 
140
                ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
 
141
                ssStatus.dwServiceSpecificExitCode = 0;
 
142
                ssStatus.dwControlsAccepted = reportState == SERVICE_START_PENDING ? 0 : SERVICE_ACCEPT_STOP;
 
143
                ssStatus.dwCurrentState = reportState;
 
144
                ssStatus.dwWin32ExitCode = NO_ERROR;
 
145
                ssStatus.dwWaitHint = waitHint;
 
146
                ssStatus.dwCheckPoint = ( reportState == SERVICE_RUNNING || reportState == SERVICE_STOPPED ) ? 0 : checkPoint++;
 
147
 
 
148
                return SetServiceStatus( _statusHandle, &ssStatus );
 
149
        }
 
150
    
 
151
    void WINAPI ServiceController::initService( DWORD argc, LPTSTR *argv ) {
 
152
                _statusHandle = RegisterServiceCtrlHandler( _serviceName.c_str(), serviceCtrl );
 
153
                if ( !_statusHandle )
 
154
                        return;
 
155
 
 
156
                reportStatus( SERVICE_START_PENDING, 1000 );
 
157
                
 
158
                _serviceCallback();
 
159
                
 
160
                reportStatus( SERVICE_STOPPED );
 
161
        }
 
162
        
 
163
        void WINAPI ServiceController::serviceCtrl( DWORD ctrlCode ) {
 
164
                switch ( ctrlCode ) {
 
165
                        case SERVICE_CONTROL_STOP:
 
166
                        case SERVICE_CONTROL_SHUTDOWN:
 
167
                                shutdown();
 
168
                                reportStatus( SERVICE_STOPPED );
 
169
                                return;
 
170
                }
 
171
        }
 
172
 
 
173
} // namespace mongo
 
174
 
 
175
#endif