win32-service 2.2.0 → 2.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/win32/daemon.rb +97 -93
- data/lib/win32/service.rb +226 -239
- data/lib/win32/windows/functions.rb +28 -28
- data/lib/win32/windows/structs.rb +1 -1
- data/lib/win32/windows/version.rb +1 -1
- data/lib/win32-daemon.rb +1 -1
- data/lib/win32-service.rb +1 -1
- metadata +8 -22
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: d6e082fe0332a702fd8a8abe6be757173ac44a97f5aca6b544e63aea98435e41
|
|
4
|
+
data.tar.gz: 22628c39784ab449296e8775298bbb9502b1fd944097dfa7c8fac25b423f1f69
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 3c20950b21f865da21aef986bed1d8f9eb72cca83f6e78f91bf4abc963bce43ae715b73a3ed5e72cc2649138209bd2120cb8e38870487620d728e264864db8fc
|
|
7
|
+
data.tar.gz: 4327e6a58cc533509506ad72783f2150f6d84ff60df1661abc8b3a5b7193d0627ed806e09c2db219ebc390202a9fa2e91902ee27eac0ff6ffac39966bb9e9a6d
|
data/lib/win32/daemon.rb
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
|
-
require_relative
|
|
2
|
-
require_relative
|
|
3
|
-
require_relative
|
|
4
|
-
require_relative
|
|
1
|
+
require_relative "windows/constants"
|
|
2
|
+
require_relative "windows/structs"
|
|
3
|
+
require_relative "windows/functions"
|
|
4
|
+
require_relative "windows/version"
|
|
5
5
|
|
|
6
6
|
# The Win32 module serves as a namespace only.
|
|
7
7
|
module Win32
|
|
@@ -18,8 +18,6 @@ module Win32
|
|
|
18
18
|
# The version of this library
|
|
19
19
|
VERSION = Win32::Service::VERSION
|
|
20
20
|
|
|
21
|
-
private
|
|
22
|
-
|
|
23
21
|
# Service is not running
|
|
24
22
|
STOPPED = SERVICE_STOPPED
|
|
25
23
|
|
|
@@ -73,16 +71,16 @@ module Win32
|
|
|
73
71
|
IDLE = 0
|
|
74
72
|
|
|
75
73
|
# Wraps SetServiceStatus.
|
|
76
|
-
SetTheServiceStatus = Proc.new do |dwCurrentState, dwWin32ExitCode,dwCheckPoint,
|
|
77
|
-
ss = SERVICE_STATUS.new
|
|
74
|
+
SetTheServiceStatus = Proc.new do |dwCurrentState, dwWin32ExitCode, dwCheckPoint, dwWaitHint|
|
|
75
|
+
ss = SERVICE_STATUS.new # Current status of the service.
|
|
78
76
|
|
|
79
77
|
# Disable control requests until the service is started.
|
|
80
78
|
if dwCurrentState == SERVICE_START_PENDING
|
|
81
79
|
ss[:dwControlsAccepted] = 0
|
|
82
80
|
else
|
|
83
81
|
ss[:dwControlsAccepted] =
|
|
84
|
-
|
|
85
|
-
|
|
82
|
+
SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN |
|
|
83
|
+
SERVICE_ACCEPT_PAUSE_CONTINUE | SERVICE_ACCEPT_PARAMCHANGE
|
|
86
84
|
end
|
|
87
85
|
|
|
88
86
|
# Initialize ss structure.
|
|
@@ -96,7 +94,7 @@ module Win32
|
|
|
96
94
|
@@dwServiceState = dwCurrentState
|
|
97
95
|
|
|
98
96
|
# Send status of the service to the Service Controller.
|
|
99
|
-
|
|
97
|
+
unless SetServiceStatus(@@ssh, ss)
|
|
100
98
|
SetEvent(@@hStopEvent)
|
|
101
99
|
end
|
|
102
100
|
end
|
|
@@ -104,8 +102,8 @@ module Win32
|
|
|
104
102
|
ERROR_CALL_NOT_IMPLEMENTED = 0x78
|
|
105
103
|
|
|
106
104
|
# Handles control signals from the service control manager.
|
|
107
|
-
Service_Ctrl_ex = Proc.new do |dwCtrlCode,dwEventType,lpEventData,lpContext|
|
|
108
|
-
@@waiting_control_code = dwCtrlCode
|
|
105
|
+
Service_Ctrl_ex = Proc.new do |dwCtrlCode, dwEventType, lpEventData, lpContext|
|
|
106
|
+
@@waiting_control_code = dwCtrlCode
|
|
109
107
|
return_value = NO_ERROR
|
|
110
108
|
|
|
111
109
|
begin
|
|
@@ -120,8 +118,8 @@ module Win32
|
|
|
120
118
|
dwState = SERVICE_PAUSED
|
|
121
119
|
when SERVICE_CONTROL_CONTINUE
|
|
122
120
|
dwState = SERVICE_RUNNING
|
|
123
|
-
#else
|
|
124
|
-
|
|
121
|
+
# else
|
|
122
|
+
# TODO: Handle other control codes? Retain the current state?
|
|
125
123
|
end
|
|
126
124
|
|
|
127
125
|
# Set the status of the service except on interrogation.
|
|
@@ -143,56 +141,56 @@ module Win32
|
|
|
143
141
|
end
|
|
144
142
|
|
|
145
143
|
# Called by the service control manager after the call to StartServiceCtrlDispatcher.
|
|
146
|
-
Service_Main = FFI::Function.new(:void,
|
|
147
|
-
begin
|
|
148
|
-
# Obtain the name of the service.
|
|
149
|
-
if lpszArgv.address!=0
|
|
150
|
-
argv = lpszArgv.get_array_of_string(0,dwArgc)
|
|
151
|
-
lpszServiceName = argv[0]
|
|
152
|
-
else
|
|
153
|
-
lpszServiceName = ''
|
|
154
|
-
end
|
|
144
|
+
Service_Main = FFI::Function.new(:void, %i{ulong pointer}, blocking: false) do |dwArgc, lpszArgv|
|
|
155
145
|
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
146
|
+
# Obtain the name of the service.
|
|
147
|
+
if lpszArgv.address != 0
|
|
148
|
+
argv = lpszArgv.get_array_of_string(0, dwArgc)
|
|
149
|
+
lpszServiceName = argv[0]
|
|
150
|
+
else
|
|
151
|
+
lpszServiceName = ""
|
|
152
|
+
end
|
|
162
153
|
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
154
|
+
# Args passed to Service.start
|
|
155
|
+
if dwArgc > 1
|
|
156
|
+
@@Argv = argv[1..-1]
|
|
157
|
+
else
|
|
158
|
+
@@Argv = nil
|
|
159
|
+
end
|
|
169
160
|
|
|
170
|
-
|
|
171
|
-
|
|
161
|
+
# Register the service ctrl handler.
|
|
162
|
+
@@ssh = RegisterServiceCtrlHandlerEx(
|
|
163
|
+
lpszServiceName,
|
|
164
|
+
Service_Ctrl_ex,
|
|
165
|
+
nil
|
|
166
|
+
)
|
|
172
167
|
|
|
173
|
-
|
|
174
|
-
|
|
168
|
+
# No service to stop, no service handle to notify, nothing to do but exit.
|
|
169
|
+
return if @@ssh == 0 # rubocop:disable Lint/NonLocalExitFromIterator
|
|
175
170
|
|
|
176
|
-
|
|
171
|
+
# The service has started.
|
|
172
|
+
SetTheServiceStatus.call(SERVICE_RUNNING, NO_ERROR, 0, 0)
|
|
177
173
|
|
|
178
|
-
|
|
179
|
-
while(WaitForSingleObject(@@hStopEvent, 1000) != WAIT_OBJECT_0) do
|
|
180
|
-
end
|
|
174
|
+
SetEvent(@@hStartEvent)
|
|
181
175
|
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
end
|
|
185
|
-
ensure
|
|
186
|
-
# Stop the service.
|
|
187
|
-
SetTheServiceStatus.call(SERVICE_STOPPED, NO_ERROR, 0, 0)
|
|
176
|
+
# Main loop for the service.
|
|
177
|
+
while WaitForSingleObject(@@hStopEvent, 1000) != WAIT_OBJECT_0
|
|
188
178
|
end
|
|
179
|
+
|
|
180
|
+
# Main loop for the service.
|
|
181
|
+
while WaitForSingleObject(@@hStopCompletedEvent, 1000) != WAIT_OBJECT_0
|
|
182
|
+
end
|
|
183
|
+
ensure
|
|
184
|
+
# Stop the service.
|
|
185
|
+
SetTheServiceStatus.call(SERVICE_STOPPED, NO_ERROR, 0, 0)
|
|
186
|
+
|
|
189
187
|
end
|
|
190
188
|
|
|
191
|
-
ThreadProc = FFI::Function.new(:ulong,[:pointer]) do |lpParameter|
|
|
189
|
+
ThreadProc = FFI::Function.new(:ulong, [:pointer]) do |lpParameter|
|
|
192
190
|
ste = FFI::MemoryPointer.new(SERVICE_TABLE_ENTRY, 2)
|
|
193
191
|
|
|
194
192
|
s = SERVICE_TABLE_ENTRY.new(ste[0])
|
|
195
|
-
s[:lpServiceName] = FFI::MemoryPointer.from_string(
|
|
193
|
+
s[:lpServiceName] = FFI::MemoryPointer.from_string("")
|
|
196
194
|
s[:lpServiceProc] = lpParameter
|
|
197
195
|
|
|
198
196
|
s = SERVICE_TABLE_ENTRY.new(ste[1])
|
|
@@ -200,19 +198,17 @@ module Win32
|
|
|
200
198
|
s[:lpServiceProc] = nil
|
|
201
199
|
|
|
202
200
|
# No service to step, no service handle, no ruby exceptions, just terminate the thread..
|
|
203
|
-
|
|
201
|
+
unless StartServiceCtrlDispatcher(ste)
|
|
204
202
|
return 1
|
|
205
203
|
end
|
|
206
204
|
|
|
207
205
|
return 0
|
|
208
206
|
end
|
|
209
207
|
|
|
210
|
-
public
|
|
211
|
-
|
|
212
208
|
# This is a shortcut for Daemon.new + Daemon#mainloop.
|
|
213
209
|
#
|
|
214
210
|
def self.mainloop
|
|
215
|
-
|
|
211
|
+
new.mainloop
|
|
216
212
|
end
|
|
217
213
|
|
|
218
214
|
# This is the method that actually puts your code into a loop and allows it
|
|
@@ -225,9 +221,9 @@ module Win32
|
|
|
225
221
|
|
|
226
222
|
# Redirect STDIN, STDOUT and STDERR to the NUL device if they're still
|
|
227
223
|
# associated with a tty. This helps newbs avoid Errno::EBADF errors.
|
|
228
|
-
STDIN.reopen(
|
|
229
|
-
STDOUT.reopen(
|
|
230
|
-
STDERR.reopen(
|
|
224
|
+
STDIN.reopen("NUL") if STDIN.isatty
|
|
225
|
+
STDOUT.reopen("NUL") if STDOUT.isatty
|
|
226
|
+
STDERR.reopen("NUL") if STDERR.isatty
|
|
231
227
|
|
|
232
228
|
# Calling init here so that init failures never even tries to start the
|
|
233
229
|
# service. Of course that means that init methods must be very quick
|
|
@@ -235,44 +231,44 @@ module Win32
|
|
|
235
231
|
# init's running.
|
|
236
232
|
#
|
|
237
233
|
# TODO: Fix?
|
|
238
|
-
service_init
|
|
234
|
+
service_init if respond_to?("service_init")
|
|
239
235
|
|
|
240
236
|
# Create the event to signal the service to start.
|
|
241
237
|
@@hStartEvent = CreateEvent(nil, 1, 0, nil)
|
|
242
238
|
|
|
243
239
|
if @@hStartEvent == 0
|
|
244
|
-
raise SystemCallError.new(
|
|
240
|
+
raise SystemCallError.new("CreateEvent", FFI.errno)
|
|
245
241
|
end
|
|
246
242
|
|
|
247
243
|
# Create the event to signal the service to stop.
|
|
248
244
|
@@hStopEvent = CreateEvent(nil, 1, 0, nil)
|
|
249
245
|
|
|
250
246
|
if @@hStopEvent == 0
|
|
251
|
-
raise SystemCallError.new(
|
|
247
|
+
raise SystemCallError.new("CreateEvent", FFI.errno)
|
|
252
248
|
end
|
|
253
249
|
|
|
254
250
|
# Create the event to signal the service that stop has completed
|
|
255
251
|
@@hStopCompletedEvent = CreateEvent(nil, 1, 0, nil)
|
|
256
252
|
|
|
257
253
|
if @@hStopCompletedEvent == 0
|
|
258
|
-
raise SystemCallError.new(
|
|
254
|
+
raise SystemCallError.new("CreateEvent", FFI.errno)
|
|
259
255
|
end
|
|
260
256
|
|
|
261
257
|
hThread = CreateThread(nil, 0, ThreadProc, Service_Main, 0, nil)
|
|
262
258
|
|
|
263
259
|
if hThread == 0
|
|
264
|
-
raise SystemCallError.new(
|
|
260
|
+
raise SystemCallError.new("CreateThread", FFI.errno)
|
|
265
261
|
end
|
|
266
262
|
|
|
267
263
|
events = FFI::MemoryPointer.new(:pointer, 2)
|
|
268
264
|
events.put_pointer(0, FFI::Pointer.new(hThread))
|
|
269
265
|
events.put_pointer(FFI::Pointer.size, FFI::Pointer.new(@@hStartEvent))
|
|
270
266
|
|
|
271
|
-
while (
|
|
267
|
+
while (index = WaitForMultipleObjects(2, events, 0, 1000)) == WAIT_TIMEOUT
|
|
272
268
|
end
|
|
273
269
|
|
|
274
270
|
if index == WAIT_FAILED
|
|
275
|
-
raise SystemCallError.new(
|
|
271
|
+
raise SystemCallError.new("WaitForMultipleObjects", FFI.errno)
|
|
276
272
|
end
|
|
277
273
|
|
|
278
274
|
# The thread exited, so the show is off.
|
|
@@ -281,39 +277,47 @@ module Win32
|
|
|
281
277
|
end
|
|
282
278
|
|
|
283
279
|
thr = Thread.new do
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
280
|
+
|
|
281
|
+
while WaitForSingleObject(@@hStopEvent, 1000) == WAIT_TIMEOUT
|
|
282
|
+
# Check to see if anything interesting has been signaled
|
|
283
|
+
case @@waiting_control_code
|
|
284
|
+
when SERVICE_CONTROL_PAUSE
|
|
285
|
+
service_pause if respond_to?("service_pause")
|
|
286
|
+
when SERVICE_CONTROL_CONTINUE
|
|
287
|
+
service_resume if respond_to?("service_resume")
|
|
288
|
+
when SERVICE_CONTROL_INTERROGATE
|
|
289
|
+
service_interrogate if respond_to?("service_interrogate")
|
|
290
|
+
when SERVICE_CONTROL_SHUTDOWN
|
|
291
|
+
service_shutdown if respond_to?("service_shutdown")
|
|
292
|
+
when SERVICE_CONTROL_PARAMCHANGE
|
|
293
|
+
service_paramchange if respond_to?("service_paramchange")
|
|
294
|
+
when SERVICE_CONTROL_NETBINDADD
|
|
295
|
+
service_netbindadd if respond_to?("service_netbindadd")
|
|
296
|
+
when SERVICE_CONTROL_NETBINDREMOVE
|
|
297
|
+
service_netbindremove if respond_to?("service_netbindremove")
|
|
298
|
+
when SERVICE_CONTROL_NETBINDENABLE
|
|
299
|
+
service_netbindenable if respond_to?("service_netbindenable")
|
|
300
|
+
when SERVICE_CONTROL_NETBINDDISABLE
|
|
301
|
+
service_netbinddisable if respond_to?("service_netbinddisable")
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
# handle user defined control codes
|
|
305
|
+
if @@waiting_control_code.between?(128, 255)
|
|
306
|
+
if respond_to?("service_user_defined_control")
|
|
307
|
+
service_user_defined_control(@@waiting_control_code)
|
|
306
308
|
end
|
|
307
|
-
@@waiting_control_code = IDLE_CONTROL_CODE
|
|
308
309
|
end
|
|
309
310
|
|
|
310
|
-
|
|
311
|
-
ensure
|
|
312
|
-
SetEvent(@@hStopCompletedEvent)
|
|
311
|
+
@@waiting_control_code = IDLE_CONTROL_CODE
|
|
313
312
|
end
|
|
313
|
+
|
|
314
|
+
service_stop if respond_to?("service_stop")
|
|
315
|
+
ensure
|
|
316
|
+
SetEvent(@@hStopCompletedEvent)
|
|
317
|
+
|
|
314
318
|
end
|
|
315
319
|
|
|
316
|
-
if respond_to?(
|
|
320
|
+
if respond_to?("service_main")
|
|
317
321
|
service_main(*@@Argv)
|
|
318
322
|
end
|
|
319
323
|
|