win32-service 1.0.1 → 2.2.0
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 +2 -1
- data/lib/win32/service.rb +176 -85
- data/lib/win32/windows/functions.rb +1 -1
- data/lib/win32/windows/structs.rb +1 -15
- data/lib/win32/windows/version.rb +1 -1
- metadata +50 -39
- data/CHANGELOG.md +0 -347
- data/Gemfile +0 -5
- data/MANIFEST +0 -24
- data/README.md +0 -75
- data/Rakefile +0 -83
- data/VERSION +0 -1
- data/appveyor.yml +0 -48
- data/doc/daemon.txt +0 -157
- data/doc/service.txt +0 -363
- data/examples/demo_daemon.rb +0 -96
- data/examples/demo_daemon_ctl.rb +0 -123
- data/examples/demo_services.rb +0 -30
- data/test/test_win32_daemon.rb +0 -58
- data/test/test_win32_service.rb +0 -468
- data/test/test_win32_service_configure.rb +0 -110
- data/test/test_win32_service_create.rb +0 -153
- data/test/test_win32_service_info.rb +0 -189
- data/test/test_win32_service_status.rb +0 -110
- data/win32-service.gemspec +0 -41
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: ef70f0e8d16323dd531f4a6558b910121fa02ed62a432e5e82a70bfa19736805
|
4
|
+
data.tar.gz: f1128b7daa3ec6d64cb374c554c291b222f37dd10079865f5be6ae930287c0bc
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: a9bb4ac05263a141d2a4fc1030e16b9d6df66af501917f3403fa082412055bd6c1118404e06b35531845bcbaa55ecd3f89e8677ec57c422b40c7cfa61d3a8e3d
|
7
|
+
data.tar.gz: be2e0f6108dd0093e582659ef201d78266cbcaa428e08eac3624146695bdc46337edbb3b5823179f3f5c541b881bb0e3d95c64fe1ef92ef636f1521a72053ef7
|
data/lib/win32/daemon.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
require_relative 'windows/constants'
|
2
2
|
require_relative 'windows/structs'
|
3
3
|
require_relative 'windows/functions'
|
4
|
+
require_relative 'windows/version'
|
4
5
|
|
5
6
|
# The Win32 module serves as a namespace only.
|
6
7
|
module Win32
|
@@ -15,7 +16,7 @@ module Win32
|
|
15
16
|
extend Windows::ServiceFunctions
|
16
17
|
|
17
18
|
# The version of this library
|
18
|
-
VERSION =
|
19
|
+
VERSION = Win32::Service::VERSION
|
19
20
|
|
20
21
|
private
|
21
22
|
|
data/lib/win32/service.rb
CHANGED
@@ -397,11 +397,11 @@ module Win32
|
|
397
397
|
if opts['failure_reset_period'] || opts['failure_reboot_message'] ||
|
398
398
|
opts['failure_command'] || opts['failure_actions']
|
399
399
|
then
|
400
|
-
|
400
|
+
self.class.configure_failure_actions(handle_scs, opts)
|
401
401
|
end
|
402
402
|
ensure
|
403
|
-
|
404
|
-
|
403
|
+
self.class.close_service_handle(handle_scs)
|
404
|
+
self.class.close_service_handle(handle_scm)
|
405
405
|
end
|
406
406
|
|
407
407
|
self
|
@@ -580,8 +580,8 @@ module Win32
|
|
580
580
|
configure_failure_actions(handle_scs, opts)
|
581
581
|
end
|
582
582
|
ensure
|
583
|
-
|
584
|
-
|
583
|
+
close_service_handle(handle_scs)
|
584
|
+
close_service_handle(handle_scm)
|
585
585
|
end
|
586
586
|
|
587
587
|
self
|
@@ -605,8 +605,8 @@ module Win32
|
|
605
605
|
handle_scs = OpenService(handle_scm, service, SERVICE_QUERY_STATUS)
|
606
606
|
bool = true if handle_scs > 0
|
607
607
|
ensure
|
608
|
-
|
609
|
-
|
608
|
+
close_service_handle(handle_scm)
|
609
|
+
close_service_handle(handle_scs)
|
610
610
|
end
|
611
611
|
|
612
612
|
bool
|
@@ -644,7 +644,7 @@ module Win32
|
|
644
644
|
|
645
645
|
FFI.raise_windows_error('OpenSCManager') unless bool
|
646
646
|
ensure
|
647
|
-
|
647
|
+
close_service_handle(handle_scm)
|
648
648
|
end
|
649
649
|
|
650
650
|
display_name.read_string
|
@@ -681,7 +681,7 @@ module Win32
|
|
681
681
|
|
682
682
|
FFI.raise_windows_error('GetServiceKeyName') unless bool
|
683
683
|
ensure
|
684
|
-
|
684
|
+
close_service_handle(handle_scm)
|
685
685
|
end
|
686
686
|
|
687
687
|
service_name.read_string
|
@@ -735,8 +735,8 @@ module Win32
|
|
735
735
|
end
|
736
736
|
|
737
737
|
ensure
|
738
|
-
|
739
|
-
|
738
|
+
close_service_handle(handle_scs)
|
739
|
+
close_service_handle(handle_scm)
|
740
740
|
end
|
741
741
|
|
742
742
|
self
|
@@ -824,8 +824,8 @@ module Win32
|
|
824
824
|
FFI.raise_windows_error('DeleteService')
|
825
825
|
end
|
826
826
|
ensure
|
827
|
-
|
828
|
-
|
827
|
+
close_service_handle(handle_scs)
|
828
|
+
close_service_handle(handle_scm)
|
829
829
|
end
|
830
830
|
|
831
831
|
self
|
@@ -873,8 +873,8 @@ module Win32
|
|
873
873
|
|
874
874
|
FFI.raise_windows_error('QueryServiceConfig') unless bool
|
875
875
|
ensure
|
876
|
-
|
877
|
-
|
876
|
+
close_service_handle(handle_scs)
|
877
|
+
close_service_handle(handle_scm)
|
878
878
|
end
|
879
879
|
|
880
880
|
ConfigStruct.new(
|
@@ -898,59 +898,41 @@ module Win32
|
|
898
898
|
# Service.status('W32Time') => <struct Struct::ServiceStatus ...>
|
899
899
|
#
|
900
900
|
def self.status(service, host=nil)
|
901
|
-
|
902
|
-
|
903
|
-
|
904
|
-
|
905
|
-
|
906
|
-
|
907
|
-
|
908
|
-
|
909
|
-
|
910
|
-
|
911
|
-
|
912
|
-
|
913
|
-
|
914
|
-
# SERVICE_STATUS_PROCESS struct
|
915
|
-
status = SERVICE_STATUS_PROCESS.new
|
916
|
-
bytes = FFI::MemoryPointer.new(:ulong)
|
917
|
-
|
918
|
-
bool = QueryServiceStatusEx(
|
919
|
-
handle_scs,
|
920
|
-
SC_STATUS_PROCESS_INFO,
|
921
|
-
status,
|
922
|
-
status.size,
|
923
|
-
bytes
|
924
|
-
)
|
901
|
+
status = SERVICE_STATUS_PROCESS.new
|
902
|
+
bytes = FFI::MemoryPointer.new(:ulong)
|
903
|
+
|
904
|
+
open_sc_manager(host) do |scm_handle|
|
905
|
+
open_service(scm_handle, service, SERVICE_QUERY_STATUS) do |service_handle|
|
906
|
+
bool = QueryServiceStatusEx(
|
907
|
+
service_handle,
|
908
|
+
SC_STATUS_PROCESS_INFO,
|
909
|
+
status,
|
910
|
+
status.size,
|
911
|
+
bytes
|
912
|
+
)
|
925
913
|
|
926
|
-
|
927
|
-
|
928
|
-
service_type = get_service_type(status[:dwServiceType])
|
929
|
-
current_state = get_current_state(status[:dwCurrentState])
|
930
|
-
controls = get_controls_accepted(status[:dwControlsAccepted])
|
931
|
-
interactive = status[:dwServiceType] & SERVICE_INTERACTIVE_PROCESS > 0
|
932
|
-
|
933
|
-
# Note that the pid and service flags will always return 0 if you're
|
934
|
-
# on Windows NT 4 or using a version of Ruby compiled with VC++ 6
|
935
|
-
# or earlier.
|
936
|
-
#
|
937
|
-
status_struct = StatusStruct.new(
|
938
|
-
service_type,
|
939
|
-
current_state,
|
940
|
-
controls,
|
941
|
-
status[:dwWin32ExitCode],
|
942
|
-
status[:dwServiceSpecificExitCode],
|
943
|
-
status[:dwCheckPoint],
|
944
|
-
status[:dwWaitHint],
|
945
|
-
interactive,
|
946
|
-
status[:dwProcessId],
|
947
|
-
status[:dwServiceFlags]
|
948
|
-
)
|
949
|
-
ensure
|
950
|
-
CloseServiceHandle(handle_scs) if handle_scs && handle_scs > 0
|
951
|
-
CloseServiceHandle(handle_scm)
|
914
|
+
FFI.raise_windows_error('QueryServiceStatusEx') unless bool
|
915
|
+
end
|
952
916
|
end
|
953
917
|
|
918
|
+
service_type = get_service_type(status[:dwServiceType])
|
919
|
+
current_state = get_current_state(status[:dwCurrentState])
|
920
|
+
controls = get_controls_accepted(status[:dwControlsAccepted])
|
921
|
+
interactive = status[:dwServiceType] & SERVICE_INTERACTIVE_PROCESS > 0
|
922
|
+
|
923
|
+
status_struct = StatusStruct.new(
|
924
|
+
service_type,
|
925
|
+
current_state,
|
926
|
+
controls,
|
927
|
+
status[:dwWin32ExitCode],
|
928
|
+
status[:dwServiceSpecificExitCode],
|
929
|
+
status[:dwCheckPoint],
|
930
|
+
status[:dwWaitHint],
|
931
|
+
interactive,
|
932
|
+
status[:dwProcessId],
|
933
|
+
status[:dwServiceFlags]
|
934
|
+
)
|
935
|
+
|
954
936
|
status_struct
|
955
937
|
end
|
956
938
|
|
@@ -1087,18 +1069,7 @@ module Win32
|
|
1087
1069
|
description = ''
|
1088
1070
|
end
|
1089
1071
|
|
1090
|
-
|
1091
|
-
delayed_start_buf = get_config2_info(handle_scs, SERVICE_CONFIG_DELAYED_AUTO_START_INFO)
|
1092
|
-
if delayed_start_buf.is_a?(FFI::MemoryPointer)
|
1093
|
-
delayed_start_info = SERVICE_DELAYED_AUTO_START_INFO.new(delayed_start_buf)
|
1094
|
-
delayed_start = delayed_start_info[:fDelayedAutostart]
|
1095
|
-
else
|
1096
|
-
delayed_start = false
|
1097
|
-
end
|
1098
|
-
rescue
|
1099
|
-
warn "WARNING: Unable to get delayed auto start information for the #{service_name} service"
|
1100
|
-
delayed_start = nil
|
1101
|
-
end
|
1072
|
+
delayed_start = delayed_start(service_name)
|
1102
1073
|
else
|
1103
1074
|
warn "WARNING: The registry entry for the #{service_name} service could not be found"
|
1104
1075
|
|
@@ -1161,7 +1132,7 @@ module Win32
|
|
1161
1132
|
actions = nil
|
1162
1133
|
end
|
1163
1134
|
ensure
|
1164
|
-
|
1135
|
+
close_service_handle(handle_scs)
|
1165
1136
|
end
|
1166
1137
|
|
1167
1138
|
struct = ServiceStruct.new(
|
@@ -1202,12 +1173,132 @@ module Win32
|
|
1202
1173
|
service_buf += ENUM_SERVICE_STATUS_PROCESS.size
|
1203
1174
|
}
|
1204
1175
|
ensure
|
1205
|
-
|
1176
|
+
close_service_handle(handle_scm)
|
1206
1177
|
end
|
1207
1178
|
|
1208
1179
|
block_given? ? nil : services_array
|
1209
1180
|
end
|
1210
1181
|
|
1182
|
+
#
|
1183
|
+
# Attempts to get the delayed_start attribute for the named +service+ on +host+,
|
1184
|
+
# or the local machine if no host is provided.
|
1185
|
+
#
|
1186
|
+
# @example Get 'SomeSvc' delayed start on the local machine
|
1187
|
+
# Service.delayed_start('SomeSvc') # => 1
|
1188
|
+
# @example Get 'SomeSvc' delayed start on host foo
|
1189
|
+
# Service.delayed_start('SomeSvc', 'foo') # => 1
|
1190
|
+
#
|
1191
|
+
# @param service [String] Service name (e.g. `"Dhcp"`)
|
1192
|
+
# @param host [String] Host of service (e.g. `"mymachine"`)
|
1193
|
+
# @return [Integer, false, nil] Returns `1` when delayed start is enabled
|
1194
|
+
# and `0` when it is not enabled. Returns nil or false when there is
|
1195
|
+
# a problem of some kind.
|
1196
|
+
#
|
1197
|
+
def self.delayed_start(service, host = nil)
|
1198
|
+
handle_scm = OpenSCManager(host, nil, SC_MANAGER_ENUMERATE_SERVICE)
|
1199
|
+
|
1200
|
+
FFI.raise_windows_error('OpenSCManager') if handle_scm == 0
|
1201
|
+
|
1202
|
+
handle_scs = OpenService(
|
1203
|
+
handle_scm,
|
1204
|
+
service,
|
1205
|
+
SERVICE_QUERY_CONFIG
|
1206
|
+
)
|
1207
|
+
|
1208
|
+
FFI.raise_windows_error('OpenService') if handle_scs == 0
|
1209
|
+
|
1210
|
+
delayed_start_buf = get_config2_info(handle_scs, SERVICE_CONFIG_DELAYED_AUTO_START_INFO)
|
1211
|
+
if delayed_start_buf.is_a?(FFI::MemoryPointer)
|
1212
|
+
delayed_start_info = SERVICE_DELAYED_AUTO_START_INFO.new(delayed_start_buf)
|
1213
|
+
delayed_start = delayed_start_info[:fDelayedAutostart]
|
1214
|
+
else
|
1215
|
+
delayed_start = false
|
1216
|
+
end
|
1217
|
+
rescue SystemCallError
|
1218
|
+
delayed_start = nil
|
1219
|
+
ensure
|
1220
|
+
close_service_handle(handle_scs)
|
1221
|
+
close_service_handle(handle_scm)
|
1222
|
+
end
|
1223
|
+
|
1224
|
+
def self.close_service_handle(handle)
|
1225
|
+
case handle
|
1226
|
+
when NilClass
|
1227
|
+
false
|
1228
|
+
when Integer
|
1229
|
+
handle > 0 ? CloseServiceHandle(handle) : false
|
1230
|
+
else
|
1231
|
+
raise ArgumentError, "You must pass a valid handle to ::close_service_handle"
|
1232
|
+
end
|
1233
|
+
end
|
1234
|
+
|
1235
|
+
#
|
1236
|
+
# Opens an existing service.
|
1237
|
+
#
|
1238
|
+
# @example
|
1239
|
+
# open_sc_manager do |scm_handle|
|
1240
|
+
# open_service(scm_handle, 'Dhcp', SERVICE_ALL_ACCESS) do |service_handle|
|
1241
|
+
# p service_handle
|
1242
|
+
# end
|
1243
|
+
# end
|
1244
|
+
#
|
1245
|
+
# @param scm_handle [Integer] pointer to Service Control Manager
|
1246
|
+
# @param service_name [String] Name of the service
|
1247
|
+
# @param desired_access [Integer] The access to the service. For a list of
|
1248
|
+
# access rights, see `Windows::ServiceConstants`.
|
1249
|
+
#
|
1250
|
+
# @see Windows::ServiceConstants
|
1251
|
+
#
|
1252
|
+
def self.open_service(scm_handle, service_name, desired_access)
|
1253
|
+
service_handle = OpenService(
|
1254
|
+
scm_handle,
|
1255
|
+
service_name,
|
1256
|
+
desired_access
|
1257
|
+
)
|
1258
|
+
FFI.raise_windows_error('OpenService') if service_handle == 0
|
1259
|
+
|
1260
|
+
if block_given?
|
1261
|
+
yield service_handle
|
1262
|
+
else
|
1263
|
+
service_handle
|
1264
|
+
end
|
1265
|
+
ensure
|
1266
|
+
close_service_handle(service_handle) if block_given?
|
1267
|
+
end
|
1268
|
+
|
1269
|
+
#
|
1270
|
+
# Establishes a connection to the service control manager on the specified
|
1271
|
+
# host and opens the SERVICES_ACTIVE_DATABASE service control manager
|
1272
|
+
# database.
|
1273
|
+
#
|
1274
|
+
# @example
|
1275
|
+
# open_sc_manager(nil, SC_MANAGER_ENUMERATE_SERVICE) do |scm_handle|
|
1276
|
+
# p scm_handle
|
1277
|
+
# end
|
1278
|
+
#
|
1279
|
+
# @param host [String] Name of host you want to connect to. If `nil` it
|
1280
|
+
# will connect to the local host.
|
1281
|
+
# @param desired_access [Integer] The access to the service control
|
1282
|
+
# manager.
|
1283
|
+
# @return [Integer] If the function succeeds, the return value is a handle
|
1284
|
+
# to the specified service control manager database. If the function
|
1285
|
+
# fails, the return value is 0.
|
1286
|
+
#
|
1287
|
+
# @see Windows::ServiceConstants
|
1288
|
+
#
|
1289
|
+
def self.open_sc_manager(host = nil, desired_access = SC_MANAGER_CONNECT)
|
1290
|
+
scm_handle = OpenSCManager(host, nil, desired_access)
|
1291
|
+
FFI.raise_windows_error('OpenSCManager') if scm_handle == 0
|
1292
|
+
|
1293
|
+
if block_given?
|
1294
|
+
yield scm_handle
|
1295
|
+
else
|
1296
|
+
scm_handle
|
1297
|
+
end
|
1298
|
+
ensure
|
1299
|
+
close_service_handle(scm_handle) if block_given?
|
1300
|
+
end
|
1301
|
+
|
1211
1302
|
private
|
1212
1303
|
|
1213
1304
|
# Configures failure actions for a given service.
|
@@ -1224,7 +1315,7 @@ module Win32
|
|
1224
1315
|
|
1225
1316
|
unless bool
|
1226
1317
|
error = FFI.errno
|
1227
|
-
|
1318
|
+
close_service_handle(handle_scs)
|
1228
1319
|
raise SystemCallError.new('OpenProcessToken', error)
|
1229
1320
|
end
|
1230
1321
|
|
@@ -1235,7 +1326,7 @@ module Win32
|
|
1235
1326
|
|
1236
1327
|
unless LookupPrivilegeValue('', 'SeShutdownPrivilege', luid)
|
1237
1328
|
error = FFI.errno
|
1238
|
-
|
1329
|
+
close_service_handle(handle_scs)
|
1239
1330
|
raise SystemCallError.new('LookupPrivilegeValue', error)
|
1240
1331
|
end
|
1241
1332
|
|
@@ -1259,7 +1350,7 @@ module Win32
|
|
1259
1350
|
|
1260
1351
|
unless bool
|
1261
1352
|
error = FFI.errno
|
1262
|
-
|
1353
|
+
close_service_handle(handle_scs)
|
1263
1354
|
raise SystemCallError.new('AdjustTokenPrivileges', error)
|
1264
1355
|
end
|
1265
1356
|
end
|
@@ -1303,7 +1394,7 @@ module Win32
|
|
1303
1394
|
|
1304
1395
|
unless bool
|
1305
1396
|
error = FFI.errno
|
1306
|
-
|
1397
|
+
close_service_handle(handle_scs)
|
1307
1398
|
raise SystemCallError.new('ChangeServiceConfig2', error)
|
1308
1399
|
end
|
1309
1400
|
end
|
@@ -1559,8 +1650,8 @@ module Win32
|
|
1559
1650
|
FFI.raise_windows_error('ControlService')
|
1560
1651
|
end
|
1561
1652
|
ensure
|
1562
|
-
|
1563
|
-
|
1653
|
+
close_service_handle(handle_scs)
|
1654
|
+
close_service_handle(handle_scm)
|
1564
1655
|
end
|
1565
1656
|
|
1566
1657
|
status
|
@@ -1,4 +1,4 @@
|
|
1
|
-
require 'ffi'
|
1
|
+
require 'ffi' unless defined?(FFI)
|
2
2
|
|
3
3
|
module Windows
|
4
4
|
module ServiceStructs
|
@@ -68,20 +68,6 @@ module Windows
|
|
68
68
|
end
|
69
69
|
end
|
70
70
|
|
71
|
-
class SERVICE_STATUS_PROCESS < FFI::Struct
|
72
|
-
layout(
|
73
|
-
:dwServiceType, :dword,
|
74
|
-
:dwCurrentState, :dword,
|
75
|
-
:dwControlsAccepted, :dword,
|
76
|
-
:dwWin32ExitCode, :dword,
|
77
|
-
:dwServiceSpecificExitCode, :dword,
|
78
|
-
:dwCheckPoint, :dword,
|
79
|
-
:dwWaitHint, :dword,
|
80
|
-
:dwProcessId, :dword,
|
81
|
-
:dwServiceFlags, :dword
|
82
|
-
)
|
83
|
-
end
|
84
|
-
|
85
71
|
class ENUM_SERVICE_STATUS_PROCESS < FFI::Struct
|
86
72
|
layout(
|
87
73
|
:lpServiceName, :pointer,
|