bolt 0.21.7 → 0.21.8

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 (83) hide show
  1. checksums.yaml +4 -4
  2. data/lib/bolt/transport/ssh/connection.rb +4 -5
  3. data/lib/bolt/transport/ssh.rb +4 -1
  4. data/lib/bolt/transport/winrm/connection.rb +3 -4
  5. data/lib/bolt/transport/winrm.rb +4 -1
  6. data/lib/bolt/version.rb +1 -1
  7. data/libexec/apply_catalog.rb +10 -2
  8. data/vendored/puppet/lib/puppet/application/apply.rb +20 -9
  9. data/vendored/puppet/lib/puppet/application/cert.rb +3 -1
  10. data/vendored/puppet/lib/puppet/application/device.rb +22 -5
  11. data/vendored/puppet/lib/puppet/configurer/fact_handler.rb +5 -1
  12. data/vendored/puppet/lib/puppet/configurer.rb +15 -2
  13. data/vendored/puppet/lib/puppet/defaults.rb +36 -25
  14. data/vendored/puppet/lib/puppet/face/certificate.rb +2 -0
  15. data/vendored/puppet/lib/puppet/feature/base.rb +0 -3
  16. data/vendored/puppet/lib/puppet/functions/call.rb +37 -0
  17. data/vendored/puppet/lib/puppet/functions.rb +5 -0
  18. data/vendored/puppet/lib/puppet/indirector/ldap.rb +6 -0
  19. data/vendored/puppet/lib/puppet/node/environment.rb +4 -2
  20. data/vendored/puppet/lib/puppet/parser/scope.rb +2 -2
  21. data/vendored/puppet/lib/puppet/pops/adapters.rb +14 -0
  22. data/vendored/puppet/lib/puppet/pops/evaluator/deferred_resolver.rb +128 -0
  23. data/vendored/puppet/lib/puppet/pops/evaluator/evaluator_impl.rb +4 -1
  24. data/vendored/puppet/lib/puppet/pops/functions/dispatch.rb +2 -0
  25. data/vendored/puppet/lib/puppet/pops/issues.rb +9 -1
  26. data/vendored/puppet/lib/puppet/pops/loader/static_loader.rb +0 -16
  27. data/vendored/puppet/lib/puppet/pops/loaders.rb +1 -3
  28. data/vendored/puppet/lib/puppet/pops/parser/eparser.rb +6 -6
  29. data/vendored/puppet/lib/puppet/pops/pcore.rb +11 -0
  30. data/vendored/puppet/lib/puppet/pops/types/type_factory.rb +17 -0
  31. data/vendored/puppet/lib/puppet/pops/validation/tasks_checker.rb +13 -5
  32. data/vendored/puppet/lib/puppet/pops.rb +1 -0
  33. data/vendored/puppet/lib/puppet/provider/service/debian.rb +1 -0
  34. data/vendored/puppet/lib/puppet/provider/service/smf.rb +2 -3
  35. data/vendored/puppet/lib/puppet/provider/service/upstart.rb +10 -2
  36. data/vendored/puppet/lib/puppet/ssl/certificate_authority.rb +6 -84
  37. data/vendored/puppet/lib/puppet/ssl/certificate_request.rb +11 -3
  38. data/vendored/puppet/lib/puppet/type/file.rb +3 -0
  39. data/vendored/puppet/lib/puppet/type/user.rb +17 -3
  40. data/vendored/puppet/lib/puppet/util/autoload.rb +36 -31
  41. data/vendored/puppet/lib/puppet/util.rb +2 -0
  42. metadata +3 -43
  43. data/vendored/puppet/lib/puppet/indirector/node/write_only_yaml.rb +0 -39
  44. data/vendored/puppet/lib/puppet/provider/augeas/augeas.rb +0 -573
  45. data/vendored/puppet/lib/puppet/provider/cisco.rb +0 -9
  46. data/vendored/puppet/lib/puppet/provider/computer/computer.rb +0 -20
  47. data/vendored/puppet/lib/puppet/provider/host/parsed.rb +0 -46
  48. data/vendored/puppet/lib/puppet/provider/interface/cisco.rb +0 -27
  49. data/vendored/puppet/lib/puppet/provider/macauthorization/macauthorization.rb +0 -298
  50. data/vendored/puppet/lib/puppet/provider/mcx/mcxcontent.rb +0 -173
  51. data/vendored/puppet/lib/puppet/provider/mount/parsed.rb +0 -282
  52. data/vendored/puppet/lib/puppet/provider/mount.rb +0 -76
  53. data/vendored/puppet/lib/puppet/provider/scheduled_task/win32_taskscheduler.rb +0 -590
  54. data/vendored/puppet/lib/puppet/provider/selboolean/getsetsebool.rb +0 -47
  55. data/vendored/puppet/lib/puppet/provider/selmodule/semodule.rb +0 -140
  56. data/vendored/puppet/lib/puppet/provider/ssh_authorized_key/parsed.rb +0 -105
  57. data/vendored/puppet/lib/puppet/provider/sshkey/parsed.rb +0 -50
  58. data/vendored/puppet/lib/puppet/provider/vlan/cisco.rb +0 -28
  59. data/vendored/puppet/lib/puppet/provider/yumrepo/inifile.rb +0 -315
  60. data/vendored/puppet/lib/puppet/type/augeas.rb +0 -211
  61. data/vendored/puppet/lib/puppet/type/computer.rb +0 -66
  62. data/vendored/puppet/lib/puppet/type/host.rb +0 -95
  63. data/vendored/puppet/lib/puppet/type/interface.rb +0 -121
  64. data/vendored/puppet/lib/puppet/type/k5login.rb +0 -165
  65. data/vendored/puppet/lib/puppet/type/macauthorization.rb +0 -167
  66. data/vendored/puppet/lib/puppet/type/mcx.rb +0 -98
  67. data/vendored/puppet/lib/puppet/type/mount.rb +0 -314
  68. data/vendored/puppet/lib/puppet/type/router.rb +0 -17
  69. data/vendored/puppet/lib/puppet/type/scheduled_task.rb +0 -183
  70. data/vendored/puppet/lib/puppet/type/selboolean.rb +0 -26
  71. data/vendored/puppet/lib/puppet/type/selmodule.rb +0 -59
  72. data/vendored/puppet/lib/puppet/type/ssh_authorized_key.rb +0 -143
  73. data/vendored/puppet/lib/puppet/type/sshkey.rb +0 -83
  74. data/vendored/puppet/lib/puppet/type/vlan.rb +0 -26
  75. data/vendored/puppet/lib/puppet/type/yumrepo.rb +0 -430
  76. data/vendored/puppet/lib/puppet/util/network_device/cisco/device.rb +0 -285
  77. data/vendored/puppet/lib/puppet/util/network_device/cisco/facts.rb +0 -72
  78. data/vendored/puppet/lib/puppet/util/network_device/cisco/interface.rb +0 -94
  79. data/vendored/puppet/lib/puppet/util/network_device/cisco.rb +0 -4
  80. data/vendored/puppet/lib/puppet/util/network_device/ipcalc.rb +0 -68
  81. data/vendored/puppet/lib/puppet/util/network_device/transport/ssh.rb +0 -126
  82. data/vendored/puppet/lib/puppet/util/network_device/transport/telnet.rb +0 -47
  83. data/vendored/puppet/lib/puppet/util/windows/taskscheduler.rb +0 -1267
@@ -1,1267 +0,0 @@
1
- require 'puppet/util/windows'
2
-
3
- # The Win32 module serves as a namespace only
4
- module Win32
5
- # The TaskScheduler class encapsulates taskscheduler settings and behavior
6
- class TaskScheduler
7
- include Puppet::Util::Windows::String
8
-
9
- require 'ffi'
10
- extend FFI::Library
11
-
12
- # The error class raised if any task scheduler specific calls fail.
13
- class Error < Puppet::Util::Windows::Error; end
14
-
15
- class << self
16
- attr_accessor :com_initialized
17
- end
18
-
19
- # :stopdoc:
20
- TASK_TIME_TRIGGER_ONCE = :TASK_TIME_TRIGGER_ONCE
21
- TASK_TIME_TRIGGER_DAILY = :TASK_TIME_TRIGGER_DAILY
22
- TASK_TIME_TRIGGER_WEEKLY = :TASK_TIME_TRIGGER_WEEKLY
23
- TASK_TIME_TRIGGER_MONTHLYDATE = :TASK_TIME_TRIGGER_MONTHLYDATE
24
- TASK_TIME_TRIGGER_MONTHLYDOW = :TASK_TIME_TRIGGER_MONTHLYDOW
25
- TASK_EVENT_TRIGGER_ON_IDLE = :TASK_EVENT_TRIGGER_ON_IDLE
26
- TASK_EVENT_TRIGGER_AT_SYSTEMSTART = :TASK_EVENT_TRIGGER_AT_SYSTEMSTART
27
- TASK_EVENT_TRIGGER_AT_LOGON = :TASK_EVENT_TRIGGER_AT_LOGON
28
-
29
- TASK_SUNDAY = 0x1
30
- TASK_MONDAY = 0x2
31
- TASK_TUESDAY = 0x4
32
- TASK_WEDNESDAY = 0x8
33
- TASK_THURSDAY = 0x10
34
- TASK_FRIDAY = 0x20
35
- TASK_SATURDAY = 0x40
36
- TASK_FIRST_WEEK = 1
37
- TASK_SECOND_WEEK = 2
38
- TASK_THIRD_WEEK = 3
39
- TASK_FOURTH_WEEK = 4
40
- TASK_LAST_WEEK = 5
41
- TASK_JANUARY = 0x1
42
- TASK_FEBRUARY = 0x2
43
- TASK_MARCH = 0x4
44
- TASK_APRIL = 0x8
45
- TASK_MAY = 0x10
46
- TASK_JUNE = 0x20
47
- TASK_JULY = 0x40
48
- TASK_AUGUST = 0x80
49
- TASK_SEPTEMBER = 0x100
50
- TASK_OCTOBER = 0x200
51
- TASK_NOVEMBER = 0x400
52
- TASK_DECEMBER = 0x800
53
-
54
- TASK_FLAG_INTERACTIVE = 0x1
55
- TASK_FLAG_DELETE_WHEN_DONE = 0x2
56
- TASK_FLAG_DISABLED = 0x4
57
- TASK_FLAG_START_ONLY_IF_IDLE = 0x10
58
- TASK_FLAG_KILL_ON_IDLE_END = 0x20
59
- TASK_FLAG_DONT_START_IF_ON_BATTERIES = 0x40
60
- TASK_FLAG_KILL_IF_GOING_ON_BATTERIES = 0x80
61
- TASK_FLAG_RUN_ONLY_IF_DOCKED = 0x100
62
- TASK_FLAG_HIDDEN = 0x200
63
- TASK_FLAG_RUN_IF_CONNECTED_TO_INTERNET = 0x400
64
- TASK_FLAG_RESTART_ON_IDLE_RESUME = 0x800
65
- TASK_FLAG_SYSTEM_REQUIRED = 0x1000
66
- TASK_FLAG_RUN_ONLY_IF_LOGGED_ON = 0x2000
67
- TASK_TRIGGER_FLAG_HAS_END_DATE = 0x1
68
- TASK_TRIGGER_FLAG_KILL_AT_DURATION_END = 0x2
69
- TASK_TRIGGER_FLAG_DISABLED = 0x4
70
-
71
- TASK_MAX_RUN_TIMES = 1440
72
- TASKS_TO_RETRIEVE = 5
73
-
74
- # COM
75
-
76
- CLSID_CTask = FFI::WIN32::GUID['148BD520-A2AB-11CE-B11F-00AA00530503']
77
- IID_ITask = FFI::WIN32::GUID['148BD524-A2AB-11CE-B11F-00AA00530503']
78
- IID_IPersistFile = FFI::WIN32::GUID['0000010b-0000-0000-C000-000000000046']
79
-
80
- SCHED_S_TASK_READY = 0x00041300
81
- SCHED_S_TASK_RUNNING = 0x00041301
82
- SCHED_S_TASK_HAS_NOT_RUN = 0x00041303
83
- SCHED_S_TASK_NOT_SCHEDULED = 0x00041305
84
- # HRESULT error codes
85
- # https://blogs.msdn.com/b/eldar/archive/2007/04/03/a-lot-of-hresult-codes.aspx
86
- # in Ruby, an 0x8XXXXXXX style HRESULT can be resolved to 2s complement
87
- # by using "0x8XXXXXXX".to_i(16) - - 0x100000000
88
- SCHED_E_ACCOUNT_INFORMATION_NOT_SET = -2147216625 # 0x8004130F
89
- SCHED_E_NO_SECURITY_SERVICES = -2147216622 # 0x80041312
90
- # No mapping between account names and security IDs was done.
91
- ERROR_NONE_MAPPED = -2147023564 # 0x80070534 WIN32 Error CODE 1332 (0x534)
92
-
93
- # :startdoc:
94
-
95
- # Shorthand constants
96
- IDLE = Puppet::Util::Windows::Process::IDLE_PRIORITY_CLASS
97
- NORMAL = Puppet::Util::Windows::Process::NORMAL_PRIORITY_CLASS
98
- HIGH = Puppet::Util::Windows::Process::HIGH_PRIORITY_CLASS
99
- REALTIME = Puppet::Util::Windows::Process::REALTIME_PRIORITY_CLASS
100
- BELOW_NORMAL = Puppet::Util::Windows::Process::BELOW_NORMAL_PRIORITY_CLASS
101
- ABOVE_NORMAL = Puppet::Util::Windows::Process::ABOVE_NORMAL_PRIORITY_CLASS
102
-
103
- ONCE = TASK_TIME_TRIGGER_ONCE
104
- DAILY = TASK_TIME_TRIGGER_DAILY
105
- WEEKLY = TASK_TIME_TRIGGER_WEEKLY
106
- MONTHLYDATE = TASK_TIME_TRIGGER_MONTHLYDATE
107
- MONTHLYDOW = TASK_TIME_TRIGGER_MONTHLYDOW
108
-
109
- ON_IDLE = TASK_EVENT_TRIGGER_ON_IDLE
110
- AT_SYSTEMSTART = TASK_EVENT_TRIGGER_AT_SYSTEMSTART
111
- AT_LOGON = TASK_EVENT_TRIGGER_AT_LOGON
112
- FIRST_WEEK = TASK_FIRST_WEEK
113
- SECOND_WEEK = TASK_SECOND_WEEK
114
- THIRD_WEEK = TASK_THIRD_WEEK
115
- FOURTH_WEEK = TASK_FOURTH_WEEK
116
- LAST_WEEK = TASK_LAST_WEEK
117
- SUNDAY = TASK_SUNDAY
118
- MONDAY = TASK_MONDAY
119
- TUESDAY = TASK_TUESDAY
120
- WEDNESDAY = TASK_WEDNESDAY
121
- THURSDAY = TASK_THURSDAY
122
- FRIDAY = TASK_FRIDAY
123
- SATURDAY = TASK_SATURDAY
124
- JANUARY = TASK_JANUARY
125
- FEBRUARY = TASK_FEBRUARY
126
- MARCH = TASK_MARCH
127
- APRIL = TASK_APRIL
128
- MAY = TASK_MAY
129
- JUNE = TASK_JUNE
130
- JULY = TASK_JULY
131
- AUGUST = TASK_AUGUST
132
- SEPTEMBER = TASK_SEPTEMBER
133
- OCTOBER = TASK_OCTOBER
134
- NOVEMBER = TASK_NOVEMBER
135
- DECEMBER = TASK_DECEMBER
136
-
137
- INTERACTIVE = TASK_FLAG_INTERACTIVE
138
- DELETE_WHEN_DONE = TASK_FLAG_DELETE_WHEN_DONE
139
- DISABLED = TASK_FLAG_DISABLED
140
- START_ONLY_IF_IDLE = TASK_FLAG_START_ONLY_IF_IDLE
141
- KILL_ON_IDLE_END = TASK_FLAG_KILL_ON_IDLE_END
142
- DONT_START_IF_ON_BATTERIES = TASK_FLAG_DONT_START_IF_ON_BATTERIES
143
- KILL_IF_GOING_ON_BATTERIES = TASK_FLAG_KILL_IF_GOING_ON_BATTERIES
144
- RUN_ONLY_IF_DOCKED = TASK_FLAG_RUN_ONLY_IF_DOCKED
145
- HIDDEN = TASK_FLAG_HIDDEN
146
- RUN_IF_CONNECTED_TO_INTERNET = TASK_FLAG_RUN_IF_CONNECTED_TO_INTERNET
147
- RESTART_ON_IDLE_RESUME = TASK_FLAG_RESTART_ON_IDLE_RESUME
148
- SYSTEM_REQUIRED = TASK_FLAG_SYSTEM_REQUIRED
149
- RUN_ONLY_IF_LOGGED_ON = TASK_FLAG_RUN_ONLY_IF_LOGGED_ON
150
-
151
- FLAG_HAS_END_DATE = TASK_TRIGGER_FLAG_HAS_END_DATE
152
- FLAG_KILL_AT_DURATION_END = TASK_TRIGGER_FLAG_KILL_AT_DURATION_END
153
- FLAG_DISABLED = TASK_TRIGGER_FLAG_DISABLED
154
-
155
- MAX_RUN_TIMES = TASK_MAX_RUN_TIMES
156
-
157
- # unfortunately MSTask.h does not specify the limits for any settings
158
- # so these were determined with some experimentation
159
- # if values too large are written, its suspected there may be internal
160
- # limits may be exceeded, corrupting the job
161
- # used for max application name and path values
162
- MAX_PATH = 260
163
- # UNLEN from lmcons.h is 256
164
- # https://technet.microsoft.com/it-it/library/bb726984(en-us).aspx specifies 104
165
- MAX_ACCOUNT_LENGTH = 256
166
- # command line max length is limited to 8191, choose something high but still enough that we don't blow out CLI
167
- MAX_PARAMETERS_LENGTH = 4096
168
- # in testing, this value could be set to a length of 99999, but saving / loading the task failed
169
- MAX_COMMENT_LENGTH = 8192
170
-
171
- # Returns a new TaskScheduler object. If a work_item (and possibly the
172
- # the trigger) are passed as arguments then a new work item is created and
173
- # associated with that trigger, although you can still activate other tasks
174
- # with the same handle.
175
- #
176
- # This is really just a bit of convenience. Passing arguments to the
177
- # constructor is the same as calling TaskScheduler.new plus
178
- # TaskScheduler#new_work_item.
179
- #
180
- def initialize(work_item=nil, trigger=nil)
181
- @pITS = nil
182
- @pITask = nil
183
-
184
- if ! self.class.com_initialized
185
- Puppet::Util::Windows::COM.InitializeCom()
186
- self.class.com_initialized = true
187
- end
188
-
189
- @pITS = COM::TaskScheduler.new
190
- at_exit do
191
- begin
192
- @pITS.Release if @pITS && !@pITS.null?
193
- @pITS = nil
194
- rescue
195
- end
196
- end
197
-
198
- if work_item
199
- if trigger
200
- raise TypeError unless trigger.is_a?(Hash)
201
- new_work_item(work_item, trigger)
202
- end
203
- end
204
- end
205
-
206
- # Returns an array of scheduled task names.
207
- #
208
- def enum
209
- raise Error.new(_('No current task scheduler. ITaskScheduler is NULL.')) if @pITS.nil?
210
- array = []
211
-
212
- @pITS.UseInstance(COM::EnumWorkItems, :Enum) do |pIEnum|
213
- FFI::MemoryPointer.new(:pointer) do |names_array_ptr_ptr|
214
- FFI::MemoryPointer.new(:win32_ulong) do |fetched_count_ptr|
215
- # awkward usage, if number requested is available, returns S_OK (0), or if less were returned returns S_FALSE (1)
216
- while (pIEnum.Next(TASKS_TO_RETRIEVE, names_array_ptr_ptr, fetched_count_ptr) >= Puppet::Util::Windows::COM::S_OK)
217
- count = fetched_count_ptr.read_win32_ulong
218
- break if count == 0
219
-
220
- names_array_ptr_ptr.read_com_memory_pointer do |names_array_ptr|
221
- # iterate over the array of pointers
222
- name_ptr_ptr = FFI::Pointer.new(:pointer, names_array_ptr)
223
- for i in 0 ... count
224
- name_ptr_ptr[i].read_com_memory_pointer do |name_ptr|
225
- array << name_ptr.read_arbitrary_wide_string_up_to(MAX_PATH)
226
- end
227
- end
228
- end
229
- end
230
- end
231
- end
232
- end
233
-
234
- array
235
- end
236
-
237
- alias :tasks :enum
238
-
239
- # Activate the specified task.
240
- #
241
- def activate(task)
242
- raise Error.new(_('No current task scheduler. ITaskScheduler is NULL.')) if @pITS.nil?
243
- raise TypeError unless task.is_a?(String)
244
-
245
- FFI::MemoryPointer.new(:pointer) do |ptr|
246
- @pITS.Activate(wide_string(task), IID_ITask, ptr)
247
-
248
- reset_current_task
249
- @pITask = COM::Task.new(ptr.read_pointer)
250
- end
251
-
252
- @pITask
253
- end
254
-
255
- # Delete the specified task name.
256
- #
257
- def delete(task)
258
- raise Error.new(_('No current task scheduler. ITaskScheduler is NULL.')) if @pITS.nil?
259
- raise TypeError unless task.is_a?(String)
260
-
261
- @pITS.Delete(wide_string(task))
262
-
263
- true
264
- end
265
-
266
- # Execute the current task.
267
- #
268
- def run
269
- raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
270
-
271
- @pITask.Run
272
- end
273
-
274
- # Saves the current task. Tasks must be saved before they can be activated.
275
- # The .job file itself is typically stored in the C:\WINDOWS\Tasks folder.
276
- #
277
- # If +file+ (an absolute path) is specified then the job is saved to that
278
- # file instead. A '.job' extension is recommended but not enforced.
279
- #
280
- def save(file = nil)
281
- raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
282
- raise Error.new(_('Account information must be set on the current task to save it properly.')) if !@account_information_set
283
-
284
- reset = true
285
-
286
- begin
287
- @pITask.QueryInstance(COM::PersistFile) do |pIPersistFile|
288
- wide_file = wide_string(file)
289
- pIPersistFile.Save(wide_file, 1)
290
- pIPersistFile.SaveCompleted(wide_file)
291
- end
292
- rescue
293
- reset = false
294
- ensure
295
- reset_current_task if reset
296
- end
297
- end
298
-
299
- # Terminate the current task.
300
- #
301
- def terminate
302
- raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
303
-
304
- @pITask.Terminate
305
- end
306
-
307
- # Set the host on which the various TaskScheduler methods will execute.
308
- #
309
- def machine=(host)
310
- raise Error.new(_('No current task scheduler. ITaskScheduler is NULL.')) if @pITS.nil?
311
- raise TypeError unless host.is_a?(String)
312
-
313
- @pITS.SetTargetComputer(wide_string(host))
314
-
315
- host
316
- end
317
-
318
- alias :host= :machine=
319
-
320
- # Sets the +user+ and +password+ for the given task. If the user and
321
- # password are set properly then true is returned.
322
- #
323
- # In some cases the job may be created, but the account information was
324
- # bad. In this case the task is created but a warning is generated and
325
- # false is returned.
326
- #
327
- # Note that if intending to use SYSTEM, specify an empty user and nil password
328
- #
329
- # Calling task.set_account_information('SYSTEM', nil) will generally not
330
- # work, except for one special case where flags are also set like:
331
- # task.flags = Win32::TaskScheduler::TASK_FLAG_RUN_ONLY_IF_LOGGED_ON
332
- #
333
- # This must be done prior to the 1st save() call for the task to be
334
- # properly registered and visible through the MMC snap-in / schtasks.exe
335
- #
336
- def set_account_information(user, password)
337
- raise Error.new(_('No current task scheduler. ITaskScheduler is NULL.')) if @pITS.nil?
338
- raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
339
-
340
- bool = false
341
-
342
- begin
343
- if (user.nil? || user=="") && (password.nil? || password=="")
344
- @pITask.SetAccountInformation(wide_string(""), FFI::Pointer::NULL)
345
- else
346
- if user.length > MAX_ACCOUNT_LENGTH
347
- raise Error.new(_("User has exceeded maximum allowed length %{max}") % { max: MAX_ACCOUNT_LENGTH })
348
- end
349
- user = wide_string(user)
350
- password = wide_string(password)
351
- @pITask.SetAccountInformation(user, password)
352
- end
353
-
354
- @account_information_set = true
355
- bool = true
356
- rescue Puppet::Util::Windows::Error => e
357
- raise e unless e.code == SCHED_E_ACCOUNT_INFORMATION_NOT_SET
358
-
359
- warn _('job created, but password was invalid')
360
- end
361
-
362
- bool
363
- end
364
-
365
- # Returns the user associated with the task or nil if no user has yet
366
- # been associated with the task.
367
- #
368
- def account_information
369
- raise Error.new(_('No current task scheduler. ITaskScheduler is NULL.')) if @pITS.nil?
370
- raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
371
-
372
- # default under certain failures
373
- user = nil
374
-
375
- begin
376
- FFI::MemoryPointer.new(:pointer) do |ptr|
377
- @pITask.GetAccountInformation(ptr)
378
- ptr.read_com_memory_pointer do |str_ptr|
379
- user = str_ptr.read_arbitrary_wide_string_up_to(MAX_ACCOUNT_LENGTH) if ! str_ptr.null?
380
- end
381
- end
382
- rescue Puppet::Util::Windows::Error => e
383
- raise e unless e.code == SCHED_E_ACCOUNT_INFORMATION_NOT_SET ||
384
- e.code == SCHED_E_NO_SECURITY_SERVICES ||
385
- e.code == ERROR_NONE_MAPPED
386
- end
387
-
388
- user
389
- end
390
-
391
- # Returns the name of the application associated with the task.
392
- #
393
- def application_name
394
- raise Error.new(_('No current task scheduler. ITaskScheduler is NULL.')) if @pITS.nil?
395
- raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
396
-
397
- app = nil
398
-
399
- FFI::MemoryPointer.new(:pointer) do |ptr|
400
- @pITask.GetApplicationName(ptr)
401
-
402
- ptr.read_com_memory_pointer do |str_ptr|
403
- app = str_ptr.read_arbitrary_wide_string_up_to(MAX_PATH) if ! str_ptr.null?
404
- end
405
- end
406
-
407
- app
408
- end
409
-
410
- # Sets the application name associated with the task.
411
- #
412
- def application_name=(app)
413
- raise Error.new(_('No current task scheduler. ITaskScheduler is NULL.')) if @pITS.nil?
414
- raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
415
- raise TypeError unless app.is_a?(String)
416
-
417
- # the application name is written to a .job file on disk, so is subject to path limitations
418
- if app.length > MAX_PATH
419
- raise Error.new(_("Application name has exceeded maximum allowed length %{max}") % { max: MAX_PATH })
420
- end
421
- @pITask.SetApplicationName(wide_string(app))
422
-
423
- app
424
- end
425
-
426
- # Returns the command line parameters for the task.
427
- #
428
- def parameters
429
- raise Error.new(_('No current task scheduler. ITaskScheduler is NULL.')) if @pITS.nil?
430
- raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
431
-
432
- param = nil
433
-
434
- FFI::MemoryPointer.new(:pointer) do |ptr|
435
- @pITask.GetParameters(ptr)
436
-
437
- ptr.read_com_memory_pointer do |str_ptr|
438
- param = str_ptr.read_arbitrary_wide_string_up_to(MAX_PARAMETERS_LENGTH) if ! str_ptr.null?
439
- end
440
- end
441
-
442
- param
443
- end
444
-
445
- # Sets the parameters for the task. These parameters are passed as command
446
- # line arguments to the application the task will run. To clear the command
447
- # line parameters set it to an empty string.
448
- #
449
- def parameters=(param)
450
- raise Error.new(_('No current task scheduler. ITaskScheduler is NULL.')) if @pITS.nil?
451
- raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
452
- raise TypeError unless param.is_a?(String)
453
-
454
- if param.length > MAX_PARAMETERS_LENGTH
455
- raise Error.new(_("Parameters has exceeded maximum allowed length %{max}") % { max: MAX_PARAMETERS_LENGTH })
456
- end
457
-
458
- @pITask.SetParameters(wide_string(param))
459
-
460
- param
461
- end
462
-
463
- # Returns the working directory for the task.
464
- #
465
- def working_directory
466
- raise Error.new(_('No current task scheduler. ITaskScheduler is NULL.')) if @pITS.nil?
467
- raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
468
-
469
- dir = nil
470
-
471
- FFI::MemoryPointer.new(:pointer) do |ptr|
472
- @pITask.GetWorkingDirectory(ptr)
473
-
474
- ptr.read_com_memory_pointer do |str_ptr|
475
- dir = str_ptr.read_arbitrary_wide_string_up_to(MAX_PATH) if ! str_ptr.null?
476
- end
477
- end
478
-
479
- dir
480
- end
481
-
482
- # Sets the working directory for the task.
483
- #
484
- def working_directory=(dir)
485
- raise Error.new(_('No current task scheduler. ITaskScheduler is NULL.')) if @pITS.nil?
486
- raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
487
- raise TypeError unless dir.is_a?(String)
488
-
489
- if dir.length > MAX_PATH
490
- raise Error.new(_("Working directory has exceeded maximum allowed length %{max}") % { max: MAX_PATH })
491
- end
492
-
493
- @pITask.SetWorkingDirectory(wide_string(dir))
494
-
495
- dir
496
- end
497
-
498
- # Returns the task's priority level. Possible values are 'idle',
499
- # 'normal', 'high', 'realtime', 'below_normal', 'above_normal',
500
- # and 'unknown'.
501
- #
502
- def priority
503
- raise Error.new(_('No current task scheduler. ITaskScheduler is NULL.')) if @pITS.nil?
504
- raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
505
-
506
- priority_name = ''
507
-
508
- FFI::MemoryPointer.new(:dword, 1) do |ptr|
509
- @pITask.GetPriority(ptr)
510
-
511
- pri = ptr.read_dword
512
- if (pri & IDLE) != 0
513
- priority_name = 'idle'
514
- elsif (pri & NORMAL) != 0
515
- priority_name = 'normal'
516
- elsif (pri & HIGH) != 0
517
- priority_name = 'high'
518
- elsif (pri & REALTIME) != 0
519
- priority_name = 'realtime'
520
- elsif (pri & BELOW_NORMAL) != 0
521
- priority_name = 'below_normal'
522
- elsif (pri & ABOVE_NORMAL) != 0
523
- priority_name = 'above_normal'
524
- else
525
- priority_name = 'unknown'
526
- end
527
- end
528
-
529
- priority_name
530
- end
531
-
532
- # Sets the priority of the task. The +priority+ should be a numeric
533
- # priority constant value.
534
- #
535
- def priority=(priority)
536
- raise Error.new(_('No current task scheduler. ITaskScheduler is NULL.')) if @pITS.nil?
537
- raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
538
- raise TypeError unless priority.is_a?(Numeric)
539
-
540
- @pITask.SetPriority(priority)
541
-
542
- priority
543
- end
544
-
545
- # Creates a new work item (scheduled job) with the given +trigger+. The
546
- # trigger variable is a hash of options that define when the scheduled
547
- # job should run.
548
- #
549
- def new_work_item(task, trigger)
550
- raise TypeError unless trigger.is_a?(Hash)
551
- raise Error.new(_('No current task scheduler. ITaskScheduler is NULL.')) if @pITS.nil?
552
-
553
- # I'm working around github issue #1 here.
554
- enum.each{ |name|
555
- if name.downcase == task.downcase + '.job'
556
- raise Error.new(_("task '%{task}' already exists") % { task: task })
557
- end
558
- }
559
-
560
- FFI::MemoryPointer.new(:pointer) do |ptr|
561
- @pITS.NewWorkItem(wide_string(task), CLSID_CTask, IID_ITask, ptr)
562
-
563
- reset_current_task
564
- @pITask = COM::Task.new(ptr.read_pointer)
565
-
566
- FFI::MemoryPointer.new(:word, 1) do |trigger_index_ptr|
567
- # Without the 'enum.include?' check above the code segfaults here if the
568
- # task already exists. This should probably be handled properly instead
569
- # of simply avoiding the issue.
570
-
571
- @pITask.UseInstance(COM::TaskTrigger, :CreateTrigger, trigger_index_ptr) do |pITaskTrigger|
572
- populate_trigger(pITaskTrigger, trigger)
573
- end
574
- end
575
- end
576
-
577
- # preload task with the SYSTEM account
578
- # empty string '' means 'SYSTEM' per MSDN, so default it
579
- # given an account is necessary for creation of a task
580
- # note that a user may set SYSTEM explicitly, but that has problems
581
- # https://msdn.microsoft.com/en-us/library/windows/desktop/aa381276(v=vs.85).aspx
582
- set_account_information('', nil)
583
-
584
- @pITask
585
- end
586
-
587
- alias :new_task :new_work_item
588
-
589
- # Returns the number of triggers associated with the active task.
590
- #
591
- def trigger_count
592
- raise Error.new(_('No current task scheduler. ITaskScheduler is NULL.')) if @pITS.nil?
593
- raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
594
-
595
- count = 0
596
-
597
- FFI::MemoryPointer.new(:word, 1) do |ptr|
598
- @pITask.GetTriggerCount(ptr)
599
- count = ptr.read_word
600
- end
601
-
602
- count
603
- end
604
-
605
- # Deletes the trigger at the specified index.
606
- #
607
- def delete_trigger(index)
608
- raise Error.new(_('No current task scheduler. ITaskScheduler is NULL.')) if @pITS.nil?
609
- raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
610
-
611
- @pITask.DeleteTrigger(index)
612
- index
613
- end
614
-
615
- # Returns a hash that describes the trigger at the given index for the
616
- # current task.
617
- #
618
- def trigger(index)
619
- raise Error.new(_('No current task scheduler. ITaskScheduler is NULL.')) if @pITS.nil?
620
- raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
621
-
622
- trigger = {}
623
-
624
- @pITask.UseInstance(COM::TaskTrigger, :GetTrigger, index) do |pITaskTrigger|
625
- FFI::MemoryPointer.new(COM::TASK_TRIGGER.size) do |task_trigger_ptr|
626
- pITaskTrigger.GetTrigger(task_trigger_ptr)
627
- trigger = populate_hash_from_trigger(COM::TASK_TRIGGER.new(task_trigger_ptr))
628
- end
629
- end
630
-
631
- trigger
632
- end
633
-
634
- # Sets the trigger for the currently active task.
635
- #
636
- def trigger=(trigger)
637
- raise Error.new(_('No current task scheduler. ITaskScheduler is NULL.')) if @pITS.nil?
638
- raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
639
- raise TypeError unless trigger.is_a?(Hash)
640
-
641
- FFI::MemoryPointer.new(:word, 1) do |trigger_index_ptr|
642
- # Without the 'enum.include?' check above the code segfaults here if the
643
- # task already exists. This should probably be handled properly instead
644
- # of simply avoiding the issue.
645
-
646
- @pITask.UseInstance(COM::TaskTrigger, :CreateTrigger, trigger_index_ptr) do |pITaskTrigger|
647
- populate_trigger(pITaskTrigger, trigger)
648
- end
649
- end
650
-
651
- trigger
652
- end
653
-
654
- # Adds a trigger at the specified index.
655
- #
656
- def add_trigger(index, trigger)
657
- raise Error.new(_('No current task scheduler. ITaskScheduler is NULL.')) if @pITS.nil?
658
- raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
659
- raise TypeError unless trigger.is_a?(Hash)
660
-
661
- @pITask.UseInstance(COM::TaskTrigger, :GetTrigger, index) do |pITaskTrigger|
662
- populate_trigger(pITaskTrigger, trigger)
663
- end
664
- end
665
-
666
- # Returns the flags (integer) that modify the behavior of the work item. You
667
- # must OR the return value to determine the flags yourself.
668
- #
669
- def flags
670
- raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
671
-
672
- flags = 0
673
-
674
- FFI::MemoryPointer.new(:dword, 1) do |ptr|
675
- @pITask.GetFlags(ptr)
676
- flags = ptr.read_dword
677
- end
678
-
679
- flags
680
- end
681
-
682
- # Sets an OR'd value of flags that modify the behavior of the work item.
683
- #
684
- def flags=(flags)
685
- raise Error.new(_('No current task scheduler. ITaskScheduler is NULL.')) if @pITS.nil?
686
- raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
687
-
688
- @pITask.SetFlags(flags)
689
- flags
690
- end
691
-
692
- # Returns the status of the currently active task. Possible values are
693
- # 'ready', 'running', 'not scheduled' or 'unknown'.
694
- #
695
- def status
696
- raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
697
-
698
- st = nil
699
-
700
- FFI::MemoryPointer.new(:hresult, 1) do |ptr|
701
- @pITask.GetStatus(ptr)
702
- st = ptr.read_hresult
703
- end
704
-
705
- case st
706
- when SCHED_S_TASK_READY
707
- status = 'ready'
708
- when SCHED_S_TASK_RUNNING
709
- status = 'running'
710
- when SCHED_S_TASK_NOT_SCHEDULED
711
- status = 'not scheduled'
712
- else
713
- status = 'unknown'
714
- end
715
-
716
- status
717
- end
718
-
719
- # Returns the exit code from the last scheduled run.
720
- #
721
- def exit_code
722
- raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
723
-
724
- status = 0
725
-
726
- begin
727
- FFI::MemoryPointer.new(:dword, 1) do |ptr|
728
- @pITask.GetExitCode(ptr)
729
- status = ptr.read_dword
730
- end
731
- rescue Puppet::Util::Windows::Error => e
732
- raise e unless e.code == SCHED_S_TASK_HAS_NOT_RUN
733
- end
734
-
735
- status
736
- end
737
-
738
- # Returns the comment associated with the task, if any.
739
- #
740
- def comment
741
- raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
742
-
743
- comment = nil
744
-
745
- FFI::MemoryPointer.new(:pointer) do |ptr|
746
- @pITask.GetComment(ptr)
747
-
748
- ptr.read_com_memory_pointer do |str_ptr|
749
- comment = str_ptr.read_arbitrary_wide_string_up_to(MAX_COMMENT_LENGTH) if ! str_ptr.null?
750
- end
751
- end
752
-
753
- comment
754
- end
755
-
756
- # Sets the comment for the task.
757
- #
758
- def comment=(comment)
759
- raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
760
- raise TypeError unless comment.is_a?(String)
761
-
762
- if comment.length > MAX_COMMENT_LENGTH
763
- raise Error.new(_("Comment has exceeded maximum allowed length %{max}") % { max: MAX_COMMENT_LENGTH })
764
- end
765
-
766
- @pITask.SetComment(wide_string(comment))
767
- comment
768
- end
769
-
770
- # Returns the name of the user who created the task.
771
- #
772
- def creator
773
- raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
774
-
775
- creator = nil
776
-
777
- FFI::MemoryPointer.new(:pointer) do |ptr|
778
- @pITask.GetCreator(ptr)
779
-
780
- ptr.read_com_memory_pointer do |str_ptr|
781
- creator = str_ptr.read_arbitrary_wide_string_up_to(MAX_ACCOUNT_LENGTH) if ! str_ptr.null?
782
- end
783
- end
784
-
785
- creator
786
- end
787
-
788
- # Sets the creator for the task.
789
- #
790
- def creator=(creator)
791
- raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
792
- raise TypeError unless creator.is_a?(String)
793
-
794
- if creator.length > MAX_ACCOUNT_LENGTH
795
- raise Error.new(_("Creator has exceeded maximum allowed length %{max}") % { max: MAX_ACCOUNT_LENGTH })
796
- end
797
-
798
-
799
- @pITask.SetCreator(wide_string(creator))
800
- creator
801
- end
802
-
803
- # Returns a Time object that indicates the next time the task will run.
804
- #
805
- def next_run_time
806
- raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
807
-
808
- time = nil
809
-
810
- FFI::MemoryPointer.new(WIN32::SYSTEMTIME.size) do |ptr|
811
- @pITask.GetNextRunTime(ptr)
812
- time = WIN32::SYSTEMTIME.new(ptr).to_local_time
813
- end
814
-
815
- time
816
- end
817
-
818
- # Returns a Time object indicating the most recent time the task ran or
819
- # nil if the task has never run.
820
- #
821
- def most_recent_run_time
822
- raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
823
-
824
- time = nil
825
-
826
- begin
827
- FFI::MemoryPointer.new(WIN32::SYSTEMTIME.size) do |ptr|
828
- @pITask.GetMostRecentRunTime(ptr)
829
- time = WIN32::SYSTEMTIME.new(ptr).to_local_time
830
- end
831
- rescue Puppet::Util::Windows::Error => e
832
- raise e unless e.code == SCHED_S_TASK_HAS_NOT_RUN
833
- end
834
-
835
- time
836
- end
837
-
838
- # Returns the maximum length of time, in milliseconds, that the task
839
- # will run before terminating.
840
- #
841
- def max_run_time
842
- raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
843
-
844
- max_run_time = nil
845
-
846
- FFI::MemoryPointer.new(:dword, 1) do |ptr|
847
- @pITask.GetMaxRunTime(ptr)
848
- max_run_time = ptr.read_dword
849
- end
850
-
851
- max_run_time
852
- end
853
-
854
- # Sets the maximum length of time, in milliseconds, that the task can run
855
- # before terminating. Returns the value you specified if successful.
856
- #
857
- def max_run_time=(max_run_time)
858
- raise Error.new(_('No currently active task. ITask is NULL.')) if @pITask.nil?
859
- raise TypeError unless max_run_time.is_a?(Numeric)
860
-
861
- @pITask.SetMaxRunTime(max_run_time)
862
- max_run_time
863
- end
864
-
865
- # Returns whether or not the scheduled task exists.
866
- def exists?(job_name)
867
- # task name comparison is case insensitive
868
- tasks.any? { |name| name.casecmp(job_name + '.job') == 0 }
869
- end
870
-
871
- private
872
-
873
- # :stopdoc:
874
-
875
- # Used for the new_work_item method
876
- ValidTriggerKeys = [
877
- 'end_day',
878
- 'end_month',
879
- 'end_year',
880
- 'flags',
881
- 'minutes_duration',
882
- 'minutes_interval',
883
- 'random_minutes_interval',
884
- 'start_day',
885
- 'start_hour',
886
- 'start_minute',
887
- 'start_month',
888
- 'start_year',
889
- 'trigger_type',
890
- 'type'
891
- ]
892
-
893
- ValidTypeKeys = [
894
- 'days_interval',
895
- 'weeks_interval',
896
- 'days_of_week',
897
- 'months',
898
- 'days',
899
- 'weeks'
900
- ]
901
-
902
- # Private method that validates keys, and converts all keys to lowercase
903
- # strings.
904
- #
905
- def transform_and_validate(hash)
906
- new_hash = {}
907
-
908
- hash.each{ |key, value|
909
- key = key.to_s.downcase
910
- if key == 'type'
911
- new_type_hash = {}
912
- raise ArgumentError unless value.is_a?(Hash)
913
- value.each{ |subkey, subvalue|
914
- subkey = subkey.to_s.downcase
915
- if ValidTypeKeys.include?(subkey)
916
- new_type_hash[subkey] = subvalue
917
- else
918
- raise ArgumentError, _("Invalid type key '%{key}'") % { key: subkey }
919
- end
920
- }
921
- new_hash[key] = new_type_hash
922
- else
923
- if ValidTriggerKeys.include?(key)
924
- new_hash[key] = value
925
- else
926
- raise ArgumentError, _("Invalid key '%{key}'") % { key: key }
927
- end
928
- end
929
- }
930
-
931
- new_hash
932
- end
933
-
934
- def reset_current_task
935
- # Ensure that COM reference is decremented properly
936
- @pITask.Release if @pITask && ! @pITask.null?
937
- @pITask = nil
938
- @account_information_set = false
939
- end
940
-
941
- def populate_trigger(task_trigger, trigger)
942
- raise TypeError unless task_trigger.is_a?(COM::TaskTrigger)
943
- trigger = transform_and_validate(trigger)
944
-
945
- FFI::MemoryPointer.new(COM::TASK_TRIGGER.size) do |trigger_ptr|
946
- FFI::MemoryPointer.new(COM::TRIGGER_TYPE_UNION.size) do |trigger_type_union_ptr|
947
- trigger_type_union = COM::TRIGGER_TYPE_UNION.new(trigger_type_union_ptr)
948
-
949
- tmp = trigger['type'].is_a?(Hash) ? trigger['type'] : nil
950
- case trigger['trigger_type']
951
- when :TASK_TIME_TRIGGER_DAILY
952
- if tmp && tmp['days_interval']
953
- trigger_type_union[:Daily][:DaysInterval] = tmp['days_interval']
954
- end
955
- when :TASK_TIME_TRIGGER_WEEKLY
956
- if tmp && tmp['weeks_interval'] && tmp['days_of_week']
957
- trigger_type_union[:Weekly][:WeeksInterval] = tmp['weeks_interval']
958
- trigger_type_union[:Weekly][:rgfDaysOfTheWeek] = tmp['days_of_week']
959
- end
960
- when :TASK_TIME_TRIGGER_MONTHLYDATE
961
- if tmp && tmp['months'] && tmp['days']
962
- trigger_type_union[:MonthlyDate][:rgfDays] = tmp['days']
963
- trigger_type_union[:MonthlyDate][:rgfMonths] = tmp['months']
964
- end
965
- when :TASK_TIME_TRIGGER_MONTHLYDOW
966
- if tmp && tmp['weeks'] && tmp['days_of_week'] && tmp['months']
967
- trigger_type_union[:MonthlyDOW][:wWhichWeek] = tmp['weeks']
968
- trigger_type_union[:MonthlyDOW][:rgfDaysOfTheWeek] = tmp['days_of_week']
969
- trigger_type_union[:MonthlyDOW][:rgfMonths] = tmp['months']
970
- end
971
- when :TASK_TIME_TRIGGER_ONCE
972
- # Do nothing. The Type member of the TASK_TRIGGER struct is ignored.
973
- else
974
- raise Error.new(_("Unknown trigger type %{type}") % { type: trigger['trigger_type'] })
975
- end
976
-
977
- trigger_struct = COM::TASK_TRIGGER.new(trigger_ptr)
978
- trigger_struct[:cbTriggerSize] = COM::TASK_TRIGGER.size
979
- now = Time.now
980
- trigger_struct[:wBeginYear] = trigger['start_year'] || now.year
981
- trigger_struct[:wBeginMonth] = trigger['start_month'] || now.month
982
- trigger_struct[:wBeginDay] = trigger['start_day'] || now.day
983
- trigger_struct[:wEndYear] = trigger['end_year'] || 0
984
- trigger_struct[:wEndMonth] = trigger['end_month'] || 0
985
- trigger_struct[:wEndDay] = trigger['end_day'] || 0
986
- trigger_struct[:wStartHour] = trigger['start_hour'] || 0
987
- trigger_struct[:wStartMinute] = trigger['start_minute'] || 0
988
- trigger_struct[:MinutesDuration] = trigger['minutes_duration'] || 0
989
- trigger_struct[:MinutesInterval] = trigger['minutes_interval'] || 0
990
- trigger_struct[:rgFlags] = trigger['flags'] || 0
991
- trigger_struct[:TriggerType] = trigger['trigger_type'] || :TASK_TIME_TRIGGER_ONCE
992
- trigger_struct[:Type] = trigger_type_union
993
- trigger_struct[:wRandomMinutesInterval] = trigger['random_minutes_interval'] || 0
994
-
995
- task_trigger.SetTrigger(trigger_struct)
996
- end
997
- end
998
- end
999
-
1000
- def populate_hash_from_trigger(task_trigger)
1001
- raise TypeError unless task_trigger.is_a?(COM::TASK_TRIGGER)
1002
-
1003
- trigger = {
1004
- 'start_year' => task_trigger[:wBeginYear],
1005
- 'start_month' => task_trigger[:wBeginMonth],
1006
- 'start_day' => task_trigger[:wBeginDay],
1007
- 'end_year' => task_trigger[:wEndYear],
1008
- 'end_month' => task_trigger[:wEndMonth],
1009
- 'end_day' => task_trigger[:wEndDay],
1010
- 'start_hour' => task_trigger[:wStartHour],
1011
- 'start_minute' => task_trigger[:wStartMinute],
1012
- 'minutes_duration' => task_trigger[:MinutesDuration],
1013
- 'minutes_interval' => task_trigger[:MinutesInterval],
1014
- 'flags' => task_trigger[:rgFlags],
1015
- 'trigger_type' => task_trigger[:TriggerType],
1016
- 'random_minutes_interval' => task_trigger[:wRandomMinutesInterval]
1017
- }
1018
-
1019
- case task_trigger[:TriggerType]
1020
- when :TASK_TIME_TRIGGER_DAILY
1021
- trigger['type'] = { 'days_interval' => task_trigger[:Type][:Daily][:DaysInterval] }
1022
- when :TASK_TIME_TRIGGER_WEEKLY
1023
- trigger['type'] = {
1024
- 'weeks_interval' => task_trigger[:Type][:Weekly][:WeeksInterval],
1025
- 'days_of_week' => task_trigger[:Type][:Weekly][:rgfDaysOfTheWeek]
1026
- }
1027
- when :TASK_TIME_TRIGGER_MONTHLYDATE
1028
- trigger['type'] = {
1029
- 'days' => task_trigger[:Type][:MonthlyDate][:rgfDays],
1030
- 'months' => task_trigger[:Type][:MonthlyDate][:rgfMonths]
1031
- }
1032
- when :TASK_TIME_TRIGGER_MONTHLYDOW
1033
- trigger['type'] = {
1034
- 'weeks' => task_trigger[:Type][:MonthlyDOW][:wWhichWeek],
1035
- 'days_of_week' => task_trigger[:Type][:MonthlyDOW][:rgfDaysOfTheWeek],
1036
- 'months' => task_trigger[:Type][:MonthlyDOW][:rgfMonths]
1037
- }
1038
- when :TASK_TIME_TRIGGER_ONCE
1039
- trigger['type'] = { 'once' => nil }
1040
- else
1041
- raise Error.new(_("Unknown trigger type %{type}") % { type: task_trigger[:TriggerType] })
1042
- end
1043
-
1044
- trigger
1045
- end
1046
-
1047
- module COM
1048
- extend FFI::Library
1049
-
1050
- com = Puppet::Util::Windows::COM
1051
-
1052
- # https://msdn.microsoft.com/en-us/library/windows/desktop/aa381811(v=vs.85).aspx
1053
- ITaskScheduler = com::Interface[com::IUnknown,
1054
- FFI::WIN32::GUID['148BD527-A2AB-11CE-B11F-00AA00530503'],
1055
-
1056
- SetTargetComputer: [[:lpcwstr], :hresult],
1057
- # LPWSTR *
1058
- GetTargetComputer: [[:pointer], :hresult],
1059
- # IEnumWorkItems **
1060
- Enum: [[:pointer], :hresult],
1061
- # LPCWSTR, REFIID, IUnknown **
1062
- Activate: [[:lpcwstr, :pointer, :pointer], :hresult],
1063
- Delete: [[:lpcwstr], :hresult],
1064
- # LPCWSTR, REFCLSID, REFIID, IUnknown **
1065
- NewWorkItem: [[:lpcwstr, :pointer, :pointer, :pointer], :hresult],
1066
- # LPCWSTR, IScheduledWorkItem *
1067
- AddWorkItem: [[:lpcwstr, :pointer], :hresult],
1068
- # LPCWSTR, REFIID
1069
- IsOfType: [[:lpcwstr, :pointer], :hresult]
1070
- ]
1071
-
1072
- TaskScheduler = com::Factory[ITaskScheduler,
1073
- FFI::WIN32::GUID['148BD52A-A2AB-11CE-B11F-00AA00530503']]
1074
-
1075
- # https://msdn.microsoft.com/en-us/library/windows/desktop/aa380706(v=vs.85).aspx
1076
- IEnumWorkItems = com::Interface[com::IUnknown,
1077
- FFI::WIN32::GUID['148BD528-A2AB-11CE-B11F-00AA00530503'],
1078
-
1079
- # ULONG, LPWSTR **, ULONG *
1080
- Next: [[:win32_ulong, :pointer, :pointer], :hresult],
1081
- Skip: [[:win32_ulong], :hresult],
1082
- Reset: [[], :hresult],
1083
- # IEnumWorkItems ** ppEnumWorkItems
1084
- Clone: [[:pointer], :hresult]
1085
- ]
1086
-
1087
- EnumWorkItems = com::Instance[IEnumWorkItems]
1088
-
1089
- # https://msdn.microsoft.com/en-us/library/windows/desktop/aa381216(v=vs.85).aspx
1090
- IScheduledWorkItem = com::Interface[com::IUnknown,
1091
- FFI::WIN32::GUID['a6b952f0-a4b1-11d0-997d-00aa006887ec'],
1092
-
1093
- # WORD *, ITaskTrigger **
1094
- CreateTrigger: [[:pointer, :pointer], :hresult],
1095
- DeleteTrigger: [[:word], :hresult],
1096
- # WORD *
1097
- GetTriggerCount: [[:pointer], :hresult],
1098
- # WORD, ITaskTrigger **
1099
- GetTrigger: [[:word, :pointer], :hresult],
1100
- # WORD, LPWSTR *
1101
- GetTriggerString: [[:word, :pointer], :hresult],
1102
- # LPSYSTEMTIME, LPSYSTEMTIME, WORD *, LPSYSTEMTIME *
1103
- GetRunTimes: [[:pointer, :pointer, :pointer, :pointer], :hresult],
1104
- # SYSTEMTIME *
1105
- GetNextRunTime: [[:pointer], :hresult],
1106
- SetIdleWait: [[:word, :word], :hresult],
1107
- # WORD *, WORD *
1108
- GetIdleWait: [[:pointer, :pointer], :hresult],
1109
- Run: [[], :hresult],
1110
- Terminate: [[], :hresult],
1111
- EditWorkItem: [[:hwnd, :dword], :hresult],
1112
- # SYSTEMTIME *
1113
- GetMostRecentRunTime: [[:pointer], :hresult],
1114
- # HRESULT *
1115
- GetStatus: [[:pointer], :hresult],
1116
- GetExitCode: [[:pdword], :hresult],
1117
- SetComment: [[:lpcwstr], :hresult],
1118
- # LPWSTR *
1119
- GetComment: [[:pointer], :hresult],
1120
- SetCreator: [[:lpcwstr], :hresult],
1121
- # LPWSTR *
1122
- GetCreator: [[:pointer], :hresult],
1123
- # WORD, BYTE[]
1124
- SetWorkItemData: [[:word, :buffer_in], :hresult],
1125
- # WORD *, BYTE **
1126
- GetWorkItemData: [[:pointer, :pointer], :hresult],
1127
- SetErrorRetryCount: [[:word], :hresult],
1128
- # WORD *
1129
- GetErrorRetryCount: [[:pointer], :hresult],
1130
- SetErrorRetryInterval: [[:word], :hresult],
1131
- # WORD *
1132
- GetErrorRetryInterval: [[:pointer], :hresult],
1133
- SetFlags: [[:dword], :hresult],
1134
- # WORD *
1135
- GetFlags: [[:pointer], :hresult],
1136
- SetAccountInformation: [[:lpcwstr, :lpcwstr], :hresult],
1137
- # LPWSTR *
1138
- GetAccountInformation: [[:pointer], :hresult]
1139
- ]
1140
-
1141
- # https://msdn.microsoft.com/en-us/library/windows/desktop/aa381311(v=vs.85).aspx
1142
- ITask = com::Interface[IScheduledWorkItem,
1143
- FFI::WIN32::GUID['148BD524-A2AB-11CE-B11F-00AA00530503'],
1144
-
1145
- SetApplicationName: [[:lpcwstr], :hresult],
1146
- # LPWSTR *
1147
- GetApplicationName: [[:pointer], :hresult],
1148
- SetParameters: [[:lpcwstr], :hresult],
1149
- # LPWSTR *
1150
- GetParameters: [[:pointer], :hresult],
1151
- SetWorkingDirectory: [[:lpcwstr], :hresult],
1152
- # LPWSTR *
1153
- GetWorkingDirectory: [[:pointer], :hresult],
1154
- SetPriority: [[:dword], :hresult],
1155
- # DWORD *
1156
- GetPriority: [[:pointer], :hresult],
1157
- SetTaskFlags: [[:dword], :hresult],
1158
- # DWORD *
1159
- GetTaskFlags: [[:pointer], :hresult],
1160
- SetMaxRunTime: [[:dword], :hresult],
1161
- # DWORD *
1162
- GetMaxRunTime: [[:pointer], :hresult]
1163
- ]
1164
-
1165
- Task = com::Instance[ITask]
1166
-
1167
- # https://msdn.microsoft.com/en-us/library/windows/desktop/ms688695(v=vs.85).aspx
1168
- IPersist = com::Interface[com::IUnknown,
1169
- FFI::WIN32::GUID['0000010c-0000-0000-c000-000000000046'],
1170
- # CLSID *
1171
- GetClassID: [[:pointer], :hresult]
1172
- ]
1173
-
1174
- # https://msdn.microsoft.com/en-us/library/windows/desktop/ms687223(v=vs.85).aspx
1175
- IPersistFile = com::Interface[IPersist,
1176
- FFI::WIN32::GUID['0000010b-0000-0000-C000-000000000046'],
1177
-
1178
- IsDirty: [[], :hresult],
1179
- Load: [[:lpcolestr, :dword], :hresult],
1180
- Save: [[:lpcolestr, :win32_bool], :hresult],
1181
- SaveCompleted: [[:lpcolestr], :hresult],
1182
- # LPOLESTR *
1183
- GetCurFile: [[:pointer], :hresult]
1184
- ]
1185
-
1186
- PersistFile = com::Instance[IPersistFile]
1187
-
1188
- # https://msdn.microsoft.com/en-us/library/windows/desktop/aa381864(v=vs.85).aspx
1189
- ITaskTrigger = com::Interface[com::IUnknown,
1190
- FFI::WIN32::GUID['148BD52B-A2AB-11CE-B11F-00AA00530503'],
1191
-
1192
- SetTrigger: [[:pointer], :hresult],
1193
- GetTrigger: [[:pointer], :hresult],
1194
- GetTriggerString: [[:pointer], :hresult]
1195
- ]
1196
-
1197
- TaskTrigger = com::Instance[ITaskTrigger]
1198
-
1199
- # https://msdn.microsoft.com/en-us/library/windows/desktop/aa383620(v=vs.85).aspx
1200
- # The TASK_TRIGGER_TYPE field of the TASK_TRIGGER structure determines
1201
- # which member of the TRIGGER_TYPE_UNION field to use.
1202
- TASK_TRIGGER_TYPE = enum(
1203
- :TASK_TIME_TRIGGER_ONCE, 0, # Ignore the Type field
1204
- :TASK_TIME_TRIGGER_DAILY, 1,
1205
- :TASK_TIME_TRIGGER_WEEKLY, 2,
1206
- :TASK_TIME_TRIGGER_MONTHLYDATE, 3,
1207
- :TASK_TIME_TRIGGER_MONTHLYDOW, 4,
1208
- :TASK_EVENT_TRIGGER_ON_IDLE, 5, # Ignore the Type field
1209
- :TASK_EVENT_TRIGGER_AT_SYSTEMSTART, 6, # Ignore the Type field
1210
- :TASK_EVENT_TRIGGER_AT_LOGON, 7 # Ignore the Type field
1211
- )
1212
-
1213
- # https://msdn.microsoft.com/en-us/library/windows/desktop/aa446857(v=vs.85).aspx
1214
- class DAILY < FFI::Struct
1215
- layout :DaysInterval, :word
1216
- end
1217
-
1218
- # https://msdn.microsoft.com/en-us/library/windows/desktop/aa384014(v=vs.85).aspx
1219
- class WEEKLY < FFI::Struct
1220
- layout :WeeksInterval, :word,
1221
- :rgfDaysOfTheWeek, :word
1222
- end
1223
-
1224
- # https://msdn.microsoft.com/en-us/library/windows/desktop/aa381918(v=vs.85).aspx
1225
- class MONTHLYDATE < FFI::Struct
1226
- layout :rgfDays, :dword,
1227
- :rgfMonths, :word
1228
- end
1229
-
1230
- # https://msdn.microsoft.com/en-us/library/windows/desktop/aa381918(v=vs.85).aspx
1231
- class MONTHLYDOW < FFI::Struct
1232
- layout :wWhichWeek, :word,
1233
- :rgfDaysOfTheWeek, :word,
1234
- :rgfMonths, :word
1235
- end
1236
-
1237
- # https://msdn.microsoft.com/en-us/library/windows/desktop/aa384002(v=vs.85).aspx
1238
- class TRIGGER_TYPE_UNION < FFI::Union
1239
- layout :Daily, DAILY,
1240
- :Weekly, WEEKLY,
1241
- :MonthlyDate, MONTHLYDATE,
1242
- :MonthlyDOW, MONTHLYDOW
1243
- end
1244
-
1245
- # https://msdn.microsoft.com/en-us/library/windows/desktop/aa383618(v=vs.85).aspx
1246
- class TASK_TRIGGER < FFI::Struct
1247
- layout :cbTriggerSize, :word, # Structure size.
1248
- :Reserved1, :word, # Reserved. Must be zero.
1249
- :wBeginYear, :word, # Trigger beginning date year.
1250
- :wBeginMonth, :word, # Trigger beginning date month.
1251
- :wBeginDay, :word, # Trigger beginning date day.
1252
- :wEndYear, :word, # Optional trigger ending date year.
1253
- :wEndMonth, :word, # Optional trigger ending date month.
1254
- :wEndDay, :word, # Optional trigger ending date day.
1255
- :wStartHour, :word, # Run bracket start time hour.
1256
- :wStartMinute, :word, # Run bracket start time minute.
1257
- :MinutesDuration, :dword, # Duration of run bracket.
1258
- :MinutesInterval, :dword, # Run bracket repetition interval.
1259
- :rgFlags, :dword, # Trigger flags.
1260
- :TriggerType, TASK_TRIGGER_TYPE, # Trigger type.
1261
- :Type, TRIGGER_TYPE_UNION, # Trigger data.
1262
- :Reserved2, :word, # Reserved. Must be zero.
1263
- :wRandomMinutesInterval, :word # Maximum number of random minutes after start time
1264
- end
1265
- end
1266
- end
1267
- end