win32-service 0.8.5 → 0.8.6
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGES +6 -0
- data/lib/win32/daemon.rb +99 -85
- data/lib/win32/service.rb +14 -8
- data/lib/win32/windows/constants.rb +2 -1
- data/win32-service.gemspec +1 -1
- metadata +11 -11
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9eb593fe954a9ad9baa295314a6deba834e416f5
|
4
|
+
data.tar.gz: b8ddb7267b81ea05bcf0c211ab684d07571a2d5b
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 59a97083e2ff8900d2f80244a6313452e8479f8d577abee74b6af9bc1a397979d28d043537d6b22c49a90d8d287b1423e53f8349cc2d4ae76022df3c58285bd0
|
7
|
+
data.tar.gz: cd0285acd389d078041dd27252c0da1880044b5100f8f848d323b05bbacf9c86d541f2d0c3dd696f70f075745f1949dcafebdf677ca330c8dfdb7c701ae36962
|
data/CHANGES
CHANGED
@@ -1,3 +1,9 @@
|
|
1
|
+
== 0.8.6 - 21-Aug-2014
|
2
|
+
* Some internal changes that make stopping a service more robust. Thanks go
|
3
|
+
to Ethan J. Brown for the patches.
|
4
|
+
* Renamed the constants module to avoid name clashes. Thanks go to Michael
|
5
|
+
Smith for the spot.
|
6
|
+
|
1
7
|
== 0.8.5 - 2-Jul-2014
|
2
8
|
* The service type for Service.new no longer defaults to being an interactive
|
3
9
|
process. This could cause process credential issues and wasn't very
|
data/lib/win32/daemon.rb
CHANGED
@@ -10,7 +10,7 @@ module Win32
|
|
10
10
|
|
11
11
|
# The Daemon class
|
12
12
|
class Daemon
|
13
|
-
include Windows::
|
13
|
+
include Windows::ServiceConstants
|
14
14
|
include Windows::Structs
|
15
15
|
include Windows::Functions
|
16
16
|
|
@@ -18,7 +18,7 @@ module Win32
|
|
18
18
|
extend Windows::Functions
|
19
19
|
|
20
20
|
# The version of this library
|
21
|
-
VERSION = '0.8.
|
21
|
+
VERSION = '0.8.6'
|
22
22
|
|
23
23
|
private
|
24
24
|
|
@@ -103,80 +103,91 @@ module Win32
|
|
103
103
|
end
|
104
104
|
end
|
105
105
|
|
106
|
+
ERROR_CALL_NOT_IMPLEMENTED = 0x78
|
107
|
+
|
106
108
|
# Handles control signals from the service control manager.
|
107
109
|
Service_Ctrl_ex = Proc.new do |dwCtrlCode,dwEventType,lpEventData,lpContext|
|
108
110
|
@@waiting_control_code = dwCtrlCode;
|
111
|
+
return_value = NO_ERROR
|
112
|
+
|
113
|
+
begin
|
114
|
+
dwState = SERVICE_RUNNING
|
115
|
+
|
116
|
+
case dwCtrlCode
|
117
|
+
when SERVICE_CONTROL_STOP
|
118
|
+
dwState = SERVICE_STOP_PENDING
|
119
|
+
when SERVICE_CONTROL_SHUTDOWN
|
120
|
+
dwState = SERVICE_STOP_PENDING
|
121
|
+
when SERVICE_CONTROL_PAUSE
|
122
|
+
dwState = SERVICE_PAUSED
|
123
|
+
when SERVICE_CONTROL_CONTINUE
|
124
|
+
dwState = SERVICE_RUNNING
|
125
|
+
#else
|
126
|
+
# TODO: Handle other control codes? Retain the current state?
|
127
|
+
end
|
109
128
|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
dwState = SERVICE_STOP_PENDING
|
115
|
-
when SERVICE_CONTROL_SHUTDOWN
|
116
|
-
dwState = SERVICE_STOP_PENDING
|
117
|
-
when SERVICE_CONTROL_PAUSE
|
118
|
-
dwState = SERVICE_PAUSED
|
119
|
-
when SERVICE_CONTROL_CONTINUE
|
120
|
-
dwState = SERVICE_RUNNING
|
121
|
-
#else
|
122
|
-
# TODO: Handle other control codes? Retain the current state?
|
123
|
-
end
|
124
|
-
|
125
|
-
# Set the status of the service except on interrogation.
|
126
|
-
unless dwCtrlCode == SERVICE_CONTROL_INTERROGATE
|
127
|
-
SetTheServiceStatus.call(dwState, NO_ERROR, 0, 0)
|
128
|
-
end
|
129
|
+
# Set the status of the service except on interrogation.
|
130
|
+
unless dwCtrlCode == SERVICE_CONTROL_INTERROGATE
|
131
|
+
SetTheServiceStatus.call(dwState, NO_ERROR, 0, 0)
|
132
|
+
end
|
129
133
|
|
130
|
-
|
131
|
-
|
132
|
-
|
133
|
-
|
134
|
+
# Tell service_main thread to stop.
|
135
|
+
if dwCtrlCode == SERVICE_CONTROL_STOP || dwCtrlCode == SERVICE_CONTROL_SHUTDOWN
|
136
|
+
if SetEvent(@@hStopEvent) == 0
|
137
|
+
SetTheServiceStatus.call(SERVICE_STOPPED, FFI.errno, 0, 0)
|
138
|
+
end
|
134
139
|
end
|
140
|
+
rescue
|
141
|
+
return_value = ERROR_CALL_NOT_IMPLEMENTED
|
135
142
|
end
|
143
|
+
|
144
|
+
return_value
|
136
145
|
end
|
137
146
|
|
138
147
|
# Called by the service control manager after the call to StartServiceCtrlDispatcher.
|
139
148
|
Service_Main = FFI::Function.new(:void, [:ulong, :pointer], :blocking => false) do |dwArgc,lpszArgv|
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
149
|
+
begin
|
150
|
+
# Obtain the name of the service.
|
151
|
+
if lpszArgv.address!=0
|
152
|
+
argv = lpszArgv.get_array_of_string(0,dwArgc)
|
153
|
+
lpszServiceName = argv[0]
|
154
|
+
else
|
155
|
+
lpszServiceName = ''
|
156
|
+
end
|
147
157
|
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
158
|
+
# Args passed to Service.start
|
159
|
+
if(dwArgc > 1)
|
160
|
+
@@Argv = argv[1..-1]
|
161
|
+
else
|
162
|
+
@@Argv = nil
|
163
|
+
end
|
154
164
|
|
155
|
-
|
156
|
-
|
157
|
-
|
158
|
-
|
159
|
-
|
160
|
-
|
165
|
+
# Register the service ctrl handler.
|
166
|
+
@@ssh = RegisterServiceCtrlHandlerEx(
|
167
|
+
lpszServiceName,
|
168
|
+
Service_Ctrl_ex,
|
169
|
+
nil
|
170
|
+
)
|
161
171
|
|
162
|
-
|
163
|
-
|
172
|
+
# No service to stop, no service handle to notify, nothing to do but exit.
|
173
|
+
return if @@ssh == 0
|
164
174
|
|
165
|
-
|
166
|
-
|
175
|
+
# The service has started.
|
176
|
+
SetTheServiceStatus.call(SERVICE_RUNNING, NO_ERROR, 0, 0)
|
167
177
|
|
168
|
-
|
178
|
+
SetEvent(@@hStartEvent)
|
169
179
|
|
170
|
-
|
171
|
-
|
172
|
-
|
180
|
+
# Main loop for the service.
|
181
|
+
while(WaitForSingleObject(@@hStopEvent, 1000) != WAIT_OBJECT_0) do
|
182
|
+
end
|
173
183
|
|
174
|
-
|
175
|
-
|
184
|
+
# Main loop for the service.
|
185
|
+
while(WaitForSingleObject(@@hStopCompletedEvent, 1000) != WAIT_OBJECT_0) do
|
186
|
+
end
|
187
|
+
ensure
|
188
|
+
# Stop the service.
|
189
|
+
SetTheServiceStatus.call(SERVICE_STOPPED, NO_ERROR, 0, 0)
|
176
190
|
end
|
177
|
-
|
178
|
-
# Stop the service.
|
179
|
-
SetTheServiceStatus.call(SERVICE_STOPPED, NO_ERROR, 0, 0)
|
180
191
|
end
|
181
192
|
|
182
193
|
ThreadProc = FFI::Function.new(:ulong,[:pointer]) do |lpParameter|
|
@@ -184,7 +195,7 @@ module Win32
|
|
184
195
|
|
185
196
|
s = SERVICE_TABLE_ENTRY.new(ste[0])
|
186
197
|
s[:lpServiceName] = FFI::MemoryPointer.from_string('')
|
187
|
-
s[:lpServiceProc] =
|
198
|
+
s[:lpServiceProc] = lpParameter
|
188
199
|
|
189
200
|
s = SERVICE_TABLE_ENTRY.new(ste[1])
|
190
201
|
s[:lpServiceName] = nil
|
@@ -249,13 +260,13 @@ module Win32
|
|
249
260
|
raise SystemCallError.new('CreateEvent', FFI.errno)
|
250
261
|
end
|
251
262
|
|
252
|
-
hThread = CreateThread(nil, 0, ThreadProc,
|
263
|
+
hThread = CreateThread(nil, 0, ThreadProc, Service_Main, 0, nil)
|
253
264
|
|
254
265
|
if hThread == 0
|
255
266
|
raise SystemCallError.new('CreateThread', FFI.errno)
|
256
267
|
end
|
257
268
|
|
258
|
-
events = FFI::MemoryPointer.new(:pointer,
|
269
|
+
events = FFI::MemoryPointer.new(:pointer, 2)
|
259
270
|
events.put_pointer(0, FFI::Pointer.new(hThread))
|
260
271
|
events.put_pointer(FFI::Pointer.size, FFI::Pointer.new(@@hStartEvent))
|
261
272
|
|
@@ -272,33 +283,36 @@ module Win32
|
|
272
283
|
end
|
273
284
|
|
274
285
|
thr = Thread.new do
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
288
|
-
|
289
|
-
|
290
|
-
|
291
|
-
|
292
|
-
|
293
|
-
|
294
|
-
|
295
|
-
|
286
|
+
begin
|
287
|
+
while(WaitForSingleObject(@@hStopEvent, 10) == WAIT_TIMEOUT)
|
288
|
+
# Check to see if anything interesting has been signaled
|
289
|
+
case @@waiting_control_code
|
290
|
+
when SERVICE_CONTROL_PAUSE
|
291
|
+
service_pause() if respond_to?('service_pause')
|
292
|
+
when SERVICE_CONTROL_CONTINUE
|
293
|
+
service_resume() if respond_to?('service_resume')
|
294
|
+
when SERVICE_CONTROL_INTERROGATE
|
295
|
+
service_interrogate() if respond_to?('service_interrogate')
|
296
|
+
when SERVICE_CONTROL_SHUTDOWN
|
297
|
+
service_shutdown() if respond_to?('service_shutdown')
|
298
|
+
when SERVICE_CONTROL_PARAMCHANGE
|
299
|
+
service_paramchange() if respond_to?('service_paramchange')
|
300
|
+
when SERVICE_CONTROL_NETBINDADD
|
301
|
+
service_netbindadd() if respond_to?('service_netbindadd')
|
302
|
+
when SERVICE_CONTROL_NETBINDREMOVE
|
303
|
+
service_netbindremove() if respond_to?('service_netbindremove')
|
304
|
+
when SERVICE_CONTROL_NETBINDENABLE
|
305
|
+
service_netbindenable() if respond_to?('service_netbindenable')
|
306
|
+
when SERVICE_CONTROL_NETBINDDISABLE
|
307
|
+
service_netbinddisable() if respond_to?('service_netbinddisable')
|
308
|
+
end
|
309
|
+
@@waiting_control_code = IDLE_CONTROL_CODE
|
296
310
|
end
|
297
|
-
@@waiting_control_code = IDLE_CONTROL_CODE
|
298
|
-
end
|
299
311
|
|
300
|
-
|
301
|
-
|
312
|
+
service_stop() if respond_to?('service_stop')
|
313
|
+
ensure
|
314
|
+
SetEvent(@@hStopCompletedEvent)
|
315
|
+
end
|
302
316
|
end
|
303
317
|
|
304
318
|
if respond_to?('service_main')
|
data/lib/win32/service.rb
CHANGED
@@ -9,7 +9,7 @@ module Win32
|
|
9
9
|
# The Service class encapsulates services controller actions, such as
|
10
10
|
# creating, starting, configuring or deleting services.
|
11
11
|
class Service
|
12
|
-
include Windows::
|
12
|
+
include Windows::ServiceConstants
|
13
13
|
include Windows::Structs
|
14
14
|
include Windows::Functions
|
15
15
|
|
@@ -17,7 +17,7 @@ module Win32
|
|
17
17
|
extend Windows::Functions
|
18
18
|
|
19
19
|
# The version of the win32-service library
|
20
|
-
VERSION = '0.8.
|
20
|
+
VERSION = '0.8.6'
|
21
21
|
|
22
22
|
# SCM security and access rights
|
23
23
|
|
@@ -1075,12 +1075,18 @@ module Win32
|
|
1075
1075
|
|
1076
1076
|
deps = config_struct[:lpDependencies].read_array_of_null_separated_strings
|
1077
1077
|
|
1078
|
-
|
1079
|
-
|
1080
|
-
|
1078
|
+
begin
|
1079
|
+
buf = get_config2_info(handle_scs, SERVICE_CONFIG_DESCRIPTION)
|
1080
|
+
|
1081
|
+
if buf.is_a?(Fixnum) || buf.read_pointer.null?
|
1082
|
+
description = ''
|
1083
|
+
else
|
1084
|
+
description = buf.read_pointer.read_string
|
1085
|
+
end
|
1086
|
+
rescue
|
1087
|
+
# While being annoying, not being able to get a description is not exceptional
|
1088
|
+
warn "WARNING: Failed to retreive description for the #{service_name} service."
|
1081
1089
|
description = ''
|
1082
|
-
else
|
1083
|
-
description = buf.read_pointer.read_string
|
1084
1090
|
end
|
1085
1091
|
|
1086
1092
|
delayed_start_buf = get_config2_info(handle_scs, SERVICE_CONFIG_DELAYED_AUTO_START_INFO)
|
@@ -1367,7 +1373,7 @@ module Win32
|
|
1367
1373
|
#
|
1368
1374
|
if !bool && err_num == ERROR_INSUFFICIENT_BUFFER
|
1369
1375
|
config2_buf = FFI::MemoryPointer.new(:char, bytes_needed.read_ulong)
|
1370
|
-
elsif [ERROR_FILE_NOT_FOUND, ERROR_RESOURCE_TYPE_NOT_FOUND].include?(err_num)
|
1376
|
+
elsif [ERROR_FILE_NOT_FOUND, ERROR_RESOURCE_TYPE_NOT_FOUND, ERROR_RESOURCE_NAME_NOT_FOUND].include?(err_num)
|
1371
1377
|
return err_num
|
1372
1378
|
else
|
1373
1379
|
CloseServiceHandle(handle)
|
@@ -1,5 +1,5 @@
|
|
1
1
|
module Windows
|
2
|
-
module
|
2
|
+
module ServiceConstants
|
3
3
|
SC_MANAGER_ALL_ACCESS = 0xF003F
|
4
4
|
SC_MANAGER_CREATE_SERVICE = 0x0002
|
5
5
|
SC_MANAGER_CONNECT = 0x0001
|
@@ -137,6 +137,7 @@ module Windows
|
|
137
137
|
ERROR_MORE_DATA = 234
|
138
138
|
ERROR_FILE_NOT_FOUND = 2
|
139
139
|
ERROR_RESOURCE_TYPE_NOT_FOUND = 1813
|
140
|
+
ERROR_RESOURCE_NAME_NOT_FOUND = 1814
|
140
141
|
WAIT_FAILED = 0xFFFFFFFF
|
141
142
|
end
|
142
143
|
end
|
data/win32-service.gemspec
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: win32-service
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.8.
|
4
|
+
version: 0.8.6
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Daniel J. Berger
|
@@ -9,48 +9,48 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2014-
|
12
|
+
date: 2014-08-21 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: ffi
|
16
16
|
requirement: !ruby/object:Gem::Requirement
|
17
17
|
requirements:
|
18
|
-
- -
|
18
|
+
- - ">="
|
19
19
|
- !ruby/object:Gem::Version
|
20
20
|
version: '0'
|
21
21
|
type: :runtime
|
22
22
|
prerelease: false
|
23
23
|
version_requirements: !ruby/object:Gem::Requirement
|
24
24
|
requirements:
|
25
|
-
- -
|
25
|
+
- - ">="
|
26
26
|
- !ruby/object:Gem::Version
|
27
27
|
version: '0'
|
28
28
|
- !ruby/object:Gem::Dependency
|
29
29
|
name: test-unit
|
30
30
|
requirement: !ruby/object:Gem::Requirement
|
31
31
|
requirements:
|
32
|
-
- -
|
32
|
+
- - ">="
|
33
33
|
- !ruby/object:Gem::Version
|
34
34
|
version: '0'
|
35
35
|
type: :development
|
36
36
|
prerelease: false
|
37
37
|
version_requirements: !ruby/object:Gem::Requirement
|
38
38
|
requirements:
|
39
|
-
- -
|
39
|
+
- - ">="
|
40
40
|
- !ruby/object:Gem::Version
|
41
41
|
version: '0'
|
42
42
|
- !ruby/object:Gem::Dependency
|
43
43
|
name: rake
|
44
44
|
requirement: !ruby/object:Gem::Requirement
|
45
45
|
requirements:
|
46
|
-
- -
|
46
|
+
- - ">="
|
47
47
|
- !ruby/object:Gem::Version
|
48
48
|
version: '0'
|
49
49
|
type: :development
|
50
50
|
prerelease: false
|
51
51
|
version_requirements: !ruby/object:Gem::Requirement
|
52
52
|
requirements:
|
53
|
-
- -
|
53
|
+
- - ">="
|
54
54
|
- !ruby/object:Gem::Version
|
55
55
|
version: '0'
|
56
56
|
description: |2
|
@@ -102,17 +102,17 @@ require_paths:
|
|
102
102
|
- lib
|
103
103
|
required_ruby_version: !ruby/object:Gem::Requirement
|
104
104
|
requirements:
|
105
|
-
- -
|
105
|
+
- - ">="
|
106
106
|
- !ruby/object:Gem::Version
|
107
107
|
version: '0'
|
108
108
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
109
109
|
requirements:
|
110
|
-
- -
|
110
|
+
- - ">="
|
111
111
|
- !ruby/object:Gem::Version
|
112
112
|
version: '0'
|
113
113
|
requirements: []
|
114
114
|
rubyforge_project:
|
115
|
-
rubygems_version: 2.
|
115
|
+
rubygems_version: 2.3.0
|
116
116
|
signing_key:
|
117
117
|
specification_version: 4
|
118
118
|
summary: An interface for MS Windows services
|