win32-service 0.8.5 → 0.8.6
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/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
|