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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: d9da3b7cac48ec6cfe0304595e3b6c6cdf8a7480
4
- data.tar.gz: e71218d14b39f03d49582806ae139306c4570883
3
+ metadata.gz: 9eb593fe954a9ad9baa295314a6deba834e416f5
4
+ data.tar.gz: b8ddb7267b81ea05bcf0c211ab684d07571a2d5b
5
5
  SHA512:
6
- metadata.gz: 7952a1dcd227fbcf118cbfdc1c3d9efcd681b82a4f3f10e331506e4cecae2456c3d181fe2c853d056c7c197f83b3d72d3506d0313234c6297127e5c0910fdda8
7
- data.tar.gz: 293fc5528459592f6cb781b48959db7184a88da758197271fa3f2bc2ed74c717b79e558d87381820b66c2d5cf2e1cc418b88e1efb915421f0d3674e40446a3de
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
@@ -10,7 +10,7 @@ module Win32
10
10
 
11
11
  # The Daemon class
12
12
  class Daemon
13
- include Windows::Constants
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.4'
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
- dwState = SERVICE_RUNNING
111
-
112
- case dwCtrlCode
113
- when SERVICE_CONTROL_STOP
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
- # Tell service_main thread to stop.
131
- if dwCtrlCode == SERVICE_CONTROL_STOP || dwCtrlCode == SERVICE_CONTROL_SHUTDOWN
132
- if !SetEvent(@@hStopEvent)
133
- SetTheServiceStatus.call(SERVICE_STOPPED, FFI.errno, 0, 0)
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
- # Obtain the name of the service.
141
- if lpszArgv.address!=0
142
- argv = lpszArgv.get_array_of_string(0,dwArgc)
143
- lpszServiceName = argv[0]
144
- else
145
- lpszServiceName = ''
146
- end
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
- # Args passed to Service.start
149
- if(dwArgc > 1)
150
- @@Argv = argv[1..-1]
151
- else
152
- @@Argv = nil
153
- end
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
- # Register the service ctrl handler.
156
- @@ssh = RegisterServiceCtrlHandlerEx(
157
- lpszServiceName,
158
- Service_Ctrl_ex,
159
- nil
160
- )
165
+ # Register the service ctrl handler.
166
+ @@ssh = RegisterServiceCtrlHandlerEx(
167
+ lpszServiceName,
168
+ Service_Ctrl_ex,
169
+ nil
170
+ )
161
171
 
162
- # No service to stop, no service handle to notify, nothing to do but exit.
163
- return if @@ssh == 0
172
+ # No service to stop, no service handle to notify, nothing to do but exit.
173
+ return if @@ssh == 0
164
174
 
165
- # The service has started.
166
- SetTheServiceStatus.call(SERVICE_RUNNING, NO_ERROR, 0, 0)
175
+ # The service has started.
176
+ SetTheServiceStatus.call(SERVICE_RUNNING, NO_ERROR, 0, 0)
167
177
 
168
- SetEvent(@@hStartEvent)
178
+ SetEvent(@@hStartEvent)
169
179
 
170
- # Main loop for the service.
171
- while(WaitForSingleObject(@@hStopEvent, 1000) != WAIT_OBJECT_0) do
172
- end
180
+ # Main loop for the service.
181
+ while(WaitForSingleObject(@@hStopEvent, 1000) != WAIT_OBJECT_0) do
182
+ end
173
183
 
174
- # Main loop for the service.
175
- while(WaitForSingleObject(@@hStopCompletedEvent, 1000) != WAIT_OBJECT_0) do
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] = Service_Main
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, nil, 0, nil)
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, FFI::Pointer.size*2)
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
- while(WaitForSingleObject(@@hStopEvent, 10) == WAIT_TIMEOUT)
276
- # Check to see if anything interesting has been signaled
277
- case @@waiting_control_code
278
- when SERVICE_CONTROL_PAUSE
279
- service_pause() if respond_to?('service_pause')
280
- when SERVICE_CONTROL_CONTINUE
281
- service_resume() if respond_to?('service_resume')
282
- when SERVICE_CONTROL_INTERROGATE
283
- service_interrogate() if respond_to?('service_interrogate')
284
- when SERVICE_CONTROL_SHUTDOWN
285
- service_shutdown() if respond_to?('service_shutdown')
286
- when SERVICE_CONTROL_PARAMCHANGE
287
- service_paramchange() if respond_to?('service_paramchange')
288
- when SERVICE_CONTROL_NETBINDADD
289
- service_netbindadd() if respond_to?('service_netbindadd')
290
- when SERVICE_CONTROL_NETBINDREMOVE
291
- service_netbindremove() if respond_to?('service_netbindremove')
292
- when SERVICE_CONTROL_NETBINDENABLE
293
- service_netbindenable() if respond_to?('service_netbindenable')
294
- when SERVICE_CONTROL_NETBINDDISABLE
295
- service_netbinddisable() if respond_to?('service_netbinddisable')
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
- service_stop() if respond_to?('service_stop')
301
- SetEvent(@@hStopCompletedEvent)
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')
@@ -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::Constants
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.5'
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
- buf = get_config2_info(handle_scs, SERVICE_CONFIG_DESCRIPTION)
1079
-
1080
- if buf.is_a?(Fixnum) || buf.read_pointer.null?
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 Constants
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
@@ -2,7 +2,7 @@ require 'rubygems'
2
2
 
3
3
  Gem::Specification.new do |spec|
4
4
  spec.name = 'win32-service'
5
- spec.version = '0.8.5'
5
+ spec.version = '0.8.6'
6
6
  spec.authors = ['Daniel J. Berger', 'Park Heesob']
7
7
  spec.license = 'Artistic 2.0'
8
8
  spec.email = 'djberg96@gmail.com'
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.5
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-07-03 00:00:00.000000000 Z
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.2.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