fintp_connectors
 All Classes Namespaces Files Functions Variables Enumerations Enumerator Macros Pages
NTServiceBase.h
Go to the documentation of this file.
1 #ifdef WIN32
2 
3 // Copyright (C) 1997 by Joerg Koenig
4 // All rights reserved
5 //
6 // Distribute freely, except: don't remove my name from the source or
7 // documentation (don't take credit for my work), mark your changes (don't
8 // get me blamed for your possible bugs), don't alter or remove this
9 // notice.
10 // No warrantee of any kind, express or implied, is included with this
11 // software; use at your own risk, responsibility for damages (if any) to
12 // anyone resulting from the use of this software rests entirely with the
13 // user.
14 //
15 // Send bug reports, bug fixes, enhancements, requests, flames, etc., and
16 // I'll try to keep a version up to date. I can be reached as follows:
17 // J.Koenig@adg.de (company site)
18 // Joerg.Koenig@rhein-neckar.de (private site)
20 //
21 // MODIFIED BY TODD C. WILSON FOR THE ROAD RUNNER NT LOGIN SERVICE.
22 // HOWEVER, THESE MODIFICATIONS ARE BROADER IN SCOPE AND USAGE AND CAN BE USED
23 // IN OTHER PROJECTS WITH NO CHANGES.
24 // MODIFIED LINES FLAGGED/BRACKETED BY "//!! TCW MOD"
25 //
27 
28 
29 // last revised: $Date: 2013-04-12 14:57:02 +0300 (Fri, 12 Apr 2013) $, $Revision: 20017 $
30 
31 
32 #ifndef NTService_h
33 #define NTService_h
34 
35 namespace FinTP
36 {
37  class CNTService
38  {
39  static BOOL m_bInstance; // only one CNTService object per application
40 
41  protected: // data members
42  TCHAR m_lpServiceName[256];
43  TCHAR m_lpDisplayName[256];
44  DWORD m_dwCheckPoint;
45  DWORD m_dwErr;
46  BOOL m_bDebug; // TRUE if -d was passed to the program
47  SERVICE_STATUS m_ssStatus; // current status of the service
48  SERVICE_STATUS_HANDLE m_sshStatusHandle;
49  DWORD m_dwControlsAccepted; // bit-field of what control requests the
50  // service will accept
51  // (dflt: SERVICE_ACCEPT_STOP)
52  PSID m_pUserSID; // the current user's security identifier
53  BOOL m_bWinNT; // TRUE, if this is running on WinNT FALSE on Win95
54  BOOL m_fConsoleReady;
55 
56  BOOL m_bAssumeRunBlocks;
57 
58  // parameters to the "CreateService()" function:
59  DWORD m_dwDesiredAccess; // default: SERVICE_ALL_ACCESS
60  DWORD m_dwServiceType; // default: SERVICE_WIN32_OWN_PROCESS
61  DWORD m_dwStartType; // default: SERVICE_AUTO_START
62  DWORD m_dwErrorControl; // default: SERVICE_ERROR_NORMAL
63  LPCTSTR m_pszLoadOrderGroup; // default: NULL
64  DWORD m_dwTagID; // retrieves the tag identifier
65  LPCTSTR m_pszDependencies; // default: NULL
66  LPCTSTR m_pszStartName; // default: NULL
67  LPCTSTR m_pszPassword; // default: NULL
68 
69 
70  public: // construction/destruction
71  // If <DisplayName> is not set, then it defaults to <ServiceName>.
72  CNTService(LPCTSTR ServiceName, LPCTSTR DisplayName = 0);
73  virtual ~CNTService();
74 
75  private: // forbidden functions
76  CNTService( const CNTService & );
77  CNTService & operator=( const CNTService & );
78 
79  public: // overridables
80  // You have to override the following two functions.
81  // "Run()" will be called to start the real
82  // service's activity. You must call
83  // ReportStatus(SERVICE_RUNNING);
84  // before you enter your main-loop !
85  // "Stop()" will be called to stop the work of
86  // the service. You should break out of the mainloop
87  // and return control to the CNTService class.
88  //
89  // In most cases these functions look like these:
90  //
91  // void CMyService :: Run(DWORD argc, LPTSTR * argv) {
92  // ReportStatus(SERVICE_START_PENDING);
93  // // do some parameter processing ...
94  // ReportStatus(SERVICE_START_PENDING);
95  // // do first part of initialisation ...
96  // ReportStatus(SERVICE_START_PENDING);
97  // // do next part of initialisation
98  // // ...
99  // m_hStop = CreateEvent(0, TRUE, FALSE, 0);
100  // ReportStatus(SERVICE_RUNNING);
101  // while( WaitForSingleObject(m_hStop, 10) != WAIT_OBJECT_0 ) {
102  // // do something
103  // }
104  // if( m_hStop )
105  // CloseHandle(m_hStop);
106  // }
107  //
108  // void CMyService :: Stop() {
109  // if( m_hStop )
110  // SetEvent(m_hStop);
111  // ReportStatus(SERVICE_STOP_PENDING);
112  // }
113  virtual void Run(DWORD argc, LPTSTR * argv) = 0;
114  virtual void Stop() = 0;
115 
116  // Pause() and Continue() do nothing by default.
117  // You can override them to handle a control request.
118  // Pause() should report the status SERVICE_PAUSED
119  // and Continue() should report the status SERVICE_RUNNING
120  // (see ReportStatus() below).
121  // Note that normally these functions will never be called. If
122  // you want a service, that accepts PAUSE and CONTINUE control
123  // requests, you have to to add SERVICE_ACCEPT_PAUSE_CONTINUE
124  // to the m_dwControlsAccepted data member.
125  virtual void Pause();
126  virtual void Continue();
127 
128  // Shutdown() will be called, if the service manager
129  // requests for the SERVICE_CONTROL_SHUTDOWN control.
130  // This control type occurs, when the system shuts down.
131  // If you want to process this notification, you have to
132  // add SERVICE_ACCEPT_SHUTDOWN to the m_dwControlsAccepted
133  // data member (and to override this function). The default
134  // implementation of Shutdown() does nothing.
135  virtual void Shutdown();
136 
137  // Call "RegisterService()" after you have constructed
138  // a CNTService object:
139  // A typical "main()" function of a service looks like this:
140  //
141  // int main( int argc, char ** argv ) {
142  // CMyService serv;
143  // exit(serv.RegisterService(argc, argv));
144  // }
145  //
146  // Where "CMyService" is a CNTService derived class.
147  // RegisterService() checks the parameterlist. The
148  // following parameters will be detected:
149  // -i install the service (calls
150  // "InstallService()" - see below)
151  //
152  // -l <account>
153  // <account> is the name of a user,
154  // under which the service shall run.
155  // This option is useful with -i only.
156  // <account> needs to have the advanced
157  // user-right "Log on as a service"
158  // (see User-Manager)
159  // <account> should have the following
160  // format: "<Domain><user>"
161  // "EuroS2Team\jko" for instance.
162  // The domain "." is predefined as the
163  // local machine. So one might use
164  // ".\jko" too.
165  //
166  // -p <password>
167  // The password of the user, under which
168  // the service shall run. Only useful
169  // with -i and -l together.
170  //
171  // -u uninstall the service (calls
172  // "RemoveService()" - see below)
173  //
174  // -d debug the service (run as console
175  // process; calls "DebugService()"
176  // see below)
177  //
178  // -e end the service (if it is running)
179  //
180  // -s start the service (if it is not running)
181  // (Note that *you* normally cannot start
182  // an NT-service from the command-line.
183  // The SCM can.)
184  //
185  // Do not use -l and -p, if your service is of type
186  // SERVICE_KERNEL_DRIVER or SERVICE_FILE_SYSTEM_DRIVER.
187  // Furthermore you canot use -i and -s together. Instead
188  // you have to start the command twice, first you install
189  // the service, then you start it.
190  // If none of the flags -i, -u, -e, -s and -d is set, then the
191  // program starts as an NT service (only the SCM can start it
192  // this way!).
193  // NOTE: If UNICODE is #define'd, then <argc> and <argv>
194  // will be ignored and the original commandline
195  // of the program will be used to parse the
196  // arguments !
197  virtual BOOL RegisterService(int argc, char ** argv);
198 
199  // "StartDispatcher()" registers one service-procedure
200  // to the service control dispatcher (using the predefined
201  // "ServiceMain()" function below).
202  // Override this funtion, if you want to develop a
203  // multithreaded NT-Service.
204  virtual BOOL StartDispatcher();
205 
206  // Override "InstallService()" to manipulate the
207  // installation behavior.
208  // This function will only be called, if the
209  // "-i" flag was passed to "RegisterService()"
210  // (see above)
211  // After "InstallService()" has completed, you
212  // should be able to see the service in the
213  // "services" control-panel-applet.
214  virtual BOOL InstallService();
215 
216  // RemoveService() removes a service from the system's
217  // service-table.
218  // It first tries to stop the service.
219  // This function will be called only if the -u
220  // flag was passed to the program. (see "RegisterService()"
221  // above)
222  // After removal of the service, it should no longer
223  // appear in the "services" control-panel-applet.
224  virtual BOOL RemoveService();
225 
226 
227  // EndService() stops a running service (if the service
228  // is running as a service! Does not end a service
229  // running as a console program (see DebugService()
230  // below))
231  virtual BOOL EndService();
232 
233  // Start the service. Does the same as if the
234  // SCM launches the program. Note that this method
235  // will create a new instance of the program.
236  virtual BOOL StartupService();
237 
238  // Run a service as a console application. This makes it
239  // easier to debug the service.
240  // This function will be called only if the -d flag
241  // was passed to the program(see "RegisterService()" above).
242  // It transparently calls "Run()". You can simulate a
243  // stop-request by pressing either Ctrl-C or Ctrl-Break (that
244  // will call the "Stop()" method).
245  virtual BOOL DebugService(int argc, char **argv,BOOL faceless=FALSE);
246 
247  protected: // implementation
248  // Override "RegisterApplicationLog()", if you want to register
249  // a different message file and/or differend supported types
250  // than the default.
251  // The proposed message file is the application itself.
252  // The proposed types are:
253  // EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE
254  // This method will be called from inside "InstallService()" (see above)
255  // Thus if you support errors only (for instance):
256  // void CMyService :: RegisterApplicationLog(LPCTSTR filename, DWORD ) {
257  // CNTService::RegisterApplicationLog(filename, EVENTLOG_ERROR_TYPE);
258  // }
259  // This method will never be called on Win95.
260  virtual void RegisterApplicationLog(
261  LPCTSTR lpszProposedMessageFile,
262  DWORD dwProposedTypes
263  );
264 
265  // "DeregisterApplicationLog()" is called from inside "RemoveService()"
266  // (see above) to clear the registry-entries made by
267  // "RegisterApplicationLog()"
268  virtual void DeregisterApplicationLog();
269 
270  public: // helpers
271  // Retrieve a human-readable error message. The message
272  // will be stored in <Buf> which is of size <Size>.
273  // Returns a pointer to <Buf>.
274  LPTSTR GetLastErrorText(LPTSTR Buf, DWORD Size);
275 
276  // report status to the service-control-manager.
277  // <CurState> can be one of:
278  // SERVICE_START_PENDING - the service is starting
279  // SERVICE_RUNNING - the service is running
280  // SERVICE_STOP_PENDING - the service is stopping
281  // SERVICE_STOPPED - the service is not running
282  // SERVICE_PAUSE_PENDING - the service pause is pending
283  // SERVICE_PAUSE - the service is paused
284  // SERVICE_CONTINUE_PENDING - the service is about to continue
285  BOOL ReportStatus(
286  DWORD CurState, // service's state
287  DWORD WaitHint = 3000, // expected time of operation in milliseconds
288  DWORD ErrExit = 0
289  );
290 
291  // AddToMessageLog() writes a message to the application event-log.
292  // (use EventViewer from the menu "Administrative Tools" to watch the log).
293  // The <EventType> parameter can be set to one of the following values:
294  // EVENTLOG_ERROR_TYPE Error event
295  // EVENTLOG_WARNING_TYPE Warning event
296  // EVENTLOG_INFORMATION_TYPE Information event
297  // EVENTLOG_AUDIT_SUCCESS Success Audit event
298  // EVENTLOG_AUDIT_FAILURE Failure Audit event
299  // See "ReportEvent()" in the help-topics for further information.
300  virtual void AddToMessageLog(
301  LPTSTR Message,
302  WORD EventType = EVENTLOG_ERROR_TYPE,
303  DWORD dwEventID = DWORD(-1)
304  );
305 
306  public: // default handlers
307  // The following functions will be used by default.
308  // You can provide other handlers. If so, you have to
309  // overload several of the "virtual"s above.
310  static void WINAPI ServiceCtrl(DWORD CtrlCode);
311  static void WINAPI ServiceMain(DWORD argc, LPTSTR * argv);
312  static BOOL WINAPI ControlHandler(DWORD CtrlType);
313 
315  public:
316  BOOL OsIsWin95() const { return ! m_bWinNT; }
317  void SetupConsole();
318 
319  };
320 
321 
322  // Retrieve the one and only CNTService object:
323  CNTService * AfxGetService();
324 }
325 
326 #endif // NTService_h
327 #endif // WIN32