win32-service 0.6.0 → 0.6.1

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.
data/CHANGES CHANGED
@@ -1,3 +1,10 @@
1
+ == 0.6.1 - 1-Jan-2008
2
+ * The Service.services method now handles the scenario where a particular
3
+ service may still exist, but its underlying registry entry has been deleted.
4
+ In this case, most ServiceInfo struct members are set to nil and a warning
5
+ is issued.
6
+ * RDoc updates.
7
+
1
8
  == 0.6.0 - 25-Nov-2007
2
9
  * The Service control class is now pure Ruby. The Daemon class is still C,
3
10
  however. That may change in the future. This means the windows-pr
data/doc/daemon.txt CHANGED
@@ -140,7 +140,7 @@ Daemon::IDLE
140
140
  service responsiveness issues.
141
141
 
142
142
  = Copyright
143
- (C) 2003-2007 Daniel J. Berger, All Rights Reserved
143
+ (C) 2003-2008 Daniel J. Berger, All Rights Reserved
144
144
 
145
145
  = License
146
146
  Ruby's
data/doc/service.txt CHANGED
@@ -16,8 +16,6 @@
16
16
  require "win32/service"
17
17
  include Win32
18
18
 
19
- s = Service.new("some_machine")
20
-
21
19
  # Create a new service
22
20
  Service.create('some_service', nil,
23
21
  :service_type => Service::WIN32_OWN_PROCESS,
@@ -352,7 +350,7 @@ Service::ERROR_CRITICAL
352
350
  Use RegisterServiceCtrlHandlerEx().
353
351
 
354
352
  = Copyright
355
- (C) 2003-2007, Daniel J. Berger, All Rights Reserved
353
+ (C) 2003-2008, Daniel J. Berger, All Rights Reserved
356
354
 
357
355
  = License
358
356
  Ruby's
data/ext/win32/daemon.c CHANGED
@@ -5,7 +5,7 @@
5
5
  #include <malloc.h>
6
6
  #include <tchar.h>
7
7
 
8
- #define WIN32_SERVICE_VERSION "0.6.0"
8
+ #define WIN32_SERVICE_VERSION "0.6.1"
9
9
 
10
10
  static VALUE cDaemonError;
11
11
 
@@ -482,15 +482,15 @@ static VALUE daemon_mainloop(VALUE self)
482
482
  * of the service status constants, e.g. RUNNING, PAUSED, etc.
483
483
  *
484
484
  * This method is typically used within your service_main method to setup the
485
- * loop. For example:
485
+ * loop. For example:
486
486
  *
487
- * class MyDaemon < Daemon
488
- * def service_main
489
- * while state == RUNNING || state == PAUSED || state == IDLE
490
- * # Your main loop here
491
- * end
492
- * end
493
- * end
487
+ * class MyDaemon < Daemon
488
+ * def service_main
489
+ * while state == RUNNING || state == PAUSED || state == IDLE
490
+ * # Your main loop here
491
+ * end
492
+ * end
493
+ * end
494
494
  *
495
495
  * See the Daemon#running? method for an abstraction of the above code.
496
496
  */
@@ -503,15 +503,15 @@ static VALUE daemon_state(VALUE self){
503
503
  * status is either RUNNING, PAUSED or IDLE.
504
504
  *
505
505
  * This is typically used within your service_main method to setup the main
506
- * loop. For example:
506
+ * loop. For example:
507
507
  *
508
- * class MyDaemon < Daemon
509
- * def service_main
510
- * while running?
511
- * # Your main loop here
508
+ * class MyDaemon < Daemon
509
+ * def service_main
510
+ * while running?
511
+ * # Your main loop here
512
+ * end
512
513
  * end
513
514
  * end
514
- * end
515
515
  */
516
516
  static VALUE daemon_is_running(VALUE self){
517
517
  VALUE v_bool = Qfalse;
@@ -527,7 +527,7 @@ static VALUE daemon_is_running(VALUE self){
527
527
  }
528
528
 
529
529
  /*
530
- * This is a shortcut for Daemon#new + Daemon#mainloop.
530
+ * This is a shortcut for Daemon.new + Daemon#mainloop.
531
531
  */
532
532
  static VALUE daemon_c_mainloop(VALUE klass){
533
533
  VALUE v_args[1];
@@ -537,11 +537,15 @@ static VALUE daemon_c_mainloop(VALUE klass){
537
537
 
538
538
  void Init_daemon()
539
539
  {
540
- VALUE mWin32, cDaemon;
540
+ /* The Win32 module serves as a namespace only. */
541
+ VALUE mWin32 = rb_define_module("Win32");
542
+
543
+ /* The Daemon class encapsulates a Windows service through the use
544
+ * of callback methods and a main loop.
545
+ */
546
+ VALUE cDaemon = rb_define_class_under(mWin32, "Daemon", rb_cObject);
541
547
 
542
- // Modules and classes
543
- mWin32 = rb_define_module("Win32");
544
- cDaemon = rb_define_class_under(mWin32, "Daemon", rb_cObject);
548
+ /* Error typically raised if something goes wrong with your daemon. */
545
549
  cDaemonError = rb_define_class_under(cDaemon, "Error", rb_eStandardError);
546
550
 
547
551
  rb_define_alloc_func(cDaemon, daemon_allocate);
@@ -556,7 +560,7 @@ void Init_daemon()
556
560
 
557
561
  // Constants
558
562
 
559
- /* 0.6.0: The version of this library */
563
+ /* 0.6.1: The version of this library */
560
564
  rb_define_const(cDaemon, "VERSION", rb_str_new2(WIN32_SERVICE_VERSION));
561
565
 
562
566
  /* Service has received a signal to resume but is not yet running */
data/lib/win32/service.rb CHANGED
@@ -6,8 +6,15 @@ require 'windows/security'
6
6
  require 'windows/msvcrt/string'
7
7
  require 'windows/msvcrt/buffer'
8
8
 
9
+ # The Win32 module serves as a namespace only.
9
10
  module Win32
11
+
12
+ # The Service class encapsulates services controller actions, such as
13
+ # creating, starting, configuring or deleting services.
10
14
  class Service
15
+
16
+ # This is the error typically raised if one of the Service methods
17
+ # should fail for any reason.
11
18
  class Error < StandardError; end
12
19
 
13
20
  include Windows::Error
@@ -25,7 +32,7 @@ module Win32
25
32
  extend Windows::MSVCRT::String
26
33
  extend Windows::MSVCRT::Buffer
27
34
 
28
- VERSION = '0.6.0'
35
+ VERSION = '0.6.1'
29
36
 
30
37
  # SCM security and access rights
31
38
 
@@ -197,6 +204,7 @@ module Win32
197
204
  # Run a command
198
205
  ACTION_RUN_COMMAND = SC_ACTION_RUN_COMMAND
199
206
 
207
+ # :stopdoc: #
200
208
  StatusStruct = Struct.new('ServiceStatus', :service_type,
201
209
  :current_state, :controls_accepted, :win32_exit_code,
202
210
  :service_specific_exit_code, :check_point, :wait_hint, :interactive,
@@ -216,6 +224,8 @@ module Win32
216
224
  :description, :interactive, :pid, :service_flags, :reset_period,
217
225
  :reboot_message, :command, :num_actions, :actions
218
226
  )
227
+
228
+ # :startdoc: #
219
229
 
220
230
  # Creates a new service with +service_name+ on +host+, or the local host
221
231
  # if no host is specified. The +options+ parameter is a hash that can
@@ -242,7 +252,7 @@ module Win32
242
252
  # Example:
243
253
  #
244
254
  # # Configure everything
245
- # Service.create('some_service', nil,
255
+ # Service.new('some_service', nil,
246
256
  # :service_type => Service::WIN32_OWN_PROCESS,
247
257
  # :description => 'A custom service I wrote just for fun',
248
258
  # :start_type => Service::AUTO_START,
@@ -1084,59 +1094,81 @@ module Win32
1084
1094
 
1085
1095
  config_buf = get_config_info(handle_scs)
1086
1096
 
1087
- binary_path = 0.chr * 260
1088
- strcpy(binary_path, config_buf[12,4].unpack('L').first)
1089
- binary_path = binary_path.unpack('Z*')[0]
1097
+ if config_buf != ERROR_FILE_NOT_FOUND
1098
+ binary_path = 0.chr * 260
1099
+ strcpy(binary_path, config_buf[12,4].unpack('L').first)
1100
+ binary_path = binary_path.unpack('Z*')[0]
1090
1101
 
1091
- load_order = 0.chr * 260
1092
- strcpy(load_order, config_buf[16,4].unpack('L').first)
1093
- load_order = load_order.unpack('Z*')[0]
1102
+ load_order = 0.chr * 260
1103
+ strcpy(load_order, config_buf[16,4].unpack('L').first)
1104
+ load_order = load_order.unpack('Z*')[0]
1094
1105
 
1095
- start_name = 0.chr * 260
1096
- strcpy(start_name, config_buf[28,4].unpack('L').first)
1097
- start_name = start_name.unpack('Z*')[0]
1106
+ start_name = 0.chr * 260
1107
+ strcpy(start_name, config_buf[28,4].unpack('L').first)
1108
+ start_name = start_name.unpack('Z*')[0]
1098
1109
 
1099
- start_type = get_start_type(config_buf[4,4].unpack('L').first)
1100
- error_control = get_error_control(config_buf[8,4].unpack('L').first)
1110
+ start_type = get_start_type(config_buf[4,4].unpack('L').first)
1111
+ error_ctrl = get_error_control(config_buf[8,4].unpack('L').first)
1101
1112
 
1102
- tag_id = config_buf[20,4].unpack('L').first
1113
+ tag_id = config_buf[20,4].unpack('L').first
1103
1114
 
1104
- dependencies = get_dependencies(config_buf[24,4].unpack('L').first)
1115
+ deps = get_dependencies(config_buf[24,4].unpack('L').first)
1105
1116
 
1106
- description = 0.chr * 1024
1107
- buf = get_config2_info(handle_scs, SERVICE_CONFIG_DESCRIPTION)
1117
+ description = 0.chr * 1024
1118
+ buf = get_config2_info(handle_scs, SERVICE_CONFIG_DESCRIPTION)
1108
1119
 
1109
- strcpy(description, buf[0,4].unpack('L').first)
1110
- description = description.unpack('Z*')[0]
1120
+ strcpy(description, buf[0,4].unpack('L').first)
1121
+ description = description.unpack('Z*')[0]
1122
+ else
1123
+ msg = "WARNING: The registry entry for the #{service_name} "
1124
+ msg += "service could not be found."
1125
+ warn msg
1126
+
1127
+ binary_path = nil
1128
+ load_order = nil
1129
+ start_name = nil
1130
+ start_type = nil
1131
+ error_ctrl = nil
1132
+ tag_id = nil
1133
+ deps = nil
1134
+ description = nil
1135
+ end
1111
1136
 
1112
1137
  buf2 = get_config2_info(handle_scs, SERVICE_CONFIG_FAILURE_ACTIONS)
1113
1138
 
1114
- reset_period = buf2[0,4].unpack('L').first
1139
+ if buf2 != ERROR_FILE_NOT_FOUND
1140
+ reset_period = buf2[0,4].unpack('L').first
1115
1141
 
1116
- reboot_msg = 0.chr * 260
1117
- strcpy(reboot_msg, buf2[4,4].unpack('L').first)
1118
- reboot_msg = reboot_msg.unpack('Z*')[0]
1142
+ reboot_msg = 0.chr * 260
1143
+ strcpy(reboot_msg, buf2[4,4].unpack('L').first)
1144
+ reboot_msg = reboot_msg.unpack('Z*')[0]
1119
1145
 
1120
- command = 0.chr * 260
1121
- strcpy(command, buf2[8,4].unpack('L').first)
1122
- command = command.unpack('Z*')[0]
1146
+ command = 0.chr * 260
1147
+ strcpy(command, buf2[8,4].unpack('L').first)
1148
+ command = command.unpack('Z*')[0]
1123
1149
 
1124
- num_actions = buf2[12,4].unpack('L').first
1125
- actions = nil
1150
+ num_actions = buf2[12,4].unpack('L').first
1151
+ actions = nil
1126
1152
 
1127
- if num_actions > 0
1128
- action_ptr = buf2[16,4].unpack('L').first
1129
- action_buf = [0,0].pack('LL') * num_actions
1130
- memcpy(action_buf, action_ptr, action_buf.size)
1153
+ if num_actions > 0
1154
+ action_ptr = buf2[16,4].unpack('L').first
1155
+ action_buf = [0,0].pack('LL') * num_actions
1156
+ memcpy(action_buf, action_ptr, action_buf.size)
1131
1157
 
1132
- i = 0
1133
- actions = {}
1134
- num_actions.times{ |n|
1135
- action_type, delay = action_buf[i, 8].unpack('LL')
1136
- action_type = get_action_type(action_type)
1137
- actions[n+1] = {:action_type => action_type, :delay => delay}
1138
- i += 8
1139
- }
1158
+ i = 0
1159
+ actions = {}
1160
+ num_actions.times{ |n|
1161
+ action_type, delay = action_buf[i, 8].unpack('LL')
1162
+ action_type = get_action_type(action_type)
1163
+ actions[n+1] = {:action_type => action_type, :delay => delay}
1164
+ i += 8
1165
+ }
1166
+ end
1167
+ else
1168
+ reset_period = nil
1169
+ reboot_message = nil
1170
+ command = nil
1171
+ actions = nil
1140
1172
  end
1141
1173
 
1142
1174
  CloseServiceHandle(handle_scs)
@@ -1153,11 +1185,11 @@ module Win32
1153
1185
  wait_hint,
1154
1186
  binary_path,
1155
1187
  start_type,
1156
- error_control,
1188
+ error_ctrl,
1157
1189
  load_order,
1158
1190
  tag_id,
1159
1191
  start_name,
1160
- dependencies,
1192
+ deps,
1161
1193
  description,
1162
1194
  interactive,
1163
1195
  pid,
@@ -1316,7 +1348,10 @@ module Win32
1316
1348
  end
1317
1349
  end
1318
1350
 
1319
- # Shortcut for QueryServiceConfig. Returns the buffer.
1351
+ # Shortcut for QueryServiceConfig. Returns the buffer. In rare cases
1352
+ # the underlying registry entry may have been deleted, but the service
1353
+ # still exists. In that case, the ERROR_FILE_NOT_FOUND value is returned
1354
+ # instead.
1320
1355
  #
1321
1356
  def self.get_config_info(handle)
1322
1357
  bytes_needed = [0].pack('L')
@@ -1328,6 +1363,8 @@ module Win32
1328
1363
 
1329
1364
  if !bool && err_num == ERROR_INSUFFICIENT_BUFFER
1330
1365
  config_buf = 0.chr * bytes_needed.unpack('L').first
1366
+ elsif err_num == ERROR_FILE_NOT_FOUND
1367
+ return err_num
1331
1368
  else
1332
1369
  error = get_last_error(err_num)
1333
1370
  CloseServiceHandle(handle)
@@ -1361,13 +1398,15 @@ module Win32
1361
1398
  # First attempt at QueryServiceConfig2 is to get size needed
1362
1399
  bool = QueryServiceConfig2(handle, info_level, 0, 0, bytes_needed)
1363
1400
 
1364
- error = GetLastError()
1401
+ err_num = GetLastError()
1365
1402
 
1366
- if !bool && error == ERROR_INSUFFICIENT_BUFFER
1403
+ if !bool && err_num == ERROR_INSUFFICIENT_BUFFER
1367
1404
  config2_buf = 0.chr * bytes_needed.unpack('L').first
1405
+ elsif err_num == ERROR_FILE_NOT_FOUND
1406
+ return err_num
1368
1407
  else
1369
1408
  CloseServiceHandle(handle)
1370
- raise Error, error
1409
+ raise Error, get_last_error(err_num)
1371
1410
  end
1372
1411
 
1373
1412
  bytes_needed = [0].pack('L')
@@ -1382,8 +1421,9 @@ module Win32
1382
1421
  )
1383
1422
 
1384
1423
  unless bool
1424
+ error = GetLastError()
1385
1425
  CloseServiceHandle(handle)
1386
- raise Error, get_last_error
1426
+ raise Error, get_last_error(error)
1387
1427
  end
1388
1428
 
1389
1429
  config2_buf
data/test/tc_daemon.rb CHANGED
@@ -17,7 +17,7 @@ class TC_Daemon < Test::Unit::TestCase
17
17
  end
18
18
 
19
19
  def test_version
20
- assert_equal('0.6.0', Daemon::VERSION)
20
+ assert_equal('0.6.1', Daemon::VERSION)
21
21
  end
22
22
 
23
23
  def test_constructor
data/test/tc_service.rb CHANGED
@@ -20,7 +20,7 @@ class TC_Win32_Service < Test::Unit::TestCase
20
20
  end
21
21
 
22
22
  def test_version
23
- assert_equal('0.6.0', Win32::Service::VERSION)
23
+ assert_equal('0.6.1', Win32::Service::VERSION)
24
24
  end
25
25
 
26
26
  def test_service_configure
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.6.0
4
+ version: 0.6.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Daniel J. Berger
@@ -9,7 +9,7 @@ autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
11
 
12
- date: 2007-11-25 00:00:00 -07:00
12
+ date: 2008-01-01 00:00:00 -07:00
13
13
  default_executable:
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
@@ -35,18 +35,18 @@ extra_rdoc_files:
35
35
  - doc/service.txt
36
36
  - doc/daemon.txt
37
37
  files:
38
+ - doc/daemon.txt
39
+ - doc/service.txt
38
40
  - test/tc_daemon.rb
39
41
  - test/tc_service.rb
40
42
  - test/tc_service_create.rb
41
43
  - test/tc_service_info.rb
42
44
  - test/tc_service_status.rb
43
45
  - lib/win32/service.rb
46
+ - ext/win32/daemon.c
44
47
  - CHANGES
45
48
  - README
46
49
  - MANIFEST
47
- - ext/win32/daemon.c
48
- - doc/service.txt
49
- - doc/daemon.txt
50
50
  has_rdoc: true
51
51
  homepage: http://www.rubyforge.org/projects/win32utils
52
52
  post_install_message:
@@ -69,7 +69,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
69
69
  requirements: []
70
70
 
71
71
  rubyforge_project: win32utils
72
- rubygems_version: 0.9.5
72
+ rubygems_version: 1.0.1
73
73
  signing_key:
74
74
  specification_version: 2
75
75
  summary: An library for controlling and creating MS Windows services