win32-service 2.2.0 → 2.3.2
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/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)
|