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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: e27f59203c2e9c16dea5335981498b12a350f3b627e9991145fc51cccc7e1d8f
4
- data.tar.gz: d692ad6fbbc89954be51465f0a5af4906554e1dcc72d4c30748e71156a07ad8c
3
+ metadata.gz: ef70f0e8d16323dd531f4a6558b910121fa02ed62a432e5e82a70bfa19736805
4
+ data.tar.gz: f1128b7daa3ec6d64cb374c554c291b222f37dd10079865f5be6ae930287c0bc
5
5
  SHA512:
6
- metadata.gz: 973eb074ad890a30ec58ff8befacd7a3c0b160dfe7f36c49d5a5ed6f70634cbf38909747e19609ccb085056c8070065029a0fed33440a8eeb0c339c036c1c0ae
7
- data.tar.gz: 79e03a845dbad972be71566e1208bdb56bab7a6ba9673301030b819bd1bc3a40b78ab45142bef2161da2e1ea9075f205d9f92d94e0442bac1efba60b2d625234
6
+ metadata.gz: a9bb4ac05263a141d2a4fc1030e16b9d6df66af501917f3403fa082412055bd6c1118404e06b35531845bcbaa55ecd3f89e8677ec57c422b40c7cfa61d3a8e3d
7
+ data.tar.gz: be2e0f6108dd0093e582659ef201d78266cbcaa428e08eac3624146695bdc46337edbb3b5823179f3f5c541b881bb0e3d95c64fe1ef92ef636f1521a72053ef7
@@ -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 = '0.8.10'.freeze
19
+ VERSION = Win32::Service::VERSION
19
20
 
20
21
  private
21
22
 
@@ -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
- Service.configure_failure_actions(handle_scs, opts)
400
+ self.class.configure_failure_actions(handle_scs, opts)
401
401
  end
402
402
  ensure
403
- CloseServiceHandle(handle_scs) if handle_scs && handle_scs > 0
404
- CloseServiceHandle(handle_scm) if handle_scm && handle_scm > 0
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
- CloseServiceHandle(handle_scs) if handle_scs && handle_scs > 0
584
- CloseServiceHandle(handle_scm) if handle_scm && handle_scm > 0
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
- CloseServiceHandle(handle_scm) if handle_scm && handle_scm > 0
609
- CloseServiceHandle(handle_scs) if handle_scs && handle_scs > 0
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
- CloseServiceHandle(handle_scm)
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
- CloseServiceHandle(handle_scm)
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
- CloseServiceHandle(handle_scs) if handle_scs && handle_scs > 0
739
- CloseServiceHandle(handle_scm)
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
- CloseServiceHandle(handle_scs) if handle_scs && handle_scs > 0
828
- CloseServiceHandle(handle_scm)
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
- CloseServiceHandle(handle_scs) if handle_scs && handle_scs > 0
877
- CloseServiceHandle(handle_scm)
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
- handle_scm = OpenSCManager(host, nil, SC_MANAGER_ENUMERATE_SERVICE)
902
-
903
- FFI.raise_windows_error('OpenSCManager') if handle_scm == 0
904
-
905
- begin
906
- handle_scs = OpenService(
907
- handle_scm,
908
- service,
909
- SERVICE_QUERY_STATUS
910
- )
911
-
912
- FFI.raise_windows_error('OpenService') if handle_scs == 0
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
- FFI.raise_windows_error('QueryServiceStatusEx') unless bool
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
- begin
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
- CloseServiceHandle(handle_scs) if handle_scs > 0
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
- CloseServiceHandle(handle_scm)
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
- CloseServiceHandle(handle_scs)
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
- CloseServiceHandle(handle_scs)
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
- CloseServiceHandle(handle_scs)
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
- CloseServiceHandle(handle_scs)
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
- CloseServiceHandle(handle_scs) if handle_scs && handle_scs > 0
1563
- CloseServiceHandle(handle_scm) if handle_scm && handle_scm > 0
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 ServiceFunctions
@@ -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,
@@ -1,6 +1,6 @@
1
1
  module Win32
2
2
  class Service
3
- VERSION = "1.0.1"
3
+ VERSION = "2.2.0"
4
4
  MAJOR, MINOR, TINY = VERSION.split(".")
5
5
  end
6
6
  end