2 * Test suite for Task interface
4 * Copyright (C) 2008 Google (Roy Shea)
5 * Copyright (C) 2018 Dmitry Timoshkov
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
27 #include "wine/test.h"
29 static ITaskScheduler
*test_task_scheduler
;
31 static DWORD
obj_refcount(void *obj_to_check
)
33 IUnknown
*obj
= obj_to_check
;
35 return IUnknown_Release(obj
);
38 static BOOL
compare_trigger_state(TASK_TRIGGER found_state
,
39 TASK_TRIGGER expected_state
)
41 ok(found_state
.cbTriggerSize
== expected_state
.cbTriggerSize
,
42 "cbTriggerSize: Found %d but expected %d\n",
43 found_state
.cbTriggerSize
, expected_state
.cbTriggerSize
);
45 ok(found_state
.Reserved1
== expected_state
.Reserved1
,
46 "Reserved1: Found %d but expected %d\n",
47 found_state
.Reserved1
, expected_state
.Reserved1
);
49 ok(found_state
.wBeginYear
== expected_state
.wBeginYear
,
50 "wBeginYear: Found %d but expected %d\n",
51 found_state
.wBeginYear
, expected_state
.wBeginYear
);
53 ok(found_state
.wBeginMonth
== expected_state
.wBeginMonth
,
54 "wBeginMonth: Found %d but expected %d\n",
55 found_state
.wBeginMonth
, expected_state
.wBeginMonth
);
57 ok(found_state
.wBeginDay
== expected_state
.wBeginDay
,
58 "wBeginDay: Found %d but expected %d\n",
59 found_state
.wBeginDay
, expected_state
.wBeginDay
);
61 ok(found_state
.wEndYear
== expected_state
.wEndYear
,
62 "wEndYear: Found %d but expected %d\n",
63 found_state
.wEndYear
, expected_state
.wEndYear
);
65 ok(found_state
.wEndMonth
== expected_state
.wEndMonth
,
66 "wEndMonth: Found %d but expected %d\n",
67 found_state
.wEndMonth
, expected_state
.wEndMonth
);
69 ok(found_state
.wEndDay
== expected_state
.wEndDay
,
70 "wEndDay: Found %d but expected %d\n",
71 found_state
.wEndDay
, expected_state
.wEndDay
);
73 ok(found_state
.wStartHour
== expected_state
.wStartHour
,
74 "wStartHour: Found %d but expected %d\n",
75 found_state
.wStartHour
, expected_state
.wStartHour
);
77 ok(found_state
.wStartMinute
== expected_state
.wStartMinute
,
78 "wStartMinute: Found %d but expected %d\n",
79 found_state
.wStartMinute
, expected_state
.wStartMinute
);
81 ok(found_state
.MinutesDuration
== expected_state
.MinutesDuration
,
82 "MinutesDuration: Found %d but expected %d\n",
83 found_state
.MinutesDuration
, expected_state
.MinutesDuration
);
85 ok(found_state
.MinutesInterval
== expected_state
.MinutesInterval
,
86 "MinutesInterval: Found %d but expected %d\n",
87 found_state
.MinutesInterval
, expected_state
.MinutesInterval
);
89 ok(found_state
.rgFlags
== expected_state
.rgFlags
,
90 "rgFlags: Found %d but expected %d\n",
91 found_state
.rgFlags
, expected_state
.rgFlags
);
93 ok(found_state
.TriggerType
== expected_state
.TriggerType
,
94 "TriggerType: Found %d but expected %d\n",
95 found_state
.TriggerType
, expected_state
.TriggerType
);
97 ok(found_state
.Type
.Daily
.DaysInterval
== expected_state
.Type
.Daily
.DaysInterval
,
98 "Type.Daily.DaysInterval: Found %d but expected %d\n",
99 found_state
.Type
.Daily
.DaysInterval
, expected_state
.Type
.Daily
.DaysInterval
);
101 ok(found_state
.Reserved2
== expected_state
.Reserved2
,
102 "Reserved2: Found %d but expected %d\n",
103 found_state
.Reserved2
, expected_state
.Reserved2
);
105 ok(found_state
.wRandomMinutesInterval
== expected_state
.wRandomMinutesInterval
,
106 "wRandomMinutesInterval: Found %d but expected %d\n",
107 found_state
.wRandomMinutesInterval
, expected_state
.wRandomMinutesInterval
);
112 static void test_SetTrigger_GetTrigger(void)
114 static const WCHAR task_name
[] = { 'T','e','s','t','i','n','g',0 };
116 ITaskTrigger
*test_trigger
;
119 TASK_TRIGGER trigger_state
;
120 TASK_TRIGGER empty_trigger_state
= {
121 sizeof(trigger_state
), 0,
125 TASK_TRIGGER_FLAG_DISABLED
, TASK_TIME_TRIGGER_DAILY
, {{1}},
128 TASK_TRIGGER normal_trigger_state
= {
129 sizeof(trigger_state
), 0,
134 TASK_TRIGGER_FLAG_DISABLED
, TASK_TIME_TRIGGER_DAILY
, {{1}},
139 hres
= ITaskScheduler_NewWorkItem(test_task_scheduler
, task_name
, &CLSID_CTask
,
140 &IID_ITask
, (IUnknown
**)&test_task
);
141 ok(hres
== S_OK
, "got %#x\n", hres
);
143 hres
= ITask_CreateTrigger(test_task
, &idx
, &test_trigger
);
144 ok(hres
== S_OK
, "got %#x\n", hres
);
146 hres
= ITaskTrigger_SetTrigger(test_trigger
, NULL
);
147 ok(hres
== E_INVALIDARG
, "got %#x\n", hres
);
149 hres
= ITaskTrigger_GetTrigger(test_trigger
, NULL
);
150 ok(hres
== E_INVALIDARG
, "got %#x\n", hres
);
152 /* Setup a trigger with base values for this test run */
154 empty_trigger_state
.wStartHour
= time
.wHour
;
155 empty_trigger_state
.wStartMinute
= time
.wMinute
;
156 empty_trigger_state
.wBeginYear
= time
.wYear
;
157 empty_trigger_state
.wBeginMonth
= time
.wMonth
;
158 empty_trigger_state
.wBeginDay
= time
.wDay
;
160 /* Test trigger state after trigger creation but before setting * state */
161 memset(&trigger_state
, 0xcf, sizeof(trigger_state
));
162 trigger_state
.cbTriggerSize
= sizeof(trigger_state
);
163 hres
= ITaskTrigger_GetTrigger(test_trigger
, &trigger_state
);
164 ok(hres
== S_OK
, "Failed to set trigger: 0x%08x\n", hres
);
165 compare_trigger_state(trigger_state
, empty_trigger_state
);
167 /* Test setting basic empty trigger */
168 hres
= ITaskTrigger_SetTrigger(test_trigger
, &empty_trigger_state
);
169 ok(hres
== S_OK
, "Failed to set trigger: 0x%08x\n", hres
);
170 memset(&trigger_state
, 0xcf, sizeof(trigger_state
));
171 trigger_state
.cbTriggerSize
= sizeof(trigger_state
);
172 hres
= ITaskTrigger_GetTrigger(test_trigger
, &trigger_state
);
173 ok(hres
== S_OK
, "Failed to GetTrigger\n");
174 compare_trigger_state(trigger_state
, empty_trigger_state
);
176 /* Test setting basic non-empty trigger */
177 hres
= ITaskTrigger_SetTrigger(test_trigger
, &normal_trigger_state
);
178 ok(hres
== S_OK
, "Failed to set trigger: 0x%08x\n", hres
);
179 memset(&trigger_state
, 0xcf, sizeof(trigger_state
));
180 trigger_state
.cbTriggerSize
= sizeof(trigger_state
);
181 hres
= ITaskTrigger_GetTrigger(test_trigger
, &trigger_state
);
182 ok(hres
== S_OK
, "Failed to GetTrigger\n");
183 compare_trigger_state(trigger_state
, normal_trigger_state
);
185 /* The following tests modify the normal_trigger_state structure
186 * before each test, and return the normal_trigger_state structure
187 * back to its original valid state after each test. This keeps
188 * each test run independent. */
190 /* Test setting trigger with invalid cbTriggerSize */
191 normal_trigger_state
.cbTriggerSize
= sizeof(trigger_state
) - 1;
192 hres
= ITaskTrigger_SetTrigger(test_trigger
, &normal_trigger_state
);
193 ok(hres
== E_INVALIDARG
, "Expected E_INVALIDARG: 0x%08x\n", hres
);
194 normal_trigger_state
.cbTriggerSize
= sizeof(trigger_state
) + 1;
195 hres
= ITaskTrigger_SetTrigger(test_trigger
, &normal_trigger_state
);
196 ok(hres
== E_INVALIDARG
, "Expected E_INVALIDARG: 0x%08x\n", hres
);
197 normal_trigger_state
.cbTriggerSize
= sizeof(trigger_state
);
199 /* Test setting trigger with invalid Reserved fields */
200 normal_trigger_state
.Reserved1
= 80;
201 normal_trigger_state
.Reserved2
= 80;
202 hres
= ITaskTrigger_SetTrigger(test_trigger
, &normal_trigger_state
);
203 ok(hres
== S_OK
, "Failed to set trigger: 0x%08x\n", hres
);
204 memset(&trigger_state
, 0xcf, sizeof(trigger_state
));
205 trigger_state
.cbTriggerSize
= sizeof(trigger_state
);
206 hres
= ITaskTrigger_GetTrigger(test_trigger
, &trigger_state
);
207 ok(hres
== S_OK
, "Expected S_OK: 0x%08x\n", hres
);
208 ok(trigger_state
.Reserved1
== 0 && trigger_state
.Reserved2
== 0,
209 "Reserved fields should be set to zero\n");
210 normal_trigger_state
.Reserved1
= 0;
211 normal_trigger_state
.Reserved2
= 0;
213 /* Test setting trigger with invalid month */
214 normal_trigger_state
.wBeginMonth
= 0;
215 hres
= ITaskTrigger_SetTrigger(test_trigger
, &normal_trigger_state
);
216 ok(hres
== E_INVALIDARG
, "Expected E_INVALIDARG: 0x%08x\n", hres
);
217 normal_trigger_state
.wBeginMonth
= 13;
218 hres
= ITaskTrigger_SetTrigger(test_trigger
, &normal_trigger_state
);
219 ok(hres
== E_INVALIDARG
, "Expected E_INVALIDARG: 0x%08x\n", hres
);
220 normal_trigger_state
.wBeginMonth
= 1;
222 /* Test setting trigger with invalid begin date */
223 normal_trigger_state
.wBeginDay
= 0;
224 hres
= ITaskTrigger_SetTrigger(test_trigger
, &normal_trigger_state
);
225 ok(hres
== E_INVALIDARG
, "Expected E_INVALIDARG: 0x%08x\n", hres
);
226 normal_trigger_state
.wBeginDay
= 32;
227 hres
= ITaskTrigger_SetTrigger(test_trigger
, &normal_trigger_state
);
228 ok(hres
== E_INVALIDARG
, "Expected E_INVALIDARG: 0x%08x\n", hres
);
229 normal_trigger_state
.wBeginMonth
= 2;
230 normal_trigger_state
.wBeginDay
= 30;
231 hres
= ITaskTrigger_SetTrigger(test_trigger
, &normal_trigger_state
);
232 ok(hres
== E_INVALIDARG
, "Expected E_INVALIDARG: 0x%08x\n", hres
);
233 normal_trigger_state
.wBeginMonth
= 1;
234 normal_trigger_state
.wBeginDay
= 1;
236 /* Test setting trigger invalid end date */
237 normal_trigger_state
.wEndYear
= 0;
238 normal_trigger_state
.wEndMonth
= 200;
239 normal_trigger_state
.wEndDay
= 200;
240 hres
= ITaskTrigger_SetTrigger(test_trigger
, &normal_trigger_state
);
241 ok(hres
== S_OK
, "Failed to set trigger: 0x%08x\n", hres
);
242 memset(&trigger_state
, 0xcf, sizeof(trigger_state
));
243 trigger_state
.cbTriggerSize
= sizeof(trigger_state
);
244 hres
= ITaskTrigger_GetTrigger(test_trigger
, &trigger_state
);
245 ok(hres
== S_OK
, "Expected S_OK: 0x%08x\n", hres
);
246 ok(trigger_state
.wEndYear
== 0, "End year should be 0: %d\n",
247 trigger_state
.wEndYear
);
248 ok(trigger_state
.wEndMonth
== 200, "End month should be 200: %d\n",
249 trigger_state
.wEndMonth
);
250 ok(trigger_state
.wEndDay
== 200, "End day should be 200: %d\n",
251 trigger_state
.wEndDay
);
252 normal_trigger_state
.rgFlags
=
253 TASK_TRIGGER_FLAG_DISABLED
| TASK_TRIGGER_FLAG_HAS_END_DATE
;
254 hres
= ITaskTrigger_SetTrigger(test_trigger
, &normal_trigger_state
);
255 ok(hres
== E_INVALIDARG
, "Expected E_INVALIDARG: 0x%08x\n", hres
);
256 normal_trigger_state
.rgFlags
= TASK_TRIGGER_FLAG_DISABLED
;
257 normal_trigger_state
.wEndYear
= 2980;
258 normal_trigger_state
.wEndMonth
= 1;
259 normal_trigger_state
.wEndDay
= 1;
261 /* Test setting trigger with invalid hour or minute*/
262 normal_trigger_state
.wStartHour
= 24;
263 hres
= ITaskTrigger_SetTrigger(test_trigger
, &normal_trigger_state
);
264 ok(hres
== E_INVALIDARG
, "Expected E_INVALIDARG: 0x%08x\n", hres
);
265 normal_trigger_state
.wStartHour
= 60;
266 hres
= ITaskTrigger_SetTrigger(test_trigger
, &normal_trigger_state
);
267 ok(hres
== E_INVALIDARG
, "Expected E_INVALIDARG: 0x%08x\n", hres
);
268 normal_trigger_state
.wStartHour
= 3;
270 /* Test setting trigger with invalid duration / interval pairs */
271 normal_trigger_state
.MinutesDuration
= 5;
272 normal_trigger_state
.MinutesInterval
= 5;
273 hres
= ITaskTrigger_SetTrigger(test_trigger
, &normal_trigger_state
);
274 ok(hres
== E_INVALIDARG
, "Expected E_INVALIDARG: 0x%08x\n", hres
);
275 normal_trigger_state
.MinutesDuration
= 5;
276 normal_trigger_state
.MinutesInterval
= 6;
277 hres
= ITaskTrigger_SetTrigger(test_trigger
, &normal_trigger_state
);
278 ok(hres
== E_INVALIDARG
, "Expected E_INVALIDARG: 0x%08x\n", hres
);
279 normal_trigger_state
.MinutesDuration
= 0;
280 normal_trigger_state
.MinutesInterval
= 6;
281 hres
= ITaskTrigger_SetTrigger(test_trigger
, &normal_trigger_state
);
282 ok(hres
== E_INVALIDARG
, "Expected E_INVALIDARG: 0x%08x\n", hres
);
283 normal_trigger_state
.MinutesDuration
= 5;
284 normal_trigger_state
.MinutesInterval
= 0;
285 hres
= ITaskTrigger_SetTrigger(test_trigger
, &normal_trigger_state
);
286 ok(hres
== S_OK
, "Failed to set trigger: 0x%08x\n", hres
);
287 normal_trigger_state
.MinutesDuration
= 0;
288 normal_trigger_state
.MinutesInterval
= 0;
290 /* Test setting trigger with end date before start date */
291 normal_trigger_state
.wEndYear
= 1979;
292 hres
= ITaskTrigger_SetTrigger(test_trigger
, &normal_trigger_state
);
293 ok(hres
== S_OK
, "Failed to set trigger: 0x%08x\n", hres
);
294 normal_trigger_state
.rgFlags
=
295 TASK_TRIGGER_FLAG_DISABLED
| TASK_TRIGGER_FLAG_HAS_END_DATE
;
296 hres
= ITaskTrigger_SetTrigger(test_trigger
, &normal_trigger_state
);
297 ok(hres
== S_OK
, "Failed to set trigger: 0x%08x\n", hres
);
298 normal_trigger_state
.rgFlags
= TASK_TRIGGER_FLAG_DISABLED
;
299 normal_trigger_state
.wEndYear
= 2980;
300 normal_trigger_state
.wEndMonth
= 1;
301 normal_trigger_state
.wEndDay
= 1;
304 /* Test setting trigger with invalid TriggerType and Type */
305 normal_trigger_state
.TriggerType
= TASK_TIME_TRIGGER_ONCE
;
306 normal_trigger_state
.Type
.Weekly
.WeeksInterval
= 2;
307 normal_trigger_state
.Type
.Weekly
.rgfDaysOfTheWeek
= (TASK_MONDAY
| TASK_TUESDAY
);
308 hres
= ITaskTrigger_SetTrigger(test_trigger
, &normal_trigger_state
);
309 ok(hres
== S_OK
, "Failed to set trigger: 0x%08x\n", hres
);
310 memset(&trigger_state
, 0xcf, sizeof(trigger_state
));
311 trigger_state
.cbTriggerSize
= sizeof(trigger_state
);
312 hres
= ITaskTrigger_GetTrigger(test_trigger
, &trigger_state
);
313 ok(hres
== S_OK
, "Expected S_OK: 0x%08x\n", hres
);
314 ok(trigger_state
.Type
.Weekly
.WeeksInterval
== 0xcfcf,
315 "Expected WeeksInterval set remain untouched: %d\n",
316 trigger_state
.Type
.Weekly
.WeeksInterval
);
317 ok(trigger_state
.Type
.Weekly
.rgfDaysOfTheWeek
== 0xcfcf,
318 "Expected WeeksInterval set remain untouched: %d\n",
319 trigger_state
.Type
.Weekly
.rgfDaysOfTheWeek
);
320 normal_trigger_state
.TriggerType
= TASK_TIME_TRIGGER_DAILY
;
321 normal_trigger_state
.Type
.Daily
.DaysInterval
= 1;
322 hres
= ITaskTrigger_SetTrigger(test_trigger
, &normal_trigger_state
);
323 ok(hres
== S_OK
, "Expected S_OK: 0x%08x\n", hres
);
325 /* Test setting trigger with set wRandomMinutesInterval */
326 normal_trigger_state
.wRandomMinutesInterval
= 5;
327 hres
= ITaskTrigger_SetTrigger(test_trigger
, &normal_trigger_state
);
328 ok(hres
== S_OK
, "Failed to set trigger: 0x%08x\n", hres
);
329 memset(&trigger_state
, 0xcf, sizeof(trigger_state
));
330 trigger_state
.cbTriggerSize
= sizeof(trigger_state
);
331 hres
= ITaskTrigger_GetTrigger(test_trigger
, &trigger_state
);
332 ok(hres
== S_OK
, "Expected S_OK: 0x%08x\n", hres
);
333 ok(trigger_state
.wRandomMinutesInterval
== 0,
334 "wRandomMinutesInterval should be set to zero\n");
335 normal_trigger_state
.wRandomMinutesInterval
= 0;
337 /* Test GetTrigger using invalid cbTriggerSiz in pTrigger. In
338 * contrast to available documentation, this succeeds in practice. */
339 hres
= ITaskTrigger_SetTrigger(test_trigger
, &normal_trigger_state
);
340 ok(hres
== S_OK
, "Failed to set trigger: 0x%08x\n", hres
);
341 memset(&trigger_state
, 0xcf, sizeof(trigger_state
));
342 trigger_state
.cbTriggerSize
= sizeof(trigger_state
) - 1;
343 hres
= ITaskTrigger_GetTrigger(test_trigger
, &trigger_state
);
344 ok(hres
== S_OK
, "Failed to GetTrigger\n");
345 ok(compare_trigger_state(trigger_state
, normal_trigger_state
),
347 memset(&trigger_state
, 0xcf, sizeof(trigger_state
));
348 trigger_state
.cbTriggerSize
= 0;
349 hres
= ITaskTrigger_GetTrigger(test_trigger
, &trigger_state
);
350 ok(hres
== S_OK
, "Failed to GetTrigger\n");
351 ok(compare_trigger_state(trigger_state
, normal_trigger_state
),
354 ITaskTrigger_Release(test_trigger
);
355 ITask_Release(test_task
);
358 static void test_task_trigger(void)
360 static const WCHAR task_name
[] = { 'T','e','s','t','i','n','g',0 };
363 ITaskTrigger
*trigger
, *trigger2
;
367 hr
= ITaskScheduler_NewWorkItem(test_task_scheduler
, task_name
, &CLSID_CTask
,
368 &IID_ITask
, (IUnknown
**)&task
);
369 ok(hr
== S_OK
, "got %#x\n", hr
);
372 hr
= ITask_GetTriggerCount(task
, &count
);
373 ok(hr
== S_OK
, "got %#x\n", hr
);
374 ok(count
== 0, "got %u\n", count
);
376 hr
= ITask_DeleteTrigger(task
, 0);
377 ok(hr
== SCHED_E_TRIGGER_NOT_FOUND
, "got %#x\n", hr
);
379 hr
= ITask_GetTrigger(task
, 0, &trigger
);
380 ok(hr
== SCHED_E_TRIGGER_NOT_FOUND
, "got %#x\n", hr
);
383 hr
= ITask_CreateTrigger(task
, &idx
, &trigger
);
384 ok(hr
== S_OK
, "got %#x\n", hr
);
385 ok(idx
== 0, "got %u\n", idx
);
387 hr
= ITask_GetTrigger(task
, 0, &trigger2
);
388 ok(hr
== S_OK
, "got %#x\n", hr
);
389 ok(trigger
!= trigger2
, "%p != %p\n", trigger
, trigger2
);
391 ref
= ITaskTrigger_Release(trigger2
);
392 ok(ref
== 0, "got %u\n", ref
);
394 ref
= ITaskTrigger_Release(trigger
);
395 ok(ref
== 0, "got %u\n", ref
);
398 hr
= ITask_GetTriggerCount(task
, &count
);
399 ok(hr
== S_OK
, "got %#x\n", hr
);
400 ok(count
== 1, "got %u\n", count
);
402 hr
= ITask_DeleteTrigger(task
, 0);
403 ok(hr
== S_OK
, "got %#x\n", hr
);
406 hr
= ITask_CreateTrigger(task
, &idx
, &trigger
);
407 ok(hr
== S_OK
, "got %#x\n", hr
);
408 ok(idx
== 0, "got %u\n", idx
);
410 hr
= ITask_DeleteTrigger(task
, 0);
411 ok(hr
== S_OK
, "got %#x\n", hr
);
414 hr
= ITask_GetTriggerCount(task
, &count
);
415 ok(hr
== S_OK
, "got %#x\n", hr
);
416 ok(count
== 0, "got %u\n", count
);
418 ref
= ITaskTrigger_Release(trigger
);
419 ok(ref
== 0, "got %u\n", ref
);
421 ref
= ITask_Release(task
);
422 ok(ref
== 0, "got %u\n", ref
);
425 static void time_add_ms(SYSTEMTIME
*st
, DWORD ms
)
434 trace("old: %u/%u/%u wday %u %u:%02u:%02u.%03u\n",
435 st
->wDay
, st
->wMonth
, st
->wYear
, st
->wDayOfWeek
,
436 st
->wHour
, st
->wMinute
, st
->wSecond
, st
->wMilliseconds
);
437 ret
= SystemTimeToFileTime(st
, &ftll
.ft
);
438 ok(ret
, "SystemTimeToFileTime error %u\n", GetLastError());
440 ftll
.ll
+= ms
* (ULONGLONG
)10000;
441 ret
= FileTimeToSystemTime(&ftll
.ft
, st
);
442 ok(ret
, "FileTimeToSystemTime error %u\n", GetLastError());
443 trace("new: %u/%u/%u wday %u %u:%02u:%02u.%03u\n",
444 st
->wDay
, st
->wMonth
, st
->wYear
, st
->wDayOfWeek
,
445 st
->wHour
, st
->wMinute
, st
->wSecond
, st
->wMilliseconds
);
448 static void trigger_add_ms(TASK_TRIGGER
*data
, DWORD ms
, SYSTEMTIME
*ret
)
452 st
.wYear
= data
->wBeginYear
;
453 st
.wMonth
= data
->wBeginMonth
;
455 st
.wDay
= data
->wBeginDay
;
456 st
.wHour
= data
->wStartHour
;
457 st
.wMinute
= data
->wStartMinute
;
459 st
.wMilliseconds
= 0;
461 time_add_ms(&st
, ms
);
463 data
->wBeginYear
= st
.wYear
;
464 data
->wBeginMonth
= st
.wMonth
;
465 data
->wBeginDay
= st
.wDay
;
466 data
->wStartHour
= st
.wHour
;
467 data
->wStartMinute
= st
.wMinute
;
472 static void test_GetNextRunTime(void)
474 static const WCHAR task_name
[] = { 'T','e','s','t','i','n','g',0 };
475 static const SYSTEMTIME st_empty
;
478 ITaskTrigger
*trigger
;
483 hr
= ITaskScheduler_NewWorkItem(test_task_scheduler
, task_name
, &CLSID_CTask
,
484 &IID_ITask
, (IUnknown
**)&task
);
485 ok(hr
== S_OK
, "got %#x\n", hr
);
487 if (0) /* crashes under Windows */
488 hr
= ITask_GetNextRunTime(task
, NULL
);
490 hr
= ITask_SetFlags(task
, TASK_FLAG_DISABLED
);
491 ok(hr
== S_OK
, "got %#x\n", hr
);
493 memset(&st
, 0xff, sizeof(st
));
494 hr
= ITask_GetNextRunTime(task
, &st
);
495 ok(hr
== SCHED_S_TASK_DISABLED
, "got %#x\n", hr
);
496 ok(!memcmp(&st
, &st_empty
, sizeof(st
)), "got %u/%u/%u wday %u %u:%02u:%02u\n",
497 st
.wDay
, st
.wMonth
, st
.wYear
, st
.wDayOfWeek
,
498 st
.wHour
, st
.wMinute
, st
.wSecond
);
500 hr
= ITask_SetFlags(task
, 0);
501 ok(hr
== S_OK
, "got %#x\n", hr
);
503 memset(&st
, 0xff, sizeof(st
));
504 hr
= ITask_GetNextRunTime(task
, &st
);
505 ok(hr
== SCHED_S_TASK_NO_VALID_TRIGGERS
, "got %#x\n", hr
);
506 ok(!memcmp(&st
, &st_empty
, sizeof(st
)), "got %u/%u/%u wday %u %u:%02u:%02u\n",
507 st
.wDay
, st
.wMonth
, st
.wYear
, st
.wDayOfWeek
,
508 st
.wHour
, st
.wMinute
, st
.wSecond
);
510 hr
= ITask_CreateTrigger(task
, &idx
, &trigger
);
511 ok(hr
== S_OK
, "got %#x\n", hr
);
513 memset(&st
, 0xff, sizeof(st
));
514 hr
= ITask_GetNextRunTime(task
, &st
);
515 ok(hr
== SCHED_S_TASK_NO_VALID_TRIGGERS
, "got %#x\n", hr
);
516 ok(!memcmp(&st
, &st_empty
, sizeof(st
)), "got %u/%u/%u wday %u %u:%02u:%02u\n",
517 st
.wDay
, st
.wMonth
, st
.wYear
, st
.wDayOfWeek
,
518 st
.wHour
, st
.wMinute
, st
.wSecond
);
520 /* TASK_TIME_TRIGGER_ONCE */
522 hr
= ITaskTrigger_GetTrigger(trigger
, &data
);
523 ok(hr
== S_OK
, "got %#x\n", hr
);
524 data
.rgFlags
&= ~TASK_TRIGGER_FLAG_DISABLED
;
525 data
.TriggerType
= TASK_TIME_TRIGGER_ONCE
;
526 /* add 5 minutes to avoid races */
527 trigger_add_ms(&data
, 5 * 60 * 1000, &cmp
);
528 hr
= ITaskTrigger_SetTrigger(trigger
, &data
);
529 ok(hr
== S_OK
, "got %#x\n", hr
);
531 memset(&st
, 0xff, sizeof(st
));
532 hr
= ITask_GetNextRunTime(task
, &st
);
533 ok(hr
== S_OK
, "got %#x\n", hr
);
534 ok(!memcmp(&st
, &cmp
, sizeof(st
)), "got %u/%u/%u wday %u %u:%02u:%02u\n",
535 st
.wDay
, st
.wMonth
, st
.wYear
, st
.wDayOfWeek
,
536 st
.wHour
, st
.wMinute
, st
.wSecond
);
538 /* TASK_TIME_TRIGGER_DAILY */
540 hr
= ITaskTrigger_GetTrigger(trigger
, &data
);
541 ok(hr
== S_OK
, "got %#x\n", hr
);
542 data
.rgFlags
&= ~TASK_TRIGGER_FLAG_DISABLED
;
543 data
.TriggerType
= TASK_TIME_TRIGGER_DAILY
;
544 data
.Type
.Daily
.DaysInterval
= 1;
545 hr
= ITaskTrigger_SetTrigger(trigger
, &data
);
546 ok(hr
== S_OK
, "got %#x\n", hr
);
548 memset(&st
, 0xff, sizeof(st
));
549 hr
= ITask_GetNextRunTime(task
, &st
);
550 ok(hr
== S_OK
, "got %#x\n", hr
);
551 ok(!memcmp(&st
, &cmp
, sizeof(st
)), "got %u/%u/%u wday %u %u:%02u:%02u\n",
552 st
.wDay
, st
.wMonth
, st
.wYear
, st
.wDayOfWeek
,
553 st
.wHour
, st
.wMinute
, st
.wSecond
);
555 /* TASK_TIME_TRIGGER_WEEKLY */
557 hr
= ITaskTrigger_GetTrigger(trigger
, &data
);
558 ok(hr
== S_OK
, "got %#x\n", hr
);
559 data
.rgFlags
&= ~TASK_TRIGGER_FLAG_DISABLED
;
560 data
.TriggerType
= TASK_TIME_TRIGGER_WEEKLY
;
561 data
.Type
.Weekly
.WeeksInterval
= 1;
563 time_add_ms(&cmp
, 3 * 24 * 60 * 60 * 1000);
564 /* bits: TASK_SUNDAY = 1, TASK_MONDAY = 2, TASK_TUESDAY = 4, etc. */
565 data
.Type
.Weekly
.rgfDaysOfTheWeek
= 1 << cmp
.wDayOfWeek
; /* wDayOfWeek is 0 based */
566 hr
= ITaskTrigger_SetTrigger(trigger
, &data
);
567 ok(hr
== S_OK
, "got %#x\n", hr
);
569 memset(&st
, 0xff, sizeof(st
));
570 hr
= ITask_GetNextRunTime(task
, &st
);
571 ok(hr
== S_OK
, "got %#x\n", hr
);
572 ok(!memcmp(&st
, &cmp
, sizeof(st
)), "got %u/%u/%u wday %u %u:%02u:%02u\n",
573 st
.wDay
, st
.wMonth
, st
.wYear
, st
.wDayOfWeek
,
574 st
.wHour
, st
.wMinute
, st
.wSecond
);
576 /* FIXME: TASK_TIME_TRIGGER_MONTHLYDATE */
577 /* FIXME: TASK_TIME_TRIGGER_MONTHLYDOW */
579 ITaskTrigger_Release(trigger
);
580 /* do not delete a valid trigger */
583 hr
= ITask_CreateTrigger(task
, &idx
, &trigger
);
584 ok(hr
== S_OK
, "got %#x\n", hr
);
585 ok(idx
== 1, "got %u\n", idx
);
587 /* TASK_EVENT_TRIGGER_ON_IDLE = 5
588 * TASK_EVENT_TRIGGER_AT_SYSTEMSTART = 6
589 * TASK_EVENT_TRIGGER_AT_LOGON = 7
591 for (i
= 5; i
<= 7; i
++)
593 hr
= ITaskTrigger_GetTrigger(trigger
, &data
);
594 ok(hr
== S_OK
, "got %#x\n", hr
);
595 data
.rgFlags
&= ~TASK_TRIGGER_FLAG_DISABLED
;
596 data
.TriggerType
= i
;
597 hr
= ITaskTrigger_SetTrigger(trigger
, &data
);
598 ok(hr
== S_OK
, "got %#x\n", hr
);
600 memset(&st
, 0xff, sizeof(st
));
601 hr
= ITask_GetNextRunTime(task
, &st
);
602 ok(hr
== S_OK
, "got %#x\n", hr
);
603 ok(!memcmp(&st
, &cmp
, sizeof(st
)), "got %u/%u/%u wday %u %u:%02u:%02u\n",
604 st
.wDay
, st
.wMonth
, st
.wYear
, st
.wDayOfWeek
,
605 st
.wHour
, st
.wMinute
, st
.wSecond
);
608 ITaskTrigger_Release(trigger
);
610 hr
= ITask_DeleteTrigger(task
, 0);
611 ok(hr
== S_OK
, "got %#x\n", hr
);
613 hr
= ITask_GetTrigger(task
, 0, &trigger
);
614 ok(hr
== S_OK
, "got %#x\n", hr
);
616 for (i
= 5; i
<= 7; i
++)
618 hr
= ITaskTrigger_GetTrigger(trigger
, &data
);
619 ok(hr
== S_OK
, "got %#x\n", hr
);
620 data
.rgFlags
&= ~TASK_TRIGGER_FLAG_DISABLED
;
621 data
.TriggerType
= i
;
622 hr
= ITaskTrigger_SetTrigger(trigger
, &data
);
623 ok(hr
== S_OK
, "got %#x\n", hr
);
625 memset(&st
, 0xff, sizeof(st
));
626 hr
= ITask_GetNextRunTime(task
, &st
);
627 ok(hr
== SCHED_S_EVENT_TRIGGER
, "got %#x\n", hr
);
628 ok(!memcmp(&st
, &st_empty
, sizeof(st
)), "got %u/%u/%u wday %u %u:%02u:%02u\n",
629 st
.wDay
, st
.wMonth
, st
.wYear
, st
.wDayOfWeek
,
630 st
.wHour
, st
.wMinute
, st
.wSecond
);
633 ITaskTrigger_Release(trigger
);
637 static HRESULT
get_task_trigger(ITask
*task
, WORD idx
, TASK_TRIGGER
*state
)
640 ITaskTrigger
*trigger
;
642 hr
= ITask_GetTrigger(task
, idx
, &trigger
);
643 if (hr
!= S_OK
) return hr
;
645 memset(state
, 0x11, sizeof(*state
));
646 hr
= ITaskTrigger_GetTrigger(trigger
, state
);
648 ITaskTrigger_Release(trigger
);
652 static void test_trigger_manager(void)
654 static const WCHAR task_name
[] = { 'T','e','s','t','i','n','g',0 };
657 ITaskTrigger
*trigger0
, *trigger1
;
658 TASK_TRIGGER state0
, state1
, state
;
662 hr
= ITaskScheduler_NewWorkItem(test_task_scheduler
, task_name
, &CLSID_CTask
,
663 &IID_ITask
, (IUnknown
**)&task
);
664 ok(hr
== S_OK
, "got %#x\n", hr
);
665 ok(obj_refcount(task
) == 1, "got %u\n", obj_refcount(task
));
668 hr
= ITask_GetTriggerCount(task
, &count
);
669 ok(hr
== S_OK
, "got %#x\n", hr
);
670 ok(count
== 0, "got %u\n", count
);
673 hr
= ITask_CreateTrigger(task
, &idx
, &trigger0
);
674 ok(hr
== S_OK
, "got %#x\n", hr
);
675 ok(idx
== 0, "got %u\n", idx
);
676 ok(obj_refcount(task
) == 2, "got %u\n", obj_refcount(task
));
679 hr
= ITask_CreateTrigger(task
, &idx
, &trigger1
);
680 ok(hr
== S_OK
, "got %#x\n", hr
);
681 ok(idx
== 1, "got %u\n", idx
);
682 ok(obj_refcount(task
) == 3, "got %u\n", obj_refcount(task
));
685 hr
= ITask_GetTriggerCount(task
, &count
);
686 ok(hr
== S_OK
, "got %#x\n", hr
);
687 ok(count
== 2, "got %u\n", count
);
689 hr
= ITaskTrigger_GetTrigger(trigger0
, &state0
);
690 ok(hr
== S_OK
, "got %#x\n", hr
);
691 state0
.wBeginYear
= 3000;
693 state0
.TriggerType
= TASK_TIME_TRIGGER_ONCE
;
694 hr
= ITaskTrigger_SetTrigger(trigger0
, &state0
);
695 ok(hr
== S_OK
, "got %#x\n", hr
);
697 hr
= get_task_trigger(task
, 0, &state
);
698 ok(hr
== S_OK
, "got %#x\n", hr
);
699 ok(state
.wBeginYear
== 3000, "got %u\n", state
.wBeginYear
);
700 ok(state
.TriggerType
== TASK_TIME_TRIGGER_ONCE
, "got %u\n", state
.TriggerType
);
702 hr
= ITaskTrigger_GetTrigger(trigger1
, &state1
);
703 ok(hr
== S_OK
, "got %#x\n", hr
);
704 state1
.wBeginYear
= 2000;
706 state1
.TriggerType
= TASK_TIME_TRIGGER_DAILY
;
707 hr
= ITaskTrigger_SetTrigger(trigger1
, &state1
);
708 ok(hr
== S_OK
, "got %#x\n", hr
);
710 hr
= get_task_trigger(task
, 1, &state
);
711 ok(hr
== S_OK
, "got %#x\n", hr
);
712 ok(state
.wBeginYear
== 2000, "got %u\n", state
.wBeginYear
);
713 ok(state
.TriggerType
== TASK_TIME_TRIGGER_DAILY
, "got %u\n", state
.TriggerType
);
715 ref
= ITaskTrigger_Release(trigger0
);
716 ok(ref
== 0, "got %u\n", ref
);
717 ref
= ITaskTrigger_Release(trigger1
);
718 ok(ref
== 0, "got %u\n", ref
);
720 ok(obj_refcount(task
) == 1, "got %u\n", obj_refcount(task
));
722 hr
= get_task_trigger(task
, 0, &state
);
723 ok(hr
== S_OK
, "got %#x\n", hr
);
724 ok(state
.wBeginYear
== 3000, "got %u\n", state
.wBeginYear
);
725 ok(state
.TriggerType
== TASK_TIME_TRIGGER_ONCE
, "got %u\n", state
.TriggerType
);
727 hr
= get_task_trigger(task
, 1, &state
);
728 ok(hr
== S_OK
, "got %#x\n", hr
);
729 ok(state
.wBeginYear
== 2000, "got %u\n", state
.wBeginYear
);
730 ok(state
.TriggerType
== TASK_TIME_TRIGGER_DAILY
, "got %u\n", state
.TriggerType
);
732 hr
= ITask_GetTrigger(task
, 0, &trigger0
);
733 ok(hr
== S_OK
, "got %#x\n", hr
);
734 hr
= ITask_GetTrigger(task
, 1, &trigger1
);
735 ok(hr
== S_OK
, "got %#x\n", hr
);
737 hr
= ITask_DeleteTrigger(task
, 0);
738 ok(hr
== S_OK
, "got %#x\n", hr
);
740 hr
= get_task_trigger(task
, 0, &state
);
741 ok(hr
== S_OK
, "got %#x\n", hr
);
742 ok(state
.wBeginYear
== 2000, "got %u\n", state
.wBeginYear
);
743 ok(state
.TriggerType
== TASK_TIME_TRIGGER_DAILY
, "got %u\n", state
.TriggerType
);
745 hr
= get_task_trigger(task
, 1, &state
);
746 ok(hr
== SCHED_E_TRIGGER_NOT_FOUND
, "got %#x\n", hr
);
748 hr
= ITaskTrigger_SetTrigger(trigger0
, &state0
);
749 ok(hr
== S_OK
, "got %#x\n", hr
);
751 hr
= ITaskTrigger_SetTrigger(trigger1
, &state1
);
752 ok(hr
== E_FAIL
, "got %#x\n", hr
);
755 hr
= ITask_GetTriggerCount(task
, &count
);
756 ok(hr
== S_OK
, "got %#x\n", hr
);
757 ok(count
== 1, "got %u\n", count
);
759 ok(obj_refcount(task
) == 3, "got %u\n", obj_refcount(task
));
761 ref
= ITaskTrigger_Release(trigger0
);
762 ok(ref
== 0, "got %u\n", ref
);
764 ref
= ITaskTrigger_Release(trigger1
);
765 ok(ref
== 0, "got %u\n", ref
);
767 ref
= ITask_Release(task
);
768 ok(ref
== 0, "got %u\n", ref
);
771 START_TEST(task_trigger
)
777 hr
= CoCreateInstance(&CLSID_CTaskScheduler
, NULL
, CLSCTX_INPROC_SERVER
,
778 &IID_ITaskScheduler
, (void **)&test_task_scheduler
);
779 ok(hr
== S_OK
, "error creating TaskScheduler instance %#x\n", hr
);
781 test_SetTrigger_GetTrigger();
783 test_GetNextRunTime();
784 test_trigger_manager();
786 ITaskScheduler_Release(test_task_scheduler
);