bolt 0.23.0 → 0.24.0

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of bolt might be problematic. Click here for more details.

Files changed (192) hide show
  1. checksums.yaml +4 -4
  2. data/bolt-modules/boltlib/lib/puppet/functions/apply_prep.rb +5 -2
  3. data/bolt-modules/boltlib/lib/puppet/functions/puppetdb_query.rb +5 -1
  4. data/bolt-modules/boltlib/lib/puppet/functions/run_task.rb +5 -8
  5. data/lib/bolt/applicator.rb +11 -8
  6. data/lib/bolt/boltdir.rb +13 -5
  7. data/lib/bolt/catalog.rb +22 -47
  8. data/lib/bolt/config.rb +1 -26
  9. data/lib/bolt/executor.rb +1 -1
  10. data/lib/bolt/outputter.rb +0 -9
  11. data/lib/bolt/outputter/human.rb +29 -14
  12. data/lib/bolt/outputter/json.rb +12 -1
  13. data/lib/bolt/pal.rb +12 -10
  14. data/lib/bolt/target.rb +0 -6
  15. data/lib/bolt/task.rb +53 -10
  16. data/lib/bolt/transport/base.rb +1 -6
  17. data/lib/bolt/transport/local.rb +11 -13
  18. data/lib/bolt/transport/local/shell.rb +2 -2
  19. data/lib/bolt/transport/ssh.rb +16 -11
  20. data/lib/bolt/transport/winrm.rb +8 -11
  21. data/lib/bolt/version.rb +1 -1
  22. data/lib/bolt_ext/schemas/task.json +12 -5
  23. data/libexec/apply_catalog.rb +3 -1
  24. data/libexec/bolt_catalog +4 -0
  25. data/vendored/puppet/lib/puppet.rb +2 -1
  26. data/vendored/puppet/lib/puppet/application/agent.rb +2 -6
  27. data/vendored/puppet/lib/puppet/application/apply.rb +100 -60
  28. data/vendored/puppet/lib/puppet/application/cert.rb +26 -291
  29. data/vendored/puppet/lib/puppet/application/device.rb +0 -5
  30. data/vendored/puppet/lib/puppet/application/lookup.rb +1 -1
  31. data/vendored/puppet/lib/puppet/application/ssl.rb +133 -0
  32. data/vendored/puppet/lib/puppet/application_support.rb +1 -2
  33. data/vendored/puppet/lib/puppet/configurer.rb +34 -50
  34. data/vendored/puppet/lib/puppet/configurer/downloader.rb +1 -1
  35. data/vendored/puppet/lib/puppet/configurer/plugin_handler.rb +1 -1
  36. data/vendored/puppet/lib/puppet/daemon.rb +1 -1
  37. data/vendored/puppet/lib/puppet/defaults.rb +40 -117
  38. data/vendored/puppet/lib/puppet/face/epp.rb +2 -2
  39. data/vendored/puppet/lib/puppet/face/help.rb +21 -7
  40. data/vendored/puppet/lib/puppet/face/node/clean.rb +14 -10
  41. data/vendored/puppet/lib/puppet/feature/base.rb +7 -23
  42. data/vendored/puppet/lib/puppet/feature/eventlog.rb +1 -1
  43. data/vendored/puppet/lib/puppet/file_serving/base.rb +2 -2
  44. data/vendored/puppet/lib/puppet/file_serving/fileset.rb +1 -1
  45. data/vendored/puppet/lib/puppet/file_serving/metadata.rb +2 -2
  46. data/vendored/puppet/lib/puppet/functions.rb +133 -0
  47. data/vendored/puppet/lib/puppet/functions/eyaml_lookup_key.rb +4 -5
  48. data/vendored/puppet/lib/puppet/functions/filter.rb +7 -6
  49. data/vendored/puppet/lib/puppet/functions/new.rb +37 -53
  50. data/vendored/puppet/lib/puppet/functions/warning.rb +1 -1
  51. data/vendored/puppet/lib/puppet/functions/yaml_data.rb +4 -5
  52. data/vendored/puppet/lib/puppet/gettext/config.rb +1 -1
  53. data/vendored/puppet/lib/puppet/graph.rb +0 -2
  54. data/vendored/puppet/lib/puppet/indirector/catalog/json.rb +14 -3
  55. data/vendored/puppet/lib/puppet/indirector/catalog/yaml.rb +0 -16
  56. data/vendored/puppet/lib/puppet/indirector/certificate/file.rb +0 -1
  57. data/vendored/puppet/lib/puppet/indirector/facts/yaml.rb +4 -2
  58. data/vendored/puppet/lib/puppet/indirector/key/file.rb +1 -6
  59. data/vendored/puppet/lib/puppet/indirector/node/exec.rb +1 -3
  60. data/vendored/puppet/lib/puppet/indirector/node/yaml.rb +0 -6
  61. data/vendored/puppet/lib/puppet/indirector/request.rb +1 -1
  62. data/vendored/puppet/lib/puppet/indirector/ssl_file.rb +3 -44
  63. data/vendored/puppet/lib/puppet/indirector/yaml.rb +4 -4
  64. data/vendored/puppet/lib/puppet/info_service/task_information_service.rb +7 -3
  65. data/vendored/puppet/lib/puppet/loaders.rb +1 -0
  66. data/vendored/puppet/lib/puppet/module/task.rb +198 -29
  67. data/vendored/puppet/lib/puppet/module_tool/applications/unpacker.rb +1 -1
  68. data/vendored/puppet/lib/puppet/network/format_support.rb +13 -8
  69. data/vendored/puppet/lib/puppet/network/formats.rb +93 -2
  70. data/vendored/puppet/lib/puppet/network/http/api/indirected_routes.rb +10 -3
  71. data/vendored/puppet/lib/puppet/node/facts.rb +11 -1
  72. data/vendored/puppet/lib/puppet/parser/catalog_compiler.rb +56 -0
  73. data/vendored/puppet/lib/puppet/parser/compiler.rb +3 -1
  74. data/vendored/puppet/lib/puppet/parser/functions.rb +3 -1
  75. data/vendored/puppet/lib/puppet/parser/functions/filter.rb +1 -1
  76. data/vendored/puppet/lib/puppet/parser/functions/generate.rb +1 -1
  77. data/vendored/puppet/lib/puppet/parser/functions/sprintf.rb +12 -1
  78. data/vendored/puppet/lib/puppet/parser/functions/tagged.rb +1 -4
  79. data/vendored/puppet/lib/puppet/parser/scope.rb +1 -1
  80. data/vendored/puppet/lib/puppet/parser/script_compiler.rb +7 -2
  81. data/vendored/puppet/lib/puppet/pops/evaluator/deferred_resolver.rb +5 -3
  82. data/vendored/puppet/lib/puppet/pops/evaluator/runtime3_converter.rb +23 -4
  83. data/vendored/puppet/lib/puppet/pops/evaluator/runtime3_support.rb +3 -4
  84. data/vendored/puppet/lib/puppet/pops/functions/dispatch.rb +4 -0
  85. data/vendored/puppet/lib/puppet/pops/issues.rb +8 -0
  86. data/vendored/puppet/lib/puppet/pops/loader/loader.rb +2 -2
  87. data/vendored/puppet/lib/puppet/pops/loader/loader_paths.rb +3 -1
  88. data/vendored/puppet/lib/puppet/pops/loader/module_loaders.rb +30 -9
  89. data/vendored/puppet/lib/puppet/pops/loader/ruby_legacy_function_instantiator.rb +62 -0
  90. data/vendored/puppet/lib/puppet/pops/loader/static_loader.rb +0 -1
  91. data/vendored/puppet/lib/puppet/pops/loader/task_instantiator.rb +13 -70
  92. data/vendored/puppet/lib/puppet/pops/loaders.rb +19 -29
  93. data/vendored/puppet/lib/puppet/pops/lookup/hiera_config.rb +1 -1
  94. data/vendored/puppet/lib/puppet/pops/model/model_label_provider.rb +4 -1
  95. data/vendored/puppet/lib/puppet/pops/pcore.rb +10 -33
  96. data/vendored/puppet/lib/puppet/pops/serialization.rb +2 -0
  97. data/vendored/puppet/lib/puppet/pops/serialization/from_data_converter.rb +2 -1
  98. data/vendored/puppet/lib/puppet/pops/serialization/to_data_converter.rb +11 -3
  99. data/vendored/puppet/lib/puppet/pops/serialization/to_stringified_converter.rb +226 -0
  100. data/vendored/puppet/lib/puppet/pops/types/p_object_type.rb +3 -0
  101. data/vendored/puppet/lib/puppet/pops/validation/checker4_0.rb +97 -47
  102. data/vendored/puppet/lib/puppet/pops/validation/validator_factory_4_0.rb +7 -8
  103. data/vendored/puppet/lib/puppet/property/keyvalue.rb +70 -8
  104. data/vendored/puppet/lib/puppet/provider/aix_object.rb +483 -0
  105. data/vendored/puppet/lib/puppet/provider/file/windows.rb +1 -1
  106. data/vendored/puppet/lib/puppet/provider/group/aix.rb +51 -112
  107. data/vendored/puppet/lib/puppet/provider/package/gem.rb +1 -1
  108. data/vendored/puppet/lib/puppet/provider/package/pip.rb +1 -1
  109. data/vendored/puppet/lib/puppet/provider/package/puppet_gem.rb +1 -1
  110. data/vendored/puppet/lib/puppet/provider/package/rpm.rb +1 -1
  111. data/vendored/puppet/lib/puppet/provider/package/windows/package.rb +1 -1
  112. data/vendored/puppet/lib/puppet/provider/package/zypper.rb +1 -1
  113. data/vendored/puppet/lib/puppet/provider/service/systemd.rb +1 -1
  114. data/vendored/puppet/lib/puppet/provider/service/windows.rb +37 -40
  115. data/vendored/puppet/lib/puppet/provider/user/aix.rb +142 -254
  116. data/vendored/puppet/lib/puppet/resource.rb +20 -3
  117. data/vendored/puppet/lib/puppet/resource/catalog.rb +2 -12
  118. data/vendored/puppet/lib/puppet/rest/routes.rb +97 -34
  119. data/vendored/puppet/lib/puppet/settings.rb +1 -1
  120. data/vendored/puppet/lib/puppet/settings/file_setting.rb +1 -1
  121. data/vendored/puppet/lib/puppet/ssl/base.rb +1 -9
  122. data/vendored/puppet/lib/puppet/ssl/certificate_request.rb +1 -13
  123. data/vendored/puppet/lib/puppet/ssl/certificate_request_attributes.rb +1 -1
  124. data/vendored/puppet/lib/puppet/ssl/host.rb +114 -232
  125. data/vendored/puppet/lib/puppet/ssl/key.rb +1 -5
  126. data/vendored/puppet/lib/puppet/ssl/oids.rb +1 -1
  127. data/vendored/puppet/lib/puppet/test/test_helper.rb +0 -4
  128. data/vendored/puppet/lib/puppet/transaction/event.rb +3 -7
  129. data/vendored/puppet/lib/puppet/transaction/persistence.rb +1 -1
  130. data/vendored/puppet/lib/puppet/type/exec.rb +18 -16
  131. data/vendored/puppet/lib/puppet/type/file.rb +3 -3
  132. data/vendored/puppet/lib/puppet/type/file/source.rb +20 -7
  133. data/vendored/puppet/lib/puppet/type/group.rb +3 -5
  134. data/vendored/puppet/lib/puppet/type/notify.rb +1 -1
  135. data/vendored/puppet/lib/puppet/type/package.rb +2 -5
  136. data/vendored/puppet/lib/puppet/type/schedule.rb +1 -1
  137. data/vendored/puppet/lib/puppet/type/service.rb +3 -6
  138. data/vendored/puppet/lib/puppet/type/tidy.rb +1 -1
  139. data/vendored/puppet/lib/puppet/type/user.rb +13 -20
  140. data/vendored/puppet/lib/puppet/util.rb +8 -9
  141. data/vendored/puppet/lib/puppet/util/execution.rb +3 -3
  142. data/vendored/puppet/lib/puppet/util/feature.rb +61 -39
  143. data/vendored/puppet/lib/puppet/util/log/destinations.rb +1 -1
  144. data/vendored/puppet/lib/puppet/util/rdoc.rb +1 -1
  145. data/vendored/puppet/lib/puppet/util/run_mode.rb +1 -1
  146. data/vendored/puppet/lib/puppet/util/storage.rb +1 -1
  147. data/vendored/puppet/lib/puppet/util/suidmanager.rb +7 -5
  148. data/vendored/puppet/lib/puppet/util/tag_set.rb +1 -1
  149. data/vendored/puppet/lib/puppet/util/tagging.rb +1 -1
  150. data/vendored/puppet/lib/puppet/util/windows.rb +18 -2
  151. data/vendored/puppet/lib/puppet/util/windows/adsi.rb +154 -205
  152. data/vendored/puppet/lib/puppet/util/windows/service.rb +770 -0
  153. data/vendored/puppet/lib/puppet/util/yaml.rb +41 -5
  154. data/vendored/puppet/lib/puppet/version.rb +1 -1
  155. data/vendored/puppet/lib/puppet_pal.rb +280 -24
  156. metadata +8 -38
  157. data/lib/bolt/catalog/compiler.rb +0 -48
  158. data/lib/bolt/catalog/loaders.rb +0 -19
  159. data/vendored/puppet/lib/puppet/application/ca.rb +0 -11
  160. data/vendored/puppet/lib/puppet/application/certificate.rb +0 -17
  161. data/vendored/puppet/lib/puppet/application/certificate_request.rb +0 -7
  162. data/vendored/puppet/lib/puppet/application/certificate_revocation_list.rb +0 -7
  163. data/vendored/puppet/lib/puppet/face/ca.rb +0 -266
  164. data/vendored/puppet/lib/puppet/face/certificate.rb +0 -167
  165. data/vendored/puppet/lib/puppet/face/certificate_request.rb +0 -56
  166. data/vendored/puppet/lib/puppet/face/certificate_revocation_list.rb +0 -56
  167. data/vendored/puppet/lib/puppet/graph/random_prioritizer.rb +0 -16
  168. data/vendored/puppet/lib/puppet/graph/title_hash_prioritizer.rb +0 -16
  169. data/vendored/puppet/lib/puppet/indirector/certificate/ca.rb +0 -9
  170. data/vendored/puppet/lib/puppet/indirector/certificate/disabled_ca.rb +0 -22
  171. data/vendored/puppet/lib/puppet/indirector/certificate_request/ca.rb +0 -22
  172. data/vendored/puppet/lib/puppet/indirector/certificate_request/disabled_ca.rb +0 -22
  173. data/vendored/puppet/lib/puppet/indirector/certificate_revocation_list/ca.rb +0 -8
  174. data/vendored/puppet/lib/puppet/indirector/certificate_revocation_list/disabled_ca.rb +0 -22
  175. data/vendored/puppet/lib/puppet/indirector/certificate_revocation_list/file.rb +0 -8
  176. data/vendored/puppet/lib/puppet/indirector/certificate_revocation_list/rest.rb +0 -11
  177. data/vendored/puppet/lib/puppet/indirector/certificate_status.rb +0 -4
  178. data/vendored/puppet/lib/puppet/indirector/certificate_status/file.rb +0 -91
  179. data/vendored/puppet/lib/puppet/indirector/certificate_status/rest.rb +0 -11
  180. data/vendored/puppet/lib/puppet/indirector/key/ca.rb +0 -16
  181. data/vendored/puppet/lib/puppet/indirector/key/disabled_ca.rb +0 -22
  182. data/vendored/puppet/lib/puppet/indirector/ldap.rb +0 -86
  183. data/vendored/puppet/lib/puppet/indirector/node/ldap.rb +0 -275
  184. data/vendored/puppet/lib/puppet/provider/aixobject.rb +0 -392
  185. data/vendored/puppet/lib/puppet/provider/cron/crontab.rb +0 -297
  186. data/vendored/puppet/lib/puppet/ssl/certificate_authority.rb +0 -475
  187. data/vendored/puppet/lib/puppet/ssl/certificate_authority/autosign_command.rb +0 -45
  188. data/vendored/puppet/lib/puppet/ssl/certificate_authority/interface.rb +0 -324
  189. data/vendored/puppet/lib/puppet/ssl/certificate_factory.rb +0 -219
  190. data/vendored/puppet/lib/puppet/ssl/certificate_revocation_list.rb +0 -111
  191. data/vendored/puppet/lib/puppet/ssl/inventory.rb +0 -55
  192. data/vendored/puppet/lib/puppet/type/cron.rb +0 -480
@@ -0,0 +1,770 @@
1
+ require 'puppet/util/windows'
2
+ require 'ffi'
3
+
4
+ module Puppet::Util::Windows
5
+ # This module is designed to provide an API between the windows system and puppet for
6
+ # service management.
7
+ #
8
+ # for an overview of the service state transitions see: https://docs.microsoft.com/en-us/windows/desktop/Services/service-status-transitions
9
+ module Service
10
+ extend FFI::Library
11
+ extend Puppet::Util::Windows::String
12
+
13
+ FILE = Puppet::Util::Windows::File
14
+
15
+ # integer value of the floor for timeouts when waiting for service pending states.
16
+ # puppet will wait the length of dwWaitHint if it is longer than this value, but
17
+ # no shorter
18
+ DEFAULT_TIMEOUT = 30
19
+
20
+ # Service control codes
21
+ # https://docs.microsoft.com/en-us/windows/desktop/api/Winsvc/nf-winsvc-controlserviceexw
22
+ SERVICE_CONTROL_STOP = 0x00000001
23
+ SERVICE_CONTROL_PAUSE = 0x00000002
24
+ SERVICE_CONTROL_CONTINUE = 0x00000003
25
+ SERVICE_CONTROL_INTERROGATE = 0x00000004
26
+ SERVICE_CONTROL_SHUTDOWN = 0x00000005
27
+ SERVICE_CONTROL_PARAMCHANGE = 0x00000006
28
+ SERVICE_CONTROL_NETBINDADD = 0x00000007
29
+ SERVICE_CONTROL_NETBINDREMOVE = 0x00000008
30
+ SERVICE_CONTROL_NETBINDENABLE = 0x00000009
31
+ SERVICE_CONTROL_NETBINDDISABLE = 0x0000000A
32
+ SERVICE_CONTROL_DEVICEEVENT = 0x0000000B
33
+ SERVICE_CONTROL_HARDWAREPROFILECHANGE = 0x0000000C
34
+ SERVICE_CONTROL_POWEREVENT = 0x0000000D
35
+ SERVICE_CONTROL_SESSIONCHANGE = 0x0000000E
36
+ SERVICE_CONTROL_PRESHUTDOWN = 0x0000000F
37
+ SERVICE_CONTROL_TIMECHANGE = 0x00000010
38
+ SERVICE_CONTROL_TRIGGEREVENT = 0x00000020
39
+
40
+ # Service start type codes
41
+ # https://docs.microsoft.com/en-us/windows/desktop/api/Winsvc/nf-winsvc-changeserviceconfigw
42
+ SERVICE_AUTO_START = 0x00000002
43
+ SERVICE_BOOT_START = 0x00000000
44
+ SERVICE_DEMAND_START = 0x00000003
45
+ SERVICE_DISABLED = 0x00000004
46
+ SERVICE_SYSTEM_START = 0x00000001
47
+ SERVICE_START_TYPES = {
48
+ SERVICE_AUTO_START => :SERVICE_AUTO_START,
49
+ SERVICE_BOOT_START => :SERVICE_BOOT_START,
50
+ SERVICE_DEMAND_START => :SERVICE_DEMAND_START,
51
+ SERVICE_DISABLED => :SERVICE_DISABLED,
52
+ SERVICE_SYSTEM_START => :SERVICE_SYSTEM_START,
53
+ }
54
+
55
+ # Service type codes
56
+ # https://docs.microsoft.com/en-us/windows/desktop/api/Winsvc/nf-winsvc-changeserviceconfigw
57
+ SERVICE_FILE_SYSTEM_DRIVER = 0x00000002
58
+ SERVICE_KERNEL_DRIVER = 0x00000001
59
+ SERVICE_WIN32_OWN_PROCESS = 0x00000010
60
+ SERVICE_WIN32_SHARE_PROCESS = 0x00000020
61
+ SERVICE_USER_OWN_PROCESS = 0x00000050
62
+ SERVICE_USER_SHARE_PROCESS = 0x00000060
63
+ # Available only if service is also SERVICE_WIN32_OWN_PROCESS or SERVICE_WIN32_SHARE_PROCESS
64
+ SERVICE_INTERACTIVE_PROCESS = 0x00000100
65
+ ALL_SERVICE_TYPES =
66
+ SERVICE_FILE_SYSTEM_DRIVER |
67
+ SERVICE_KERNEL_DRIVER |
68
+ SERVICE_WIN32_OWN_PROCESS |
69
+ SERVICE_WIN32_SHARE_PROCESS
70
+
71
+ # Current state codes
72
+ # https://docs.microsoft.com/en-us/windows/desktop/api/winsvc/ns-winsvc-_service_status_process
73
+ SERVICE_CONTINUE_PENDING = 0x00000005
74
+ SERVICE_PAUSE_PENDING = 0x00000006
75
+ SERVICE_PAUSED = 0x00000007
76
+ SERVICE_RUNNING = 0x00000004
77
+ SERVICE_START_PENDING = 0x00000002
78
+ SERVICE_STOP_PENDING = 0x00000003
79
+ SERVICE_STOPPED = 0x00000001
80
+ SERVICE_STATES = {
81
+ SERVICE_CONTINUE_PENDING => :SERVICE_CONTINUE_PENDING,
82
+ SERVICE_PAUSE_PENDING => :SERVICE_PAUSE_PENDING,
83
+ SERVICE_PAUSED => :SERVICE_PAUSED,
84
+ SERVICE_RUNNING => :SERVICE_RUNNING,
85
+ SERVICE_START_PENDING => :SERVICE_START_PENDING,
86
+ SERVICE_STOP_PENDING => :SERVICE_STOP_PENDING,
87
+ SERVICE_STOPPED => :SERVICE_STOPPED,
88
+ }
89
+
90
+ # Service accepts control codes
91
+ # https://docs.microsoft.com/en-us/windows/desktop/api/winsvc/ns-winsvc-_service_status_process
92
+ SERVICE_ACCEPT_STOP = 0x00000001
93
+ SERVICE_ACCEPT_PAUSE_CONTINUE = 0x00000002
94
+ SERVICE_ACCEPT_SHUTDOWN = 0x00000004
95
+ SERVICE_ACCEPT_PARAMCHANGE = 0x00000008
96
+ SERVICE_ACCEPT_NETBINDCHANGE = 0x00000010
97
+ SERVICE_ACCEPT_HARDWAREPROFILECHANGE = 0x00000020
98
+ SERVICE_ACCEPT_POWEREVENT = 0x00000040
99
+ SERVICE_ACCEPT_SESSIONCHANGE = 0x00000080
100
+ SERVICE_ACCEPT_PRESHUTDOWN = 0x00000100
101
+ SERVICE_ACCEPT_TIMECHANGE = 0x00000200
102
+ SERVICE_ACCEPT_TRIGGEREVENT = 0x00000400
103
+ SERVICE_ACCEPT_USER_LOGOFF = 0x00000800
104
+
105
+ # Service manager access codes
106
+ # https://docs.microsoft.com/en-us/windows/desktop/Services/service-security-and-access-rights
107
+ SC_MANAGER_CREATE_SERVICE = 0x00000002
108
+ SC_MANAGER_CONNECT = 0x00000001
109
+ SC_MANAGER_ENUMERATE_SERVICE = 0x00000004
110
+ SC_MANAGER_LOCK = 0x00000008
111
+ SC_MANAGER_MODIFY_BOOT_CONFIG = 0x00000020
112
+ SC_MANAGER_QUERY_LOCK_STATUS = 0x00000010
113
+ SC_MANAGER_ALL_ACCESS =
114
+ FILE::STANDARD_RIGHTS_REQUIRED |
115
+ SC_MANAGER_CREATE_SERVICE |
116
+ SC_MANAGER_CONNECT |
117
+ SC_MANAGER_ENUMERATE_SERVICE |
118
+ SC_MANAGER_LOCK |
119
+ SC_MANAGER_MODIFY_BOOT_CONFIG |
120
+ SC_MANAGER_QUERY_LOCK_STATUS
121
+
122
+
123
+ # Service access codes
124
+ # https://docs.microsoft.com/en-us/windows/desktop/Services/service-security-and-access-rights
125
+ SERVICE_CHANGE_CONFIG = 0x0002
126
+ SERVICE_ENUMERATE_DEPENDENTS = 0x0008
127
+ SERVICE_INTERROGATE = 0x0080
128
+ SERVICE_PAUSE_CONTINUE = 0x0040
129
+ SERVICE_QUERY_STATUS = 0x0004
130
+ SERVICE_QUERY_CONFIG = 0x0001
131
+ SERVICE_START = 0x0010
132
+ SERVICE_STOP = 0x0020
133
+ SERVICE_USER_DEFINED_CONTROL = 0x0100
134
+ SERVICE_ALL_ACCESS =
135
+ FILE::STANDARD_RIGHTS_REQUIRED |
136
+ SERVICE_CHANGE_CONFIG |
137
+ SERVICE_ENUMERATE_DEPENDENTS |
138
+ SERVICE_INTERROGATE |
139
+ SERVICE_PAUSE_CONTINUE |
140
+ SERVICE_QUERY_STATUS |
141
+ SERVICE_QUERY_CONFIG |
142
+ SERVICE_START |
143
+ SERVICE_STOP |
144
+ SERVICE_USER_DEFINED_CONTROL
145
+
146
+ # Service config codes
147
+ # From the windows 10 SDK:
148
+ # //
149
+ # // Value to indicate no change to an optional parameter
150
+ # //
151
+ # #define SERVICE_NO_CHANGE 0xffffffff
152
+ SERVICE_NO_CHANGE = 0xffffffff
153
+
154
+ # Service enum codes
155
+ # https://docs.microsoft.com/en-us/windows/desktop/api/winsvc/nf-winsvc-enumservicesstatusexa
156
+ SERVICE_ACTIVE = 0x00000001
157
+ SERVICE_INACTIVE = 0x00000002
158
+ SERVICE_STATE_ALL =
159
+ SERVICE_ACTIVE |
160
+ SERVICE_INACTIVE
161
+
162
+ # https://docs.microsoft.com/en-us/windows/desktop/api/winsvc/ns-winsvc-_enum_service_status_processw
163
+ SERVICENAME_MAX = 256
164
+
165
+ # https://docs.microsoft.com/en-us/windows/desktop/api/winsvc/ns-winsvc-_service_status_process
166
+ # typedef struct _SERVICE_STATUS_PROCESS {
167
+ # DWORD dwServiceType;
168
+ # DWORD dwCurrentState;
169
+ # DWORD dwControlsAccepted;
170
+ # DWORD dwWin32ExitCode;
171
+ # DWORD dwServiceSpecificExitCode;
172
+ # DWORD dwCheckPoint;
173
+ # DWORD dwWaitHint;
174
+ # DWORD dwProcessId;
175
+ # DWORD dwServiceFlags;
176
+ # } SERVICE_STATUS_PROCESS, *LPSERVICE_STATUS_PROCESS;
177
+ class SERVICE_STATUS_PROCESS < FFI::Struct
178
+ layout(
179
+ :dwServiceType, :dword,
180
+ :dwCurrentState, :dword,
181
+ :dwControlsAccepted, :dword,
182
+ :dwWin32ExitCode, :dword,
183
+ :dwServiceSpecificExitCode, :dword,
184
+ :dwCheckPoint, :dword,
185
+ :dwWaitHint, :dword,
186
+ :dwProcessId, :dword,
187
+ :dwServiceFlags, :dword
188
+ )
189
+ end
190
+
191
+
192
+ # https://docs.microsoft.com/en-us/windows/desktop/api/winsvc/ns-winsvc-_enum_service_status_processw
193
+ # typedef struct _ENUM_SERVICE_STATUS_PROCESSW {
194
+ # LPWSTR lpServiceName;
195
+ # LPWSTR lpDisplayName;
196
+ # SERVICE_STATUS_PROCESS ServiceStatusProcess;
197
+ # } ENUM_SERVICE_STATUS_PROCESSW, *LPENUM_SERVICE_STATUS_PROCESSW;
198
+ class ENUM_SERVICE_STATUS_PROCESSW < FFI::Struct
199
+ layout(
200
+ :lpServiceName, :pointer,
201
+ :lpDisplayName, :pointer,
202
+ :ServiceStatusProcess, SERVICE_STATUS_PROCESS
203
+ )
204
+ end
205
+
206
+ # typedef struct _SERVICE_STATUS {
207
+ # DWORD dwServiceType;
208
+ # DWORD dwCurrentState;
209
+ # DWORD dwControlsAccepted;
210
+ # DWORD dwWin32ExitCode;
211
+ # DWORD dwServiceSpecificExitCode;
212
+ # DWORD dwCheckPoint;
213
+ # DWORD dwWaitHint;
214
+ # } SERVICE_STATUS, *LPSERVICE_STATUS;
215
+ class SERVICE_STATUS < FFI::Struct
216
+ layout(
217
+ :dwServiceType, :dword,
218
+ :dwCurrentState, :dword,
219
+ :dwControlsAccepted, :dword,
220
+ :dwWin32ExitCode, :dword,
221
+ :dwServiceSpecificExitCode, :dword,
222
+ :dwCheckPoint, :dword,
223
+ :dwWaitHint, :dword,
224
+ )
225
+ end
226
+
227
+ # typedef struct _QUERY_SERVICE_CONFIGW {
228
+ # DWORD dwServiceType;
229
+ # DWORD dwStartType;
230
+ # DWORD dwErrorControl;
231
+ # LPWSTR lpBinaryPathName;
232
+ # LPWSTR lpLoadOrderGroup;
233
+ # DWORD dwTagId;
234
+ # LPWSTR lpDependencies;
235
+ # LPWSTR lpServiceStartName;
236
+ # LPWSTR lpDisplayName;
237
+ # } QUERY_SERVICE_CONFIGW, *LPQUERY_SERVICE_CONFIGW;
238
+ class QUERY_SERVICE_CONFIGW < FFI::Struct
239
+ layout(
240
+ :dwServiceType, :dword,
241
+ :dwStartType, :dword,
242
+ :dwErrorControl, :dword,
243
+ :lpBinaryPathName, :pointer,
244
+ :lpLoadOrderGroup, :pointer,
245
+ :dwTagId, :dword,
246
+ :lpDependencies, :pointer,
247
+ :lpServiceStartName, :pointer,
248
+ :lpDisplayName, :pointer,
249
+ )
250
+ end
251
+
252
+ # Start a windows service, assume that the service is already in the stopped state
253
+ #
254
+ # @param [:string] service_name name of the service to start
255
+ def start(service_name)
256
+ open_service(service_name, SC_MANAGER_CONNECT, SERVICE_START | SERVICE_QUERY_STATUS) do |service|
257
+ # don't attempt to fail here if the service isn't stopped because windows error codes
258
+ # are likely more informative than ours and a failed call to StartServiceW will produce
259
+ # those errors
260
+ wait_for_pending_transition(service, SERVICE_STOP_PENDING, SERVICE_STOPPED)
261
+ if StartServiceW(service, 0, FFI::Pointer::NULL) == FFI::WIN32_FALSE
262
+ raise Puppet::Util::Windows::Error.new(_("Failed to start the service"))
263
+ end
264
+ unless wait_for_pending_transition(service, SERVICE_START_PENDING, SERVICE_RUNNING)
265
+ raise Puppet::Error.new(_("Failed to start the service, after calling StartService the service is not in SERVICE_START_PENDING or SERVICE_RUNNING"))
266
+ end
267
+ end
268
+ end
269
+ module_function :start
270
+
271
+ # Use ControlService to send a stop signal to a windows service
272
+ #
273
+ # @param [:string] service_name name of the service to stop
274
+ def stop(service_name)
275
+ open_service(service_name, SC_MANAGER_CONNECT, SERVICE_STOP | SERVICE_QUERY_STATUS) do |service|
276
+ FFI::MemoryPointer.new(SERVICE_STATUS.size) do |status_ptr|
277
+ status = SERVICE_STATUS.new(status_ptr)
278
+ # don't attempt to fail here if the service isn't started because windows error codes
279
+ # are likely more informative than ours and a failed call to ControlService will produce
280
+ # those errors
281
+ wait_for_pending_transition(service, SERVICE_START_PENDING, SERVICE_RUNNING)
282
+ if ControlService(service, SERVICE_CONTROL_STOP, status) == FFI::WIN32_FALSE
283
+ raise Puppet::Util::Windows::Error.new(_("Failed to send stop control to service, current state is %{current_state}. Failed with") % { current_state: status[:dwCurrentState].to_s })
284
+ end
285
+ unless wait_for_pending_transition(service, SERVICE_STOP_PENDING, SERVICE_STOPPED)
286
+ raise Puppet::Error.new(_("Failed to stop the service, after calling ControlService the service is not in SERVICE_STOP_PENDING or SERVICE_STOPPED"))
287
+ end
288
+ end
289
+ end
290
+ end
291
+ module_function :stop
292
+
293
+ # Query the state of a service using QueryServiceStatusEx
294
+ #
295
+ # @param [:string] service_name name of the service to query
296
+ # @return [string] the status of the service
297
+ def service_state(service_name)
298
+ status = nil
299
+ open_service(service_name, SC_MANAGER_CONNECT, SERVICE_QUERY_STATUS) do |service|
300
+ status = query_status(service)
301
+ end
302
+ state = SERVICE_STATES[status[:dwCurrentState]]
303
+ if state.nil?
304
+ raise Puppet::Error.new(_("Unknown Service state '%{current_state}' for '%{service_name}'") % { current_state: status[:dwCurrentState].to_s, service_name: service_name})
305
+ end
306
+ state
307
+ end
308
+ module_function :service_state
309
+
310
+ # Query the configuration of a service using QueryServiceConfigW
311
+ #
312
+ # @param [:string] service_name name of the service to query
313
+ # @return [QUERY_SERVICE_CONFIGW.struct] the configuration of the service
314
+ def service_start_type(service_name)
315
+ config = nil
316
+ open_service(service_name, SC_MANAGER_CONNECT, SERVICE_QUERY_CONFIG) do |service|
317
+ config = query_config(service)
318
+ end
319
+ start_type = SERVICE_START_TYPES[config[:dwStartType]]
320
+ if start_type.nil?
321
+ raise Puppet::Error.new(_("Unknown start type '%{start_type}' for '%{service_name}'") % { start_type: config[:dwStartType].to_s, service_name: service_name})
322
+ end
323
+ start_type
324
+ end
325
+ module_function :service_start_type
326
+
327
+ # Change the startup mode of a windows service
328
+ #
329
+ # @param [string] service_name the name of the service to modify
330
+ # @param [Int] startup_type a code corresponding to a start type for
331
+ # windows service, see the "Service start type codes" section in the
332
+ # Puppet::Util::Windows::Service file for the list of available codes
333
+ def set_startup_mode(service_name, startup_type)
334
+ startup_code = SERVICE_START_TYPES.key(startup_type)
335
+ if startup_code.nil?
336
+ raise Puppet::Error.new(_("Unknown start type %{start_type}") % {startup_type: startup_type.to_s})
337
+ end
338
+ open_service(service_name, SC_MANAGER_CONNECT, SERVICE_CHANGE_CONFIG) do |service|
339
+ # Currently the only thing puppet's API can really manage
340
+ # in this list is dwStartType (the third param). Thus no
341
+ # generic function was written to make use of all the params
342
+ # since the API as-is couldn't use them anyway
343
+ success = ChangeServiceConfigW(
344
+ service,
345
+ SERVICE_NO_CHANGE, # dwServiceType
346
+ startup_code, # dwStartType
347
+ SERVICE_NO_CHANGE, # dwErrorControl
348
+ FFI::Pointer::NULL, # lpBinaryPathName
349
+ FFI::Pointer::NULL, # lpLoadOrderGroup
350
+ FFI::Pointer::NULL, # lpdwTagId
351
+ FFI::Pointer::NULL, # lpDependencies
352
+ FFI::Pointer::NULL, # lpServiceStartName
353
+ FFI::Pointer::NULL, # lpPassword
354
+ FFI::Pointer::NULL # lpDisplayName
355
+ )
356
+ if success == FFI::WIN32_FALSE
357
+ raise Puppet::Util::Windows::Error.new(_("Failed to update service configuration"))
358
+ end
359
+ end
360
+ end
361
+ module_function :set_startup_mode
362
+
363
+ # enumerate over all services in all states and return them as a hash
364
+ #
365
+ # @return [Hash] a hash containing services:
366
+ # { 'service name' => {
367
+ # 'display_name' => 'display name',
368
+ # 'service_status_process' => SERVICE_STATUS_PROCESS struct
369
+ # }
370
+ # }
371
+ def services
372
+ services = {}
373
+ open_scm(SC_MANAGER_ENUMERATE_SERVICE) do |scm|
374
+ size_required = 0
375
+ services_returned = 0
376
+ FFI::MemoryPointer.new(:dword) do |bytes_pointer|
377
+ FFI::MemoryPointer.new(:dword) do |svcs_ret_ptr|
378
+ FFI::MemoryPointer.new(:dword) do |resume_ptr|
379
+ resume_ptr.write_dword(0)
380
+ # Fetch the bytes of memory required to be allocated
381
+ # for QueryServiceConfigW to return succesfully. This
382
+ # is done by sending NULL and 0 for the pointer and size
383
+ # respectively, letting the command fail, then reading the
384
+ # value of pcbBytesNeeded
385
+ #
386
+ # return value will be false from this call, since it's designed
387
+ # to fail. Just ignore it
388
+ EnumServicesStatusExW(
389
+ scm,
390
+ :SC_ENUM_PROCESS_INFO,
391
+ ALL_SERVICE_TYPES,
392
+ SERVICE_STATE_ALL,
393
+ FFI::Pointer::NULL,
394
+ 0,
395
+ bytes_pointer,
396
+ svcs_ret_ptr,
397
+ resume_ptr,
398
+ FFI::Pointer::NULL
399
+ )
400
+ size_required = bytes_pointer.read_dword
401
+ FFI::MemoryPointer.new(size_required) do |buffer_ptr|
402
+ resume_ptr.write_dword(0)
403
+ svcs_ret_ptr.write_dword(0)
404
+ success = EnumServicesStatusExW(
405
+ scm,
406
+ :SC_ENUM_PROCESS_INFO,
407
+ ALL_SERVICE_TYPES,
408
+ SERVICE_STATE_ALL,
409
+ buffer_ptr,
410
+ buffer_ptr.size,
411
+ bytes_pointer,
412
+ svcs_ret_ptr,
413
+ resume_ptr,
414
+ FFI::Pointer::NULL
415
+ )
416
+ if success == FFI::WIN32_FALSE
417
+ raise Puppet::Util::Windows::Error.new(_("Failed to fetch services"))
418
+ end
419
+ # Now that the buffer is populated with services
420
+ # we pull the data from memory using pointer arithmetic:
421
+ # the number of services returned by the function is
422
+ # available to be read from svcs_ret_ptr, and we iterate
423
+ # that many times moving the cursor pointer the length of
424
+ # ENUM_SERVICE_STATUS_PROCESSW.size. This should iterate
425
+ # over the buffer and extract each struct.
426
+ services_returned = svcs_ret_ptr.read_dword
427
+ cursor_ptr = FFI::Pointer.new(ENUM_SERVICE_STATUS_PROCESSW, buffer_ptr)
428
+ 0.upto(services_returned - 1) do |index|
429
+ service = ENUM_SERVICE_STATUS_PROCESSW.new(cursor_ptr[index])
430
+ services[service[:lpServiceName].read_arbitrary_wide_string_up_to(SERVICENAME_MAX)] = {
431
+ :display_name => service[:lpDisplayName].read_arbitrary_wide_string_up_to(SERVICENAME_MAX),
432
+ :service_status_process => service[:ServiceStatusProcess]
433
+ }
434
+ end
435
+ end # buffer_ptr
436
+ end # resume_ptr
437
+ end # scvs_ret_ptr
438
+ end # bytes_ptr
439
+ end # open_scm
440
+ services
441
+ end
442
+ module_function :services
443
+
444
+ class << self
445
+ # @api private
446
+ # Opens a connection to the SCManager on windows then uses that
447
+ # handle to create a handle to a specific service in windows
448
+ # corresponding to service_name
449
+ #
450
+ # this function takes a block that executes within the context of
451
+ # the open service handler, and will close the service and SCManager
452
+ # handles once the block finishes
453
+ #
454
+ # @param [string] service_name the name of the service to open
455
+ # @param [Integer] scm_access code corresponding to the access type requested for the scm
456
+ # @param [Integer] service_access code corresponding to the access type requested for the service
457
+ # @yieldparam [:handle] service the windows native handle used to access
458
+ # the service
459
+ def open_service(service_name, scm_access, service_access, &block)
460
+ service = FFI::Pointer::NULL_HANDLE
461
+ open_scm(scm_access) do |scm|
462
+ service = OpenServiceW(scm, wide_string(service_name), service_access)
463
+ raise Puppet::Util::Windows::Error.new(_("Failed to open a handle to the service")) if service == FFI::Pointer::NULL_HANDLE
464
+ yield service
465
+ end
466
+ ensure
467
+ CloseServiceHandle(service)
468
+ end
469
+ private :open_service
470
+
471
+ # @api private
472
+ #
473
+ # Opens a handle to the service control manager
474
+ #
475
+ # @param [Integer] scm_access code corresponding to the access type requested for the scm
476
+ def open_scm(scm_access, &block)
477
+ scm = OpenSCManagerW(FFI::Pointer::NULL, FFI::Pointer::NULL, scm_access)
478
+ raise Puppet::Util::Windows::Error.new(_("Failed to open a handle to the service control manager")) if scm == FFI::Pointer::NULL_HANDLE
479
+ yield scm
480
+ ensure
481
+ CloseServiceHandle(scm)
482
+ end
483
+ private :open_scm
484
+
485
+ # @api private
486
+ # perform QueryServiceStatusEx on a windows service and return the
487
+ # result
488
+ #
489
+ # @param [:handle] service handle of the service to query
490
+ # @return [SERVICE_STATUS_PROCESS struct] the result of the query
491
+ def query_status(service)
492
+ size_required = nil
493
+ status = nil
494
+ # Fetch the bytes of memory required to be allocated
495
+ # for QueryServiceConfigW to return succesfully. This
496
+ # is done by sending NULL and 0 for the pointer and size
497
+ # respectively, letting the command fail, then reading the
498
+ # value of pcbBytesNeeded
499
+ FFI::MemoryPointer.new(:lpword) do |bytes_pointer|
500
+ # return value will be false from this call, since it's designed
501
+ # to fail. Just ignore it
502
+ QueryServiceStatusEx(
503
+ service,
504
+ :SC_STATUS_PROCESS_INFO,
505
+ FFI::Pointer::NULL,
506
+ 0,
507
+ bytes_pointer
508
+ )
509
+ size_required = bytes_pointer.read_dword
510
+ FFI::MemoryPointer.new(size_required) do |ssp_ptr|
511
+ status = SERVICE_STATUS_PROCESS.new(ssp_ptr)
512
+ success = QueryServiceStatusEx(
513
+ service,
514
+ :SC_STATUS_PROCESS_INFO,
515
+ ssp_ptr,
516
+ size_required,
517
+ bytes_pointer
518
+ )
519
+ if success == FFI::WIN32_FALSE
520
+ raise Puppet::Util::Windows::Error.new(_("Service query failed"))
521
+ end
522
+ end
523
+ end
524
+ status
525
+ end
526
+ private :query_status
527
+
528
+ # @api private
529
+ # perform QueryServiceConfigW on a windows service and return the
530
+ # result
531
+ #
532
+ # @param [:handle] service handle of the service to query
533
+ # @return [QUERY_SERVICE_CONFIGW struct] the result of the query
534
+ def query_config(service)
535
+ config = nil
536
+ size_required = nil
537
+ # Fetch the bytes of memory required to be allocated
538
+ # for QueryServiceConfigW to return succesfully. This
539
+ # is done by sending NULL and 0 for the pointer and size
540
+ # respectively, letting the command fail, then reading the
541
+ # value of pcbBytesNeeded
542
+ FFI::MemoryPointer.new(:lpword) do |bytes_pointer|
543
+ # return value will be false from this call, since it's designed
544
+ # to fail. Just ignore it
545
+ QueryServiceConfigW(service, FFI::Pointer::NULL, 0, bytes_pointer)
546
+ size_required = bytes_pointer.read_dword
547
+ FFI::MemoryPointer.new(size_required) do |ssp_ptr|
548
+ config = QUERY_SERVICE_CONFIGW.new(ssp_ptr)
549
+ success = QueryServiceConfigW(
550
+ service,
551
+ ssp_ptr,
552
+ size_required,
553
+ bytes_pointer
554
+ )
555
+ if success == FFI::WIN32_FALSE
556
+ raise Puppet::Util::Windows::Error.new(_("Service query failed"))
557
+ end
558
+ end
559
+ end
560
+ config
561
+ end
562
+ private :query_config
563
+
564
+ # @api private
565
+ # waits for a windows service to report final_state if it
566
+ # is in pending_state
567
+ #
568
+ # @param [:handle] service handle to the service to wait on
569
+ # @param [Integer] pending_state the state to wait on
570
+ # @param [Integer] final_state the state indicating the transition is finished
571
+ # @return [bool] 'true' once the service is reporting final_state,
572
+ # 'false' if the service was not in pending_state or finaL_state
573
+ def wait_for_pending_transition(service, pending_state, final_state)
574
+ elapsed_time = 0
575
+ last_checkpoint = -1
576
+ loop do
577
+ status = query_status(service)
578
+ state = status[:dwCurrentState]
579
+ return true if state == final_state
580
+ unless state == pending_state
581
+ return false
582
+ end
583
+ # When the service is in the pending state we need to do the following:
584
+ # 1. check if any progress has been made since dwWaitHint using dwCheckPoint,
585
+ # and fail if no progress was made
586
+ # 2. if progress has been made, increment elapsed_time and set last_checkpoint
587
+ # 3. sleep, then loop again if there was progress.
588
+ time_to_wait = wait_hint_to_wait_time(status[:dwWaitHint])
589
+ if status[:dwCheckPoint] > last_checkpoint
590
+ elapsed_time = 0
591
+ else
592
+ timeout = milliseconds_to_seconds(status[:dwWaitHint]);
593
+ timeout = DEFAULT_TIMEOUT if timeout < DEFAULT_TIMEOUT
594
+ if elapsed_time >= (timeout)
595
+ raise Puppet::Error.new(_("No progress made on service operation and dwWaitHint exceeded"))
596
+ end
597
+ end
598
+ last_checkpoint = status[:dwCheckPoint]
599
+ sleep(time_to_wait)
600
+ elapsed_time += time_to_wait
601
+ end
602
+ end
603
+ private :wait_for_pending_transition
604
+
605
+ # @api private
606
+ #
607
+ # create a usable wait time to wait between querying the service.
608
+ #
609
+ # @param [Integer] wait_hint the wait hint of a service in milliseconds
610
+ # @return [Integer] the time to wait in seconds between querying the service
611
+ def wait_hint_to_wait_time(wait_hint)
612
+ # Wait 1/10th the wait_hint, but no less than 1 and
613
+ # no more than 10 seconds
614
+ wait_time = milliseconds_to_seconds(wait_hint) / 10;
615
+ wait_time = 1 if wait_time < 1
616
+ wait_time = 10 if wait_time > 10
617
+ wait_time
618
+ end
619
+ private :wait_hint_to_wait_time
620
+
621
+ # @api private
622
+ #
623
+ # process the wait hint listed by a service to something
624
+ # usable by ruby sleep
625
+ #
626
+ # @param [Integer] wait_hint the wait hint of a service in milliseconds
627
+ # @return [Integer] wait_hint in seconds
628
+ def milliseconds_to_seconds(wait_hint)
629
+ wait_hint / 1000;
630
+ end
631
+ private :milliseconds_to_seconds
632
+ end
633
+
634
+ # https://docs.microsoft.com/en-us/windows/desktop/api/Winsvc/nf-winsvc-openscmanagerw
635
+ # SC_HANDLE OpenSCManagerW(
636
+ # LPCWSTR lpMachineName,
637
+ # LPCWSTR lpDatabaseName,
638
+ # DWORD dwDesiredAccess
639
+ # );
640
+ ffi_lib :advapi32
641
+ attach_function_private :OpenSCManagerW,
642
+ [:lpcwstr, :lpcwstr, :dword], :handle
643
+
644
+ # https://docs.microsoft.com/en-us/windows/desktop/api/Winsvc/nf-winsvc-openservicew
645
+ # SC_HANDLE OpenServiceW(
646
+ # SC_HANDLE hSCManager,
647
+ # LPCWSTR lpServiceName,
648
+ # DWORD dwDesiredAccess
649
+ # );
650
+ ffi_lib :advapi32
651
+ attach_function_private :OpenServiceW,
652
+ [:handle, :lpcwstr, :dword], :handle
653
+
654
+ # https://docs.microsoft.com/en-us/windows/desktop/api/Winsvc/nf-winsvc-closeservicehandle
655
+ # BOOL CloseServiceHandle(
656
+ # SC_HANDLE hSCObject
657
+ # );
658
+ ffi_lib :advapi32
659
+ attach_function_private :CloseServiceHandle,
660
+ [:handle], :win32_bool
661
+
662
+ # https://docs.microsoft.com/en-us/windows/desktop/api/winsvc/nf-winsvc-queryservicestatusex
663
+ # BOOL QueryServiceStatusEx(
664
+ # SC_HANDLE hService,
665
+ # SC_STATUS_TYPE InfoLevel,
666
+ # LPBYTE lpBuffer,
667
+ # DWORD cbBufSize,
668
+ # LPDWORD pcbBytesNeeded
669
+ # );
670
+ SC_STATUS_TYPE = enum(
671
+ :SC_STATUS_PROCESS_INFO, 0,
672
+ )
673
+ ffi_lib :advapi32
674
+ attach_function_private :QueryServiceStatusEx,
675
+ [:handle, SC_STATUS_TYPE, :lpbyte, :dword, :lpdword], :win32_bool
676
+
677
+ # https://docs.microsoft.com/en-us/windows/desktop/api/Winsvc/nf-winsvc-queryserviceconfigw
678
+ # BOOL QueryServiceConfigW(
679
+ # SC_HANDLE hService,
680
+ # LPQUERY_SERVICE_CONFIGW lpServiceConfig,
681
+ # DWORD cbBufSize,
682
+ # LPDWORD pcbBytesNeeded
683
+ # );
684
+ ffi_lib :advapi32
685
+ attach_function_private :QueryServiceConfigW,
686
+ [:handle, :lpbyte, :dword, :lpdword], :win32_bool
687
+
688
+ # https://docs.microsoft.com/en-us/windows/desktop/api/Winsvc/nf-winsvc-startservicew
689
+ # BOOL StartServiceW(
690
+ # SC_HANDLE hService,
691
+ # DWORD dwNumServiceArgs,
692
+ # LPCWSTR *lpServiceArgVectors
693
+ # );
694
+ ffi_lib :advapi32
695
+ attach_function_private :StartServiceW,
696
+ [:handle, :dword, :pointer], :win32_bool
697
+
698
+ # https://docs.microsoft.com/en-us/windows/desktop/api/winsvc/nf-winsvc-controlservice
699
+ # BOOL ControlService(
700
+ # SC_HANDLE hService,
701
+ # DWORD dwControl,
702
+ # LPSERVICE_STATUS lpServiceStatus
703
+ # );
704
+ ffi_lib :advapi32
705
+ attach_function_private :ControlService,
706
+ [:handle, :dword, :pointer], :win32_bool
707
+
708
+ # https://docs.microsoft.com/en-us/windows/desktop/api/winsvc/nf-winsvc-changeserviceconfigw
709
+ # BOOL ChangeServiceConfigW(
710
+ # SC_HANDLE hService,
711
+ # DWORD dwServiceType,
712
+ # DWORD dwStartType,
713
+ # DWORD dwErrorControl,
714
+ # LPCWSTR lpBinaryPathName,
715
+ # LPCWSTR lpLoadOrderGroup,
716
+ # LPDWORD lpdwTagId,
717
+ # LPCWSTR lpDependencies,
718
+ # LPCWSTR lpServiceStartName,
719
+ # LPCWSTR lpPassword,
720
+ # LPCWSTR lpDisplayName
721
+ # );
722
+ ffi_lib :advapi32
723
+ attach_function_private :ChangeServiceConfigW,
724
+ [
725
+ :handle,
726
+ :dword,
727
+ :dword,
728
+ :dword,
729
+ :lpcwstr,
730
+ :lpcwstr,
731
+ :lpdword,
732
+ :lpcwstr,
733
+ :lpcwstr,
734
+ :lpcwstr,
735
+ :lpcwstr
736
+ ], :win32_bool
737
+
738
+
739
+ # https://docs.microsoft.com/en-us/windows/desktop/api/winsvc/nf-winsvc-enumservicesstatusexw
740
+ # BOOL EnumServicesStatusExW(
741
+ # SC_HANDLE hSCManager,
742
+ # SC_ENUM_TYPE InfoLevel,
743
+ # DWORD dwServiceType,
744
+ # DWORD dwServiceState,
745
+ # LPBYTE lpServices,
746
+ # DWORD cbBufSize,
747
+ # LPDWORD pcbBytesNeeded,
748
+ # LPDWORD lpServicesReturned,
749
+ # LPDWORD lpResumeHandle,
750
+ # LPCWSTR pszGroupName
751
+ # );
752
+ SC_ENUM_TYPE = enum(
753
+ :SC_ENUM_PROCESS_INFO, 0,
754
+ )
755
+ ffi_lib :advapi32
756
+ attach_function_private :EnumServicesStatusExW,
757
+ [
758
+ :handle,
759
+ SC_ENUM_TYPE,
760
+ :dword,
761
+ :dword,
762
+ :lpbyte,
763
+ :dword,
764
+ :lpdword,
765
+ :lpdword,
766
+ :lpdword,
767
+ :lpcwstr
768
+ ], :win32_bool
769
+ end
770
+ end