win32-service 2.2.0 → 2.3.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/lib/win32/daemon.rb +54 -50
- data/lib/win32/service.rb +221 -221
- data/lib/win32/windows/functions.rb +27 -27
- data/lib/win32/windows/structs.rb +1 -1
- data/lib/win32/windows/version.rb +1 -1
- data/lib/win32-daemon.rb +1 -1
- data/lib/win32-service.rb +1 -1
- metadata +3 -17
data/lib/win32/service.rb
CHANGED
@@ -1,8 +1,8 @@
|
|
1
|
-
require
|
2
|
-
require_relative
|
3
|
-
require_relative
|
4
|
-
require_relative
|
5
|
-
require_relative
|
1
|
+
require "ffi/win32/extensions"
|
2
|
+
require_relative "windows/version"
|
3
|
+
require_relative "windows/constants"
|
4
|
+
require_relative "windows/structs"
|
5
|
+
require_relative "windows/functions"
|
6
6
|
|
7
7
|
# The Win32 module serves as a namespace only.
|
8
8
|
module Win32
|
@@ -76,7 +76,7 @@ module Win32
|
|
76
76
|
KERNEL_DRIVER = SERVICE_KERNEL_DRIVER
|
77
77
|
|
78
78
|
# File system driver service
|
79
|
-
FILE_SYSTEM_DRIVER
|
79
|
+
FILE_SYSTEM_DRIVER = SERVICE_FILE_SYSTEM_DRIVER
|
80
80
|
|
81
81
|
# Service that runs in its own process
|
82
82
|
WIN32_OWN_PROCESS = SERVICE_WIN32_OWN_PROCESS
|
@@ -190,7 +190,7 @@ module Win32
|
|
190
190
|
# :stopdoc: #
|
191
191
|
|
192
192
|
StatusStruct = Struct.new(
|
193
|
-
|
193
|
+
"ServiceStatus",
|
194
194
|
:service_type,
|
195
195
|
:current_state,
|
196
196
|
:controls_accepted,
|
@@ -204,7 +204,7 @@ module Win32
|
|
204
204
|
)
|
205
205
|
|
206
206
|
ConfigStruct = Struct.new(
|
207
|
-
|
207
|
+
"ServiceConfigInfo",
|
208
208
|
:service_type,
|
209
209
|
:start_type,
|
210
210
|
:error_control,
|
@@ -217,7 +217,7 @@ module Win32
|
|
217
217
|
)
|
218
218
|
|
219
219
|
ServiceStruct = Struct.new(
|
220
|
-
|
220
|
+
"ServiceInfo",
|
221
221
|
:service_name,
|
222
222
|
:display_name,
|
223
223
|
:service_type,
|
@@ -291,51 +291,52 @@ module Win32
|
|
291
291
|
# :display_name => 'This is some service',
|
292
292
|
# )
|
293
293
|
#
|
294
|
-
def initialize(options={})
|
294
|
+
def initialize(options = {})
|
295
295
|
unless options.is_a?(Hash)
|
296
|
-
raise ArgumentError,
|
296
|
+
raise ArgumentError, "options parameter must be a hash"
|
297
297
|
end
|
298
298
|
|
299
299
|
if options.empty?
|
300
|
-
raise ArgumentError,
|
300
|
+
raise ArgumentError, "no options provided"
|
301
301
|
end
|
302
302
|
|
303
303
|
opts = {
|
304
|
-
|
305
|
-
|
306
|
-
|
307
|
-
|
308
|
-
|
309
|
-
|
310
|
-
|
311
|
-
|
312
|
-
|
313
|
-
|
314
|
-
|
315
|
-
|
316
|
-
|
317
|
-
|
318
|
-
|
319
|
-
|
320
|
-
|
321
|
-
|
304
|
+
"display_name" => nil,
|
305
|
+
"desired_access" => SERVICE_ALL_ACCESS,
|
306
|
+
"service_type" => SERVICE_WIN32_OWN_PROCESS,
|
307
|
+
"start_type" => SERVICE_DEMAND_START,
|
308
|
+
"error_control" => SERVICE_ERROR_NORMAL,
|
309
|
+
"binary_path_name" => nil,
|
310
|
+
"load_order_group" => nil,
|
311
|
+
"dependencies" => nil,
|
312
|
+
"service_start_name" => nil,
|
313
|
+
"password" => nil,
|
314
|
+
"description" => nil,
|
315
|
+
"failure_reset_period" => nil,
|
316
|
+
"failure_reboot_message" => nil,
|
317
|
+
"failure_command" => nil,
|
318
|
+
"failure_actions" => nil,
|
319
|
+
"failure_delay" => 0,
|
320
|
+
"host" => nil,
|
321
|
+
"service_name" => nil,
|
322
322
|
}
|
323
323
|
|
324
324
|
# Validate the hash options
|
325
|
-
options.each{ |key, value|
|
325
|
+
options.each { |key, value|
|
326
326
|
key = key.to_s.downcase
|
327
327
|
unless opts.include?(key)
|
328
328
|
raise ArgumentError, "Invalid option '#{key}'"
|
329
329
|
end
|
330
|
+
|
330
331
|
opts[key] = value
|
331
332
|
}
|
332
333
|
|
333
|
-
unless opts[
|
334
|
-
raise ArgumentError,
|
334
|
+
unless opts["service_name"]
|
335
|
+
raise ArgumentError, "No service_name specified"
|
335
336
|
end
|
336
337
|
|
337
|
-
service_name = opts.delete(
|
338
|
-
host = opts.delete(
|
338
|
+
service_name = opts.delete("service_name")
|
339
|
+
host = opts.delete("host")
|
339
340
|
|
340
341
|
raise TypeError unless service_name.is_a?(String)
|
341
342
|
raise TypeError if host && !host.is_a?(String)
|
@@ -343,16 +344,16 @@ module Win32
|
|
343
344
|
begin
|
344
345
|
handle_scm = OpenSCManager(host, nil, SC_MANAGER_CREATE_SERVICE)
|
345
346
|
|
346
|
-
FFI.raise_windows_error(
|
347
|
+
FFI.raise_windows_error("OpenSCManager") if handle_scm == 0
|
347
348
|
|
348
349
|
# Display name defaults to service_name
|
349
|
-
opts[
|
350
|
+
opts["display_name"] ||= service_name
|
350
351
|
|
351
|
-
dependencies = opts[
|
352
|
+
dependencies = opts["dependencies"]
|
352
353
|
|
353
354
|
if dependencies && !dependencies.empty?
|
354
355
|
unless dependencies.is_a?(Array) || dependencies.is_a?(String)
|
355
|
-
raise TypeError,
|
356
|
+
raise TypeError, "dependencies must be a string or array"
|
356
357
|
end
|
357
358
|
|
358
359
|
if dependencies.is_a?(Array)
|
@@ -366,24 +367,24 @@ module Win32
|
|
366
367
|
handle_scs = CreateService(
|
367
368
|
handle_scm,
|
368
369
|
service_name,
|
369
|
-
opts[
|
370
|
-
opts[
|
371
|
-
opts[
|
372
|
-
opts[
|
373
|
-
opts[
|
374
|
-
opts[
|
375
|
-
opts[
|
370
|
+
opts["display_name"],
|
371
|
+
opts["desired_access"],
|
372
|
+
opts["service_type"],
|
373
|
+
opts["start_type"],
|
374
|
+
opts["error_control"],
|
375
|
+
opts["binary_path_name"],
|
376
|
+
opts["load_order_group"],
|
376
377
|
nil,
|
377
378
|
dependencies,
|
378
|
-
opts[
|
379
|
-
opts[
|
379
|
+
opts["service_start_name"],
|
380
|
+
opts["password"]
|
380
381
|
)
|
381
382
|
|
382
|
-
FFI.raise_windows_error(
|
383
|
+
FFI.raise_windows_error("CreateService") if handle_scs == 0
|
383
384
|
|
384
|
-
if opts[
|
385
|
+
if opts["description"]
|
385
386
|
description = SERVICE_DESCRIPTION.new
|
386
|
-
description[:lpDescription] = FFI::MemoryPointer.from_string(opts[
|
387
|
+
description[:lpDescription] = FFI::MemoryPointer.from_string(opts["description"])
|
387
388
|
|
388
389
|
bool = ChangeServiceConfig2(
|
389
390
|
handle_scs,
|
@@ -391,12 +392,11 @@ module Win32
|
|
391
392
|
description
|
392
393
|
)
|
393
394
|
|
394
|
-
FFI.raise_windows_error(
|
395
|
+
FFI.raise_windows_error("ChangeServiceConfig2") unless bool
|
395
396
|
end
|
396
397
|
|
397
|
-
if opts[
|
398
|
-
|
399
|
-
then
|
398
|
+
if opts["failure_reset_period"] || opts["failure_reboot_message"] ||
|
399
|
+
opts["failure_command"] || opts["failure_actions"]
|
400
400
|
self.class.configure_failure_actions(handle_scs, opts)
|
401
401
|
end
|
402
402
|
ensure
|
@@ -450,63 +450,67 @@ module Win32
|
|
450
450
|
# :description => 'A custom service I wrote just for fun'
|
451
451
|
# )
|
452
452
|
#
|
453
|
-
def self.configure(options={})
|
453
|
+
def self.configure(options = {})
|
454
454
|
unless options.is_a?(Hash)
|
455
|
-
raise ArgumentError,
|
455
|
+
raise ArgumentError, "options parameter must be a hash"
|
456
456
|
end
|
457
457
|
|
458
458
|
if options.empty?
|
459
|
-
raise ArgumentError,
|
459
|
+
raise ArgumentError, "no options provided"
|
460
460
|
end
|
461
461
|
|
462
462
|
opts = {
|
463
|
-
|
464
|
-
|
465
|
-
|
466
|
-
|
467
|
-
|
468
|
-
|
469
|
-
|
470
|
-
|
471
|
-
|
472
|
-
|
473
|
-
|
474
|
-
|
475
|
-
|
476
|
-
|
477
|
-
|
478
|
-
|
479
|
-
|
480
|
-
|
463
|
+
"service_type" => SERVICE_NO_CHANGE,
|
464
|
+
"start_type" => SERVICE_NO_CHANGE,
|
465
|
+
"error_control" => SERVICE_NO_CHANGE,
|
466
|
+
"binary_path_name" => nil,
|
467
|
+
"load_order_group" => nil,
|
468
|
+
"dependencies" => nil,
|
469
|
+
"service_start_name" => nil,
|
470
|
+
"password" => nil,
|
471
|
+
"display_name" => nil,
|
472
|
+
"description" => nil,
|
473
|
+
"failure_reset_period" => nil,
|
474
|
+
"failure_reboot_message" => nil,
|
475
|
+
"failure_command" => nil,
|
476
|
+
"failure_actions" => nil,
|
477
|
+
"failure_delay" => 0,
|
478
|
+
"service_name" => nil,
|
479
|
+
"host" => nil,
|
480
|
+
"delayed_start" => false,
|
481
481
|
}
|
482
482
|
|
483
483
|
# Validate the hash options
|
484
|
-
options.each{ |key, value|
|
484
|
+
options.each { |key, value|
|
485
485
|
key = key.to_s.downcase
|
486
486
|
unless opts.include?(key)
|
487
487
|
raise ArgumentError, "Invalid option '#{key}'"
|
488
488
|
end
|
489
|
+
|
489
490
|
opts[key] = value
|
490
491
|
}
|
491
492
|
|
492
|
-
unless opts[
|
493
|
-
raise ArgumentError,
|
493
|
+
unless opts["service_name"]
|
494
|
+
raise ArgumentError, "No service_name specified"
|
494
495
|
end
|
495
496
|
|
496
|
-
service = opts.delete(
|
497
|
-
host = opts.delete(
|
497
|
+
service = opts.delete("service_name")
|
498
|
+
host = opts.delete("host")
|
498
499
|
|
499
500
|
raise TypeError unless service.is_a?(String)
|
500
|
-
|
501
|
+
|
502
|
+
if host
|
503
|
+
raise TypeError unless host.is_a?(String)
|
504
|
+
end
|
501
505
|
|
502
506
|
begin
|
503
507
|
handle_scm = OpenSCManager(host, nil, SC_MANAGER_CONNECT)
|
504
508
|
|
505
|
-
FFI.raise_windows_error(
|
509
|
+
FFI.raise_windows_error("OpenSCManager") if handle_scm == 0
|
506
510
|
|
507
511
|
desired_access = SERVICE_CHANGE_CONFIG
|
508
512
|
|
509
|
-
if opts[
|
513
|
+
if opts["failure_actions"]
|
510
514
|
desired_access |= SERVICE_START
|
511
515
|
end
|
512
516
|
|
@@ -516,13 +520,13 @@ module Win32
|
|
516
520
|
desired_access
|
517
521
|
)
|
518
522
|
|
519
|
-
FFI.raise_windows_error(
|
523
|
+
FFI.raise_windows_error("OpenService") if handle_scs == 0
|
520
524
|
|
521
|
-
dependencies = opts[
|
525
|
+
dependencies = opts["dependencies"]
|
522
526
|
|
523
527
|
if dependencies && !dependencies.empty?
|
524
528
|
unless dependencies.is_a?(Array) || dependencies.is_a?(String)
|
525
|
-
raise TypeError,
|
529
|
+
raise TypeError, "dependencies must be a string or array"
|
526
530
|
end
|
527
531
|
|
528
532
|
if dependencies.is_a?(Array)
|
@@ -534,23 +538,23 @@ module Win32
|
|
534
538
|
|
535
539
|
bool = ChangeServiceConfig(
|
536
540
|
handle_scs,
|
537
|
-
opts[
|
538
|
-
opts[
|
539
|
-
opts[
|
540
|
-
opts[
|
541
|
-
opts[
|
541
|
+
opts["service_type"],
|
542
|
+
opts["start_type"],
|
543
|
+
opts["error_control"],
|
544
|
+
opts["binary_path_name"],
|
545
|
+
opts["load_order_group"],
|
542
546
|
nil,
|
543
547
|
dependencies,
|
544
|
-
opts[
|
545
|
-
opts[
|
546
|
-
opts[
|
548
|
+
opts["service_start_name"],
|
549
|
+
opts["password"],
|
550
|
+
opts["display_name"]
|
547
551
|
)
|
548
552
|
|
549
|
-
FFI.raise_windows_error(
|
553
|
+
FFI.raise_windows_error("ChangeServiceConfig") unless bool
|
550
554
|
|
551
|
-
if opts[
|
555
|
+
if opts["description"]
|
552
556
|
description = SERVICE_DESCRIPTION.new
|
553
|
-
description[:lpDescription] = FFI::MemoryPointer.from_string(opts[
|
557
|
+
description[:lpDescription] = FFI::MemoryPointer.from_string(opts["description"])
|
554
558
|
|
555
559
|
bool = ChangeServiceConfig2(
|
556
560
|
handle_scs,
|
@@ -558,12 +562,12 @@ module Win32
|
|
558
562
|
description
|
559
563
|
)
|
560
564
|
|
561
|
-
FFI.raise_windows_error(
|
565
|
+
FFI.raise_windows_error("ChangeServiceConfig2") unless bool
|
562
566
|
end
|
563
567
|
|
564
|
-
if opts[
|
568
|
+
if opts["delayed_start"]
|
565
569
|
delayed_start = SERVICE_DELAYED_AUTO_START_INFO.new
|
566
|
-
delayed_start[:fDelayedAutostart] = opts[
|
570
|
+
delayed_start[:fDelayedAutostart] = opts["delayed_start"]
|
567
571
|
|
568
572
|
bool = ChangeServiceConfig2(
|
569
573
|
handle_scs,
|
@@ -571,12 +575,11 @@ module Win32
|
|
571
575
|
delayed_start
|
572
576
|
)
|
573
577
|
|
574
|
-
FFI.raise_windows_error(
|
578
|
+
FFI.raise_windows_error("ChangeServiceConfig2") unless bool
|
575
579
|
end
|
576
580
|
|
577
|
-
if opts[
|
578
|
-
|
579
|
-
then
|
581
|
+
if opts["failure_reset_period"] || opts["failure_reboot_message"] ||
|
582
|
+
opts["failure_command"] || opts["failure_actions"]
|
580
583
|
configure_failure_actions(handle_scs, opts)
|
581
584
|
end
|
582
585
|
ensure
|
@@ -594,13 +597,13 @@ module Win32
|
|
594
597
|
#
|
595
598
|
# Service.exists?('W32Time') => true
|
596
599
|
#
|
597
|
-
def self.exists?(service, host=nil)
|
600
|
+
def self.exists?(service, host = nil)
|
598
601
|
bool = false
|
599
602
|
|
600
603
|
begin
|
601
604
|
handle_scm = OpenSCManager(host, nil, SC_MANAGER_ENUMERATE_SERVICE)
|
602
605
|
|
603
|
-
FFI.raise_windows_error(
|
606
|
+
FFI.raise_windows_error("OpenSCManager") if handle_scm == 0
|
604
607
|
|
605
608
|
handle_scs = OpenService(handle_scm, service, SERVICE_QUERY_STATUS)
|
606
609
|
bool = true if handle_scs > 0
|
@@ -624,13 +627,13 @@ module Win32
|
|
624
627
|
#
|
625
628
|
# Service.get_display_name('W32Time') => 'Windows Time'
|
626
629
|
#
|
627
|
-
def self.get_display_name(service, host=nil)
|
630
|
+
def self.get_display_name(service, host = nil)
|
628
631
|
handle_scm = OpenSCManager(host, nil, SC_MANAGER_CONNECT)
|
629
632
|
|
630
|
-
FFI.raise_windows_error(
|
633
|
+
FFI.raise_windows_error("OpenSCManager") if handle_scm == 0
|
631
634
|
|
632
635
|
display_name = FFI::MemoryPointer.new(260)
|
633
|
-
display_size
|
636
|
+
display_size = FFI::MemoryPointer.new(:ulong)
|
634
637
|
display_size.write_ulong(display_name.size)
|
635
638
|
|
636
639
|
begin
|
@@ -641,8 +644,7 @@ module Win32
|
|
641
644
|
display_size
|
642
645
|
)
|
643
646
|
|
644
|
-
|
645
|
-
FFI.raise_windows_error('OpenSCManager') unless bool
|
647
|
+
FFI.raise_windows_error("OpenSCManager") unless bool
|
646
648
|
ensure
|
647
649
|
close_service_handle(handle_scm)
|
648
650
|
end
|
@@ -662,10 +664,10 @@ module Win32
|
|
662
664
|
#
|
663
665
|
# Service.get_service_name('Windows Time') => 'W32Time'
|
664
666
|
#
|
665
|
-
def self.get_service_name(display_name, host=nil)
|
667
|
+
def self.get_service_name(display_name, host = nil)
|
666
668
|
handle_scm = OpenSCManager(host, nil, SC_MANAGER_CONNECT)
|
667
669
|
|
668
|
-
FFI.raise_windows_error(
|
670
|
+
FFI.raise_windows_error("OpenSCManager") if handle_scm == 0
|
669
671
|
|
670
672
|
service_name = FFI::MemoryPointer.new(260)
|
671
673
|
service_size = FFI::MemoryPointer.new(:ulong)
|
@@ -679,7 +681,7 @@ module Win32
|
|
679
681
|
service_size
|
680
682
|
)
|
681
683
|
|
682
|
-
FFI.raise_windows_error(
|
684
|
+
FFI.raise_windows_error("GetServiceKeyName") unless bool
|
683
685
|
ensure
|
684
686
|
close_service_handle(handle_scm)
|
685
687
|
end
|
@@ -699,15 +701,15 @@ module Win32
|
|
699
701
|
# # Start 'SomeSvc' on host 'foo', passing 'hello' as an argument
|
700
702
|
# Service.start('SomeSvc', 'foo', 'hello') => self
|
701
703
|
#
|
702
|
-
def self.start(service, host=nil, *args)
|
704
|
+
def self.start(service, host = nil, *args)
|
703
705
|
handle_scm = OpenSCManager(host, nil, SC_MANAGER_CONNECT)
|
704
706
|
|
705
|
-
FFI.raise_windows_error(
|
707
|
+
FFI.raise_windows_error("OpenSCManager") if handle_scm == 0
|
706
708
|
|
707
709
|
begin
|
708
710
|
handle_scs = OpenService(handle_scm, service, SERVICE_START)
|
709
711
|
|
710
|
-
FFI.raise_windows_error(
|
712
|
+
FFI.raise_windows_error("OpenService") if handle_scs == 0
|
711
713
|
|
712
714
|
num_args = 0
|
713
715
|
|
@@ -717,7 +719,7 @@ module Win32
|
|
717
719
|
str_ptrs = []
|
718
720
|
num_args = args.size
|
719
721
|
|
720
|
-
args.each{ |string|
|
722
|
+
args.each { |string|
|
721
723
|
str_ptrs << FFI::MemoryPointer.from_string(string)
|
722
724
|
}
|
723
725
|
|
@@ -725,13 +727,13 @@ module Win32
|
|
725
727
|
|
726
728
|
vector = FFI::MemoryPointer.new(:pointer, str_ptrs.size)
|
727
729
|
|
728
|
-
str_ptrs.each_with_index{ |p, i|
|
730
|
+
str_ptrs.each_with_index { |p, i|
|
729
731
|
vector[i].put_pointer(0, p)
|
730
732
|
}
|
731
733
|
end
|
732
734
|
|
733
735
|
unless StartService(handle_scs, num_args, vector)
|
734
|
-
FFI.raise_windows_error(
|
736
|
+
FFI.raise_windows_error("StartService")
|
735
737
|
end
|
736
738
|
|
737
739
|
ensure
|
@@ -752,7 +754,7 @@ module Win32
|
|
752
754
|
#
|
753
755
|
# Service.stop('W32Time') => self
|
754
756
|
#
|
755
|
-
def self.stop(service, host=nil)
|
757
|
+
def self.stop(service, host = nil)
|
756
758
|
service_signal = SERVICE_STOP
|
757
759
|
control_signal = SERVICE_CONTROL_STOP
|
758
760
|
send_signal(service, host, service_signal, control_signal)
|
@@ -773,7 +775,7 @@ module Win32
|
|
773
775
|
#
|
774
776
|
# Service.pause('Schedule') => self
|
775
777
|
#
|
776
|
-
def self.pause(service, host=nil)
|
778
|
+
def self.pause(service, host = nil)
|
777
779
|
service_signal = SERVICE_PAUSE_CONTINUE
|
778
780
|
control_signal = SERVICE_CONTROL_PAUSE
|
779
781
|
send_signal(service, host, service_signal, control_signal)
|
@@ -790,7 +792,7 @@ module Win32
|
|
790
792
|
#
|
791
793
|
# Service.resume('Schedule') => self
|
792
794
|
#
|
793
|
-
def self.resume(service, host=nil)
|
795
|
+
def self.resume(service, host = nil)
|
794
796
|
service_signal = SERVICE_PAUSE_CONTINUE
|
795
797
|
control_signal = SERVICE_CONTROL_CONTINUE
|
796
798
|
send_signal(service, host, service_signal, control_signal)
|
@@ -810,18 +812,18 @@ module Win32
|
|
810
812
|
#
|
811
813
|
# Service.delete('SomeService') => self
|
812
814
|
#
|
813
|
-
def self.delete(service, host=nil)
|
815
|
+
def self.delete(service, host = nil)
|
814
816
|
handle_scm = OpenSCManager(host, nil, SC_MANAGER_CREATE_SERVICE)
|
815
817
|
|
816
|
-
FFI.raise_windows_error(
|
818
|
+
FFI.raise_windows_error("OpenSCManager") if handle_scm == 0
|
817
819
|
|
818
820
|
begin
|
819
821
|
handle_scs = OpenService(handle_scm, service, DELETE)
|
820
822
|
|
821
|
-
FFI.raise_windows_error(
|
823
|
+
FFI.raise_windows_error("OpenService") if handle_scs == 0
|
822
824
|
|
823
825
|
unless DeleteService(handle_scs)
|
824
|
-
FFI.raise_windows_error(
|
826
|
+
FFI.raise_windows_error("DeleteService")
|
825
827
|
end
|
826
828
|
ensure
|
827
829
|
close_service_handle(handle_scs)
|
@@ -843,17 +845,17 @@ module Win32
|
|
843
845
|
# is returned with the Service.services method, but is faster for
|
844
846
|
# looking up basic information for a single service.
|
845
847
|
#
|
846
|
-
def self.config_info(service, host=nil)
|
848
|
+
def self.config_info(service, host = nil)
|
847
849
|
raise TypeError if host && !host.is_a?(String)
|
848
850
|
|
849
851
|
handle_scm = OpenSCManager(host, nil, SC_MANAGER_ENUMERATE_SERVICE)
|
850
852
|
|
851
|
-
FFI.raise_windows_error(
|
853
|
+
FFI.raise_windows_error("OpenSCManager") if handle_scm == 0
|
852
854
|
|
853
855
|
begin
|
854
856
|
handle_scs = OpenService(handle_scm, service, SERVICE_QUERY_CONFIG)
|
855
857
|
|
856
|
-
FFI.raise_windows_error(
|
858
|
+
FFI.raise_windows_error("OpenService") if handle_scs == 0
|
857
859
|
|
858
860
|
# First, get the buf size needed
|
859
861
|
bytes = FFI::MemoryPointer.new(:ulong)
|
@@ -861,7 +863,7 @@ module Win32
|
|
861
863
|
bool = QueryServiceConfig(handle_scs, nil, 0, bytes)
|
862
864
|
|
863
865
|
if !bool && FFI.errno != ERROR_INSUFFICIENT_BUFFER
|
864
|
-
FFI.raise_windows_error(
|
866
|
+
FFI.raise_windows_error("QueryServiceConfig")
|
865
867
|
end
|
866
868
|
|
867
869
|
buf = FFI::MemoryPointer.new(:char, bytes.read_ulong)
|
@@ -871,7 +873,7 @@ module Win32
|
|
871
873
|
|
872
874
|
struct = QUERY_SERVICE_CONFIG.new(buf) # cast the buffer
|
873
875
|
|
874
|
-
FFI.raise_windows_error(
|
876
|
+
FFI.raise_windows_error("QueryServiceConfig") unless bool
|
875
877
|
ensure
|
876
878
|
close_service_handle(handle_scs)
|
877
879
|
close_service_handle(handle_scm)
|
@@ -897,7 +899,7 @@ module Win32
|
|
897
899
|
#
|
898
900
|
# Service.status('W32Time') => <struct Struct::ServiceStatus ...>
|
899
901
|
#
|
900
|
-
def self.status(service, host=nil)
|
902
|
+
def self.status(service, host = nil)
|
901
903
|
status = SERVICE_STATUS_PROCESS.new
|
902
904
|
bytes = FFI::MemoryPointer.new(:ulong)
|
903
905
|
|
@@ -911,7 +913,7 @@ module Win32
|
|
911
913
|
bytes
|
912
914
|
)
|
913
915
|
|
914
|
-
FFI.raise_windows_error(
|
916
|
+
FFI.raise_windows_error("QueryServiceStatusEx") unless bool
|
915
917
|
end
|
916
918
|
end
|
917
919
|
|
@@ -957,7 +959,7 @@ module Win32
|
|
957
959
|
# # Enumerate over all 'network' services locally
|
958
960
|
# Service.services(nil, 'network'){ |service| p service }
|
959
961
|
#
|
960
|
-
def self.services(host=nil, group=nil)
|
962
|
+
def self.services(host = nil, group = nil)
|
961
963
|
unless host.nil?
|
962
964
|
raise TypeError unless host.is_a?(String) # Avoid strange errors
|
963
965
|
end
|
@@ -968,7 +970,7 @@ module Win32
|
|
968
970
|
|
969
971
|
handle_scm = OpenSCManager(host, nil, SC_MANAGER_ENUMERATE_SERVICE)
|
970
972
|
|
971
|
-
FFI.raise_windows_error(
|
973
|
+
FFI.raise_windows_error("OpenSCManager") if handle_scm == 0
|
972
974
|
|
973
975
|
bytes_needed = FFI::MemoryPointer.new(:ulong)
|
974
976
|
services_returned = FFI::MemoryPointer.new(:ulong)
|
@@ -992,7 +994,7 @@ module Win32
|
|
992
994
|
if !bool && FFI.errno == ERROR_MORE_DATA
|
993
995
|
service_buf = FFI::MemoryPointer.new(:char, bytes_needed.read_ulong)
|
994
996
|
else
|
995
|
-
FFI.raise_windows_error(
|
997
|
+
FFI.raise_windows_error("EnumServiceStatusEx")
|
996
998
|
end
|
997
999
|
|
998
1000
|
bool = EnumServicesStatusEx(
|
@@ -1008,13 +1010,13 @@ module Win32
|
|
1008
1010
|
group
|
1009
1011
|
)
|
1010
1012
|
|
1011
|
-
FFI.raise_windows_error(
|
1013
|
+
FFI.raise_windows_error("EnumServiceStatusEx") unless bool
|
1012
1014
|
|
1013
1015
|
num_services = services_returned.read_ulong
|
1014
1016
|
|
1015
1017
|
services_array = [] unless block_given?
|
1016
1018
|
|
1017
|
-
1.upto(num_services){ |num|
|
1019
|
+
1.upto(num_services) { |num|
|
1018
1020
|
# Cast the buffer
|
1019
1021
|
struct = ENUM_SERVICE_STATUS_PROCESS.new(service_buf)
|
1020
1022
|
|
@@ -1040,7 +1042,7 @@ module Win32
|
|
1040
1042
|
SERVICE_QUERY_CONFIG
|
1041
1043
|
)
|
1042
1044
|
|
1043
|
-
FFI.raise_windows_error(
|
1045
|
+
FFI.raise_windows_error("OpenService") if handle_scs == 0
|
1044
1046
|
|
1045
1047
|
config_struct = get_config_info(handle_scs)
|
1046
1048
|
|
@@ -1059,14 +1061,14 @@ module Win32
|
|
1059
1061
|
buf = get_config2_info(handle_scs, SERVICE_CONFIG_DESCRIPTION)
|
1060
1062
|
|
1061
1063
|
if buf.is_a?(Numeric) || buf.read_pointer.null?
|
1062
|
-
description =
|
1064
|
+
description = ""
|
1063
1065
|
else
|
1064
1066
|
description = buf.read_pointer.read_string
|
1065
1067
|
end
|
1066
1068
|
rescue
|
1067
1069
|
# While being annoying, not being able to get a description is not exceptional
|
1068
1070
|
warn "WARNING: Failed to retrieve description for the #{service_name} service."
|
1069
|
-
description =
|
1071
|
+
description = ""
|
1070
1072
|
end
|
1071
1073
|
|
1072
1074
|
delayed_start = delayed_start(service_name)
|
@@ -1111,11 +1113,11 @@ module Win32
|
|
1111
1113
|
|
1112
1114
|
actions = {}
|
1113
1115
|
|
1114
|
-
num_actions.times{ |n|
|
1116
|
+
num_actions.times { |n|
|
1115
1117
|
sc_action = SC_ACTION.new(action_ptr[n * SC_ACTION.size])
|
1116
1118
|
delay = sc_action[:Delay]
|
1117
1119
|
action_type = get_action_type(sc_action[:Type])
|
1118
|
-
actions[n+1] = {:
|
1120
|
+
actions[n + 1] = { action_type: action_type, delay: delay }
|
1119
1121
|
}
|
1120
1122
|
end
|
1121
1123
|
else
|
@@ -1165,9 +1167,9 @@ module Win32
|
|
1165
1167
|
)
|
1166
1168
|
|
1167
1169
|
if block_given?
|
1168
|
-
|
1170
|
+
yield struct
|
1169
1171
|
else
|
1170
|
-
|
1172
|
+
services_array << struct
|
1171
1173
|
end
|
1172
1174
|
|
1173
1175
|
service_buf += ENUM_SERVICE_STATUS_PROCESS.size
|
@@ -1197,7 +1199,7 @@ module Win32
|
|
1197
1199
|
def self.delayed_start(service, host = nil)
|
1198
1200
|
handle_scm = OpenSCManager(host, nil, SC_MANAGER_ENUMERATE_SERVICE)
|
1199
1201
|
|
1200
|
-
FFI.raise_windows_error(
|
1202
|
+
FFI.raise_windows_error("OpenSCManager") if handle_scm == 0
|
1201
1203
|
|
1202
1204
|
handle_scs = OpenService(
|
1203
1205
|
handle_scm,
|
@@ -1205,7 +1207,7 @@ module Win32
|
|
1205
1207
|
SERVICE_QUERY_CONFIG
|
1206
1208
|
)
|
1207
1209
|
|
1208
|
-
FFI.raise_windows_error(
|
1210
|
+
FFI.raise_windows_error("OpenService") if handle_scs == 0
|
1209
1211
|
|
1210
1212
|
delayed_start_buf = get_config2_info(handle_scs, SERVICE_CONFIG_DELAYED_AUTO_START_INFO)
|
1211
1213
|
if delayed_start_buf.is_a?(FFI::MemoryPointer)
|
@@ -1255,13 +1257,13 @@ module Win32
|
|
1255
1257
|
service_name,
|
1256
1258
|
desired_access
|
1257
1259
|
)
|
1258
|
-
|
1260
|
+
FFI.raise_windows_error("OpenService") if service_handle == 0
|
1259
1261
|
|
1260
|
-
|
1261
|
-
|
1262
|
-
|
1263
|
-
|
1264
|
-
|
1262
|
+
if block_given?
|
1263
|
+
yield service_handle
|
1264
|
+
else
|
1265
|
+
service_handle
|
1266
|
+
end
|
1265
1267
|
ensure
|
1266
1268
|
close_service_handle(service_handle) if block_given?
|
1267
1269
|
end
|
@@ -1288,7 +1290,7 @@ module Win32
|
|
1288
1290
|
#
|
1289
1291
|
def self.open_sc_manager(host = nil, desired_access = SC_MANAGER_CONNECT)
|
1290
1292
|
scm_handle = OpenSCManager(host, nil, desired_access)
|
1291
|
-
FFI.raise_windows_error(
|
1293
|
+
FFI.raise_windows_error("OpenSCManager") if scm_handle == 0
|
1292
1294
|
|
1293
1295
|
if block_given?
|
1294
1296
|
yield scm_handle
|
@@ -1299,12 +1301,10 @@ module Win32
|
|
1299
1301
|
close_service_handle(scm_handle) if block_given?
|
1300
1302
|
end
|
1301
1303
|
|
1302
|
-
private
|
1303
|
-
|
1304
1304
|
# Configures failure actions for a given service.
|
1305
1305
|
#
|
1306
1306
|
def self.configure_failure_actions(handle_scs, opts)
|
1307
|
-
if opts[
|
1307
|
+
if opts["failure_actions"]
|
1308
1308
|
token_handle = FFI::MemoryPointer.new(:ulong)
|
1309
1309
|
|
1310
1310
|
bool = OpenProcessToken(
|
@@ -1316,7 +1316,7 @@ module Win32
|
|
1316
1316
|
unless bool
|
1317
1317
|
error = FFI.errno
|
1318
1318
|
close_service_handle(handle_scs)
|
1319
|
-
raise SystemCallError.new(
|
1319
|
+
raise SystemCallError.new("OpenProcessToken", error)
|
1320
1320
|
end
|
1321
1321
|
|
1322
1322
|
token_handle = token_handle.read_ulong
|
@@ -1324,10 +1324,10 @@ module Win32
|
|
1324
1324
|
# Get the LUID for shutdown privilege.
|
1325
1325
|
luid = LUID.new
|
1326
1326
|
|
1327
|
-
unless LookupPrivilegeValue(
|
1327
|
+
unless LookupPrivilegeValue("", "SeShutdownPrivilege", luid)
|
1328
1328
|
error = FFI.errno
|
1329
1329
|
close_service_handle(handle_scs)
|
1330
|
-
raise SystemCallError.new(
|
1330
|
+
raise SystemCallError.new("LookupPrivilegeValue", error)
|
1331
1331
|
end
|
1332
1332
|
|
1333
1333
|
luid_and_attrs = LUID_AND_ATTRIBUTES.new
|
@@ -1351,35 +1351,35 @@ module Win32
|
|
1351
1351
|
unless bool
|
1352
1352
|
error = FFI.errno
|
1353
1353
|
close_service_handle(handle_scs)
|
1354
|
-
raise SystemCallError.new(
|
1354
|
+
raise SystemCallError.new("AdjustTokenPrivileges", error)
|
1355
1355
|
end
|
1356
1356
|
end
|
1357
1357
|
|
1358
1358
|
sfa = SERVICE_FAILURE_ACTIONS.new
|
1359
1359
|
|
1360
|
-
if opts[
|
1361
|
-
sfa[:dwResetPeriod] = opts[
|
1360
|
+
if opts["failure_reset_period"]
|
1361
|
+
sfa[:dwResetPeriod] = opts["failure_reset_period"]
|
1362
1362
|
end
|
1363
1363
|
|
1364
|
-
if opts[
|
1365
|
-
sfa[:lpRebootMsg] = FFI::MemoryPointer.from_string(opts[
|
1364
|
+
if opts["failure_reboot_message"]
|
1365
|
+
sfa[:lpRebootMsg] = FFI::MemoryPointer.from_string(opts["failure_reboot_message"])
|
1366
1366
|
end
|
1367
1367
|
|
1368
|
-
if opts[
|
1369
|
-
sfa[:lpCommand] = FFI::MemoryPointer.from_string(opts[
|
1368
|
+
if opts["failure_command"]
|
1369
|
+
sfa[:lpCommand] = FFI::MemoryPointer.from_string(opts["failure_command"])
|
1370
1370
|
end
|
1371
1371
|
|
1372
|
-
if opts[
|
1373
|
-
action_size = opts[
|
1372
|
+
if opts["failure_actions"]
|
1373
|
+
action_size = opts["failure_actions"].size
|
1374
1374
|
action_ptr = FFI::MemoryPointer.new(SC_ACTION, action_size)
|
1375
1375
|
|
1376
1376
|
actions = action_size.times.collect do |i|
|
1377
1377
|
SC_ACTION.new(action_ptr + i * SC_ACTION.size)
|
1378
1378
|
end
|
1379
1379
|
|
1380
|
-
opts[
|
1380
|
+
opts["failure_actions"].each_with_index { |action, i|
|
1381
1381
|
actions[i][:Type] = action
|
1382
|
-
actions[i][:Delay] = opts[
|
1382
|
+
actions[i][:Delay] = opts["failure_delay"]
|
1383
1383
|
}
|
1384
1384
|
|
1385
1385
|
sfa[:cActions] = action_size
|
@@ -1395,7 +1395,7 @@ module Win32
|
|
1395
1395
|
unless bool
|
1396
1396
|
error = FFI.errno
|
1397
1397
|
close_service_handle(handle_scs)
|
1398
|
-
raise SystemCallError.new(
|
1398
|
+
raise SystemCallError.new("ChangeServiceConfig2", error)
|
1399
1399
|
end
|
1400
1400
|
end
|
1401
1401
|
|
@@ -1404,15 +1404,15 @@ module Win32
|
|
1404
1404
|
def self.get_action_type(action_type)
|
1405
1405
|
case action_type
|
1406
1406
|
when SC_ACTION_NONE
|
1407
|
-
|
1407
|
+
"none"
|
1408
1408
|
when SC_ACTION_REBOOT
|
1409
|
-
|
1409
|
+
"reboot"
|
1410
1410
|
when SC_ACTION_RESTART
|
1411
|
-
|
1411
|
+
"restart"
|
1412
1412
|
when SC_ACTION_RUN_COMMAND
|
1413
|
-
|
1413
|
+
"command"
|
1414
1414
|
else
|
1415
|
-
|
1415
|
+
"unknown"
|
1416
1416
|
end
|
1417
1417
|
end
|
1418
1418
|
|
@@ -1434,7 +1434,7 @@ module Win32
|
|
1434
1434
|
else
|
1435
1435
|
error = FFI.errno
|
1436
1436
|
CloseServiceHandle(handle)
|
1437
|
-
FFI.raise_windows_error(
|
1437
|
+
FFI.raise_windows_error("QueryServiceConfig", error)
|
1438
1438
|
end
|
1439
1439
|
|
1440
1440
|
bytes_needed.clear
|
@@ -1448,7 +1448,7 @@ module Win32
|
|
1448
1448
|
bytes_needed
|
1449
1449
|
)
|
1450
1450
|
|
1451
|
-
FFI.raise_windows_error(
|
1451
|
+
FFI.raise_windows_error("QueryServiceConfig") unless bool
|
1452
1452
|
ensure
|
1453
1453
|
CloseServiceHandle(handle) unless bool
|
1454
1454
|
end
|
@@ -1476,7 +1476,7 @@ module Win32
|
|
1476
1476
|
return err_num
|
1477
1477
|
else
|
1478
1478
|
CloseServiceHandle(handle)
|
1479
|
-
FFI.raise_windows_error(
|
1479
|
+
FFI.raise_windows_error("QueryServiceConfig2", err_num)
|
1480
1480
|
end
|
1481
1481
|
|
1482
1482
|
bytes_needed.clear
|
@@ -1491,7 +1491,7 @@ module Win32
|
|
1491
1491
|
bytes_needed
|
1492
1492
|
)
|
1493
1493
|
|
1494
|
-
FFI.raise_windows_error(
|
1494
|
+
FFI.raise_windows_error("QueryServiceConfig2") unless bool
|
1495
1495
|
ensure
|
1496
1496
|
CloseServiceHandle(handle) unless bool
|
1497
1497
|
end
|
@@ -1504,13 +1504,13 @@ module Win32
|
|
1504
1504
|
def self.get_error_control(error_control)
|
1505
1505
|
case error_control
|
1506
1506
|
when SERVICE_ERROR_CRITICAL
|
1507
|
-
|
1507
|
+
"critical"
|
1508
1508
|
when SERVICE_ERROR_IGNORE
|
1509
|
-
|
1509
|
+
"ignore"
|
1510
1510
|
when SERVICE_ERROR_NORMAL
|
1511
|
-
|
1511
|
+
"normal"
|
1512
1512
|
when SERVICE_ERROR_SEVERE
|
1513
|
-
|
1513
|
+
"severe"
|
1514
1514
|
else
|
1515
1515
|
nil
|
1516
1516
|
end
|
@@ -1521,15 +1521,15 @@ module Win32
|
|
1521
1521
|
def self.get_start_type(start_type)
|
1522
1522
|
case start_type
|
1523
1523
|
when SERVICE_AUTO_START
|
1524
|
-
|
1524
|
+
"auto start"
|
1525
1525
|
when SERVICE_BOOT_START
|
1526
|
-
|
1526
|
+
"boot start"
|
1527
1527
|
when SERVICE_DEMAND_START
|
1528
|
-
|
1528
|
+
"demand start"
|
1529
1529
|
when SERVICE_DISABLED
|
1530
|
-
|
1530
|
+
"disabled"
|
1531
1531
|
when SERVICE_SYSTEM_START
|
1532
|
-
|
1532
|
+
"system start"
|
1533
1533
|
else
|
1534
1534
|
nil
|
1535
1535
|
end
|
@@ -1542,39 +1542,39 @@ module Win32
|
|
1542
1542
|
array = []
|
1543
1543
|
|
1544
1544
|
if controls & SERVICE_ACCEPT_NETBINDCHANGE > 0
|
1545
|
-
array <<
|
1545
|
+
array << "netbind change"
|
1546
1546
|
end
|
1547
1547
|
|
1548
1548
|
if controls & SERVICE_ACCEPT_PARAMCHANGE > 0
|
1549
|
-
array <<
|
1549
|
+
array << "param change"
|
1550
1550
|
end
|
1551
1551
|
|
1552
1552
|
if controls & SERVICE_ACCEPT_PAUSE_CONTINUE > 0
|
1553
|
-
array <<
|
1553
|
+
array << "pause continue"
|
1554
1554
|
end
|
1555
1555
|
|
1556
1556
|
if controls & SERVICE_ACCEPT_SHUTDOWN > 0
|
1557
|
-
array <<
|
1557
|
+
array << "shutdown"
|
1558
1558
|
end
|
1559
1559
|
|
1560
1560
|
if controls & SERVICE_ACCEPT_PRESHUTDOWN > 0
|
1561
|
-
array <<
|
1561
|
+
array << "pre-shutdown"
|
1562
1562
|
end
|
1563
1563
|
|
1564
1564
|
if controls & SERVICE_ACCEPT_STOP > 0
|
1565
|
-
array <<
|
1565
|
+
array << "stop"
|
1566
1566
|
end
|
1567
1567
|
|
1568
1568
|
if controls & SERVICE_ACCEPT_HARDWAREPROFILECHANGE > 0
|
1569
|
-
array <<
|
1569
|
+
array << "hardware profile change"
|
1570
1570
|
end
|
1571
1571
|
|
1572
1572
|
if controls & SERVICE_ACCEPT_POWEREVENT > 0
|
1573
|
-
array <<
|
1573
|
+
array << "power event"
|
1574
1574
|
end
|
1575
1575
|
|
1576
1576
|
if controls & SERVICE_ACCEPT_SESSIONCHANGE > 0
|
1577
|
-
array <<
|
1577
|
+
array << "session change"
|
1578
1578
|
end
|
1579
1579
|
|
1580
1580
|
array
|
@@ -1585,19 +1585,19 @@ module Win32
|
|
1585
1585
|
def self.get_current_state(state)
|
1586
1586
|
case state
|
1587
1587
|
when SERVICE_CONTINUE_PENDING
|
1588
|
-
|
1588
|
+
"continue pending"
|
1589
1589
|
when SERVICE_PAUSE_PENDING
|
1590
|
-
|
1590
|
+
"pause pending"
|
1591
1591
|
when SERVICE_PAUSED
|
1592
|
-
|
1592
|
+
"paused"
|
1593
1593
|
when SERVICE_RUNNING
|
1594
|
-
|
1594
|
+
"running"
|
1595
1595
|
when SERVICE_START_PENDING
|
1596
|
-
|
1596
|
+
"start pending"
|
1597
1597
|
when SERVICE_STOP_PENDING
|
1598
|
-
|
1598
|
+
"stop pending"
|
1599
1599
|
when SERVICE_STOPPED
|
1600
|
-
|
1600
|
+
"stopped"
|
1601
1601
|
else
|
1602
1602
|
nil
|
1603
1603
|
end
|
@@ -1608,25 +1608,25 @@ module Win32
|
|
1608
1608
|
def self.get_service_type(service_type)
|
1609
1609
|
case service_type
|
1610
1610
|
when SERVICE_FILE_SYSTEM_DRIVER
|
1611
|
-
|
1611
|
+
"file system driver"
|
1612
1612
|
when SERVICE_KERNEL_DRIVER
|
1613
|
-
|
1613
|
+
"kernel driver"
|
1614
1614
|
when SERVICE_WIN32_OWN_PROCESS
|
1615
|
-
|
1615
|
+
"own process"
|
1616
1616
|
when SERVICE_WIN32_SHARE_PROCESS
|
1617
|
-
|
1617
|
+
"share process"
|
1618
1618
|
when SERVICE_RECOGNIZER_DRIVER
|
1619
|
-
|
1619
|
+
"recognizer driver"
|
1620
1620
|
when SERVICE_DRIVER
|
1621
|
-
|
1621
|
+
"driver"
|
1622
1622
|
when SERVICE_WIN32
|
1623
|
-
|
1623
|
+
"win32"
|
1624
1624
|
when SERVICE_TYPE_ALL
|
1625
|
-
|
1625
|
+
"all"
|
1626
1626
|
when SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_OWN_PROCESS
|
1627
|
-
|
1627
|
+
"own process, interactive"
|
1628
1628
|
when SERVICE_INTERACTIVE_PROCESS | SERVICE_WIN32_SHARE_PROCESS
|
1629
|
-
|
1629
|
+
"share process, interactive"
|
1630
1630
|
else
|
1631
1631
|
nil
|
1632
1632
|
end
|
@@ -1637,17 +1637,17 @@ module Win32
|
|
1637
1637
|
def self.send_signal(service, host, service_signal, control_signal)
|
1638
1638
|
handle_scm = OpenSCManager(host, nil, SC_MANAGER_CONNECT)
|
1639
1639
|
|
1640
|
-
FFI.raise_windows_error(
|
1640
|
+
FFI.raise_windows_error("OpenSCManager") if handle_scm == 0
|
1641
1641
|
|
1642
1642
|
begin
|
1643
1643
|
handle_scs = OpenService(handle_scm, service, service_signal)
|
1644
1644
|
|
1645
|
-
FFI.raise_windows_error(
|
1645
|
+
FFI.raise_windows_error("OpenService") if handle_scs == 0
|
1646
1646
|
|
1647
1647
|
status = SERVICE_STATUS.new
|
1648
1648
|
|
1649
1649
|
unless ControlService(handle_scs, control_signal, status)
|
1650
|
-
FFI.raise_windows_error(
|
1650
|
+
FFI.raise_windows_error("ControlService")
|
1651
1651
|
end
|
1652
1652
|
ensure
|
1653
1653
|
close_service_handle(handle_scs)
|