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 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