2 * Test suite for TaskScheduler 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
28 #include "wine/test.h"
30 static ITaskScheduler
*test_task_scheduler
;
32 static const WCHAR does_not_existW
[] = {'\\','\\','d','o','e','s','_','n','o','t','_','e','x','i','s','t',0};
34 static void test_NewWorkItem(void)
38 const WCHAR task_name
[] = {'T', 'e', 's', 't', 'i', 'n', 'g', 0};
41 /* Initialize a GUID that will not be a recognized CLSID or a IID */
42 CoCreateGuid(&GUID_BAD
);
44 /* Create TaskScheduler */
45 hres
= CoCreateInstance(&CLSID_CTaskScheduler
, NULL
, CLSCTX_INPROC_SERVER
,
46 &IID_ITaskScheduler
, (void **) &test_task_scheduler
);
47 ok(hres
== S_OK
, "CTaskScheduler CoCreateInstance failed: %08x\n", hres
);
50 skip("Failed to create task scheduler. Skipping tests.\n");
54 /* Test basic task creation */
55 hres
= ITaskScheduler_NewWorkItem(test_task_scheduler
, task_name
,
56 &CLSID_CTask
, &IID_ITask
, (IUnknown
**)&task
);
57 ok(hres
== S_OK
, "NewNetworkItem failed: %08x\n", hres
);
61 /* Task creation attempt using invalid work item class ID */
62 hres
= ITaskScheduler_NewWorkItem(test_task_scheduler
, task_name
,
63 &GUID_BAD
, &IID_ITask
, (IUnknown
**)&task
);
64 ok(hres
== CLASS_E_CLASSNOTAVAILABLE
,
65 "Expected CLASS_E_CLASSNOTAVAILABLE: %08x\n", hres
);
67 /* Task creation attempt using invalid interface ID */
68 hres
= ITaskScheduler_NewWorkItem(test_task_scheduler
, task_name
,
69 &CLSID_CTask
, &GUID_BAD
, (IUnknown
**)&task
);
70 ok(hres
== E_NOINTERFACE
, "Expected E_NOINTERFACE: %08x\n", hres
);
72 /* Task creation attempt using invalid work item class and interface ID */
73 hres
= ITaskScheduler_NewWorkItem(test_task_scheduler
, task_name
,
74 &GUID_BAD
, &GUID_BAD
, (IUnknown
**)&task
);
75 ok(hres
== CLASS_E_CLASSNOTAVAILABLE
,
76 "Expected CLASS_E_CLASSNOTAVAILABLE: %08x\n", hres
);
78 ITaskScheduler_Release(test_task_scheduler
);
82 static void test_Activate(void)
86 const WCHAR not_task_name
[] =
87 {'N', 'o', 'S', 'u', 'c', 'h', 'T', 'a', 's', 'k', 0};
89 /* Create TaskScheduler */
90 hres
= CoCreateInstance(&CLSID_CTaskScheduler
, NULL
, CLSCTX_INPROC_SERVER
,
91 &IID_ITaskScheduler
, (void **) &test_task_scheduler
);
92 ok(hres
== S_OK
, "CTaskScheduler CoCreateInstance failed: %08x\n", hres
);
95 skip("Failed to create task scheduler. Skipping tests.\n");
99 /* Attempt to activate a nonexistent task */
100 hres
= ITaskScheduler_Activate(test_task_scheduler
, not_task_name
,
101 &IID_ITask
, (IUnknown
**)&task
);
102 ok(hres
== COR_E_FILENOTFOUND
, "Expected COR_E_FILENOTFOUND: %08x\n", hres
);
104 ITaskScheduler_Release(test_task_scheduler
);
108 static void test_GetTargetComputer(void)
113 /* Create TaskScheduler */
114 hres
= CoCreateInstance(&CLSID_CTaskScheduler
, NULL
, CLSCTX_INPROC_SERVER
,
115 &IID_ITaskScheduler
, (void **) &test_task_scheduler
);
116 ok(hres
== S_OK
, "CTaskScheduler CoCreateInstance failed: %08x\n", hres
);
119 skip("Failed to create task scheduler.\n");
125 /* This crashes on w2k */
126 hres
= ITaskScheduler_GetTargetComputer(test_task_scheduler
, NULL
);
127 ok(hres
== E_INVALIDARG
, "got 0x%x (expected E_INVALIDARG)\n", hres
);
130 hres
= ITaskScheduler_GetTargetComputer(test_task_scheduler
, &oldname
);
131 ok((hres
== S_OK
) && oldname
&& oldname
[0] == '\\' && oldname
[1] == '\\' && oldname
[2],
132 "got 0x%x and %s (expected S_OK and an unc name)\n", hres
, wine_dbgstr_w(oldname
));
134 CoTaskMemFree(oldname
);
136 ITaskScheduler_Release(test_task_scheduler
);
140 static void test_SetTargetComputer(void)
142 WCHAR buffer
[MAX_COMPUTERNAME_LENGTH
+ 3]; /* extra space for two '\' and a zero */
143 DWORD len
= MAX_COMPUTERNAME_LENGTH
+ 1; /* extra space for a zero */
144 WCHAR
*oldname
= NULL
;
151 if (!GetComputerNameW(buffer
+ 2, &len
))
154 /* Create TaskScheduler */
155 hres
= CoCreateInstance(&CLSID_CTaskScheduler
, NULL
, CLSCTX_INPROC_SERVER
,
156 &IID_ITaskScheduler
, (void **) &test_task_scheduler
);
157 ok(hres
== S_OK
, "CTaskScheduler CoCreateInstance failed: %08x\n", hres
);
160 skip("Failed to create task scheduler. Skipping tests.\n");
164 hres
= ITaskScheduler_GetTargetComputer(test_task_scheduler
, &oldname
);
165 ok(hres
== S_OK
, "got 0x%x and %s (expected S_OK)\n", hres
, wine_dbgstr_w(oldname
));
167 /* NULL is an alias for the local computer */
168 hres
= ITaskScheduler_SetTargetComputer(test_task_scheduler
, NULL
);
169 ok(hres
== S_OK
, "got 0x%x (expected S_OK)\n", hres
);
170 hres
= ITaskScheduler_GetTargetComputer(test_task_scheduler
, &name
);
171 ok((hres
== S_OK
&& !lstrcmpiW(name
, buffer
)),
172 "got 0x%x with %s (expected S_OK and %s)\n",
173 hres
, wine_dbgstr_w(name
), wine_dbgstr_w(buffer
));
176 /* The name must be valid */
177 hres
= ITaskScheduler_SetTargetComputer(test_task_scheduler
, does_not_existW
);
178 ok(hres
== HRESULT_FROM_WIN32(ERROR_BAD_NETPATH
), "got 0x%x (expected 0x80070035)\n", hres
);
179 /* the name of the target computer is unchanged */
180 hres
= ITaskScheduler_GetTargetComputer(test_task_scheduler
, &name
);
181 ok((hres
== S_OK
&& !lstrcmpiW(name
, buffer
)),
182 "got 0x%x with %s (expected S_OK and %s)\n",
183 hres
, wine_dbgstr_w(name
), wine_dbgstr_w(buffer
));
186 /* the two backslashes are optional */
187 hres
= ITaskScheduler_SetTargetComputer(test_task_scheduler
, oldname
+ 2);
188 if (hres
== E_ACCESSDENIED
)
190 skip("SetTargetComputer failed with E_ACCESSDENIED (needs admin rights)\n");
193 ok(hres
== S_OK
, "got 0x%x (expected S_OK)\n", hres
);
195 /* the case is ignored */
197 hres
= ITaskScheduler_SetTargetComputer(test_task_scheduler
, buffer
);
198 ok(hres
== S_OK
, "got 0x%x (expected S_OK)\n", hres
);
200 hres
= ITaskScheduler_SetTargetComputer(test_task_scheduler
, buffer
);
201 ok(hres
== S_OK
, "got 0x%x (expected S_OK)\n", hres
);
204 hres
= ITaskScheduler_SetTargetComputer(test_task_scheduler
, oldname
);
205 ok(hres
== S_OK
, "got 0x%x (expected S_OK)\n", hres
);
208 CoTaskMemFree(oldname
);
209 ITaskScheduler_Release(test_task_scheduler
);
213 static void test_Enum(void)
215 static const WCHAR Task1
[] = { 'w','i','n','e','t','a','s','k','1',0 };
216 ITaskScheduler
*scheduler
;
218 IEnumWorkItems
*tasks
;
223 hr
= CoCreateInstance(&CLSID_CTaskScheduler
, NULL
, CLSCTX_INPROC_SERVER
,
224 &IID_ITaskScheduler
, (void **)&scheduler
);
225 ok(hr
== S_OK
, "got %#x\n", hr
);
227 /* cleanup after previous runs */
228 ITaskScheduler_Delete(scheduler
, Task1
);
230 hr
= ITaskScheduler_NewWorkItem(scheduler
, Task1
, &CLSID_CTask
, &IID_ITask
, (IUnknown
**)&task
);
231 ok(hr
== S_OK
, "got %#x\n", hr
);
232 hr
= ITaskScheduler_AddWorkItem(scheduler
, Task1
, (IScheduledWorkItem
*)task
);
233 ok(hr
== S_OK
, "got %#x\n", hr
);
237 hr
= ITaskScheduler_Enum(scheduler
, NULL
);
238 ok(hr
== E_INVALIDARG
, "got %#x\n", hr
);
240 hr
= ITaskScheduler_Enum(scheduler
, &tasks
);
241 ok(hr
== S_OK
, "got %#x\n", hr
);
243 names
= (void *)0xdeadbeef;
244 fetched
= 0xdeadbeef;
245 hr
= IEnumWorkItems_Next(tasks
, 0, &names
, &fetched
);
246 ok(hr
== E_INVALIDARG
, "got %#x\n", hr
);
247 ok(names
== (void *)0xdeadbeef, "got %p\n", names
);
248 ok(fetched
== 0xdeadbeef, "got %#x\n", fetched
);
250 hr
= IEnumWorkItems_Next(tasks
, 1, NULL
, NULL
);
251 ok(hr
== E_INVALIDARG
, "got %#x\n", hr
);
254 hr
= IEnumWorkItems_Next(tasks
, 1, &names
, NULL
);
255 ok(hr
== S_OK
, "got %#x\n", hr
);
256 ok(names
!= NULL
, "got NULL\n");
257 ok(names
[0] != NULL
, "got NULL\n");
258 CoTaskMemFree(names
[0]);
259 CoTaskMemFree(names
);
261 names
= (void *)0xdeadbeef;
262 hr
= IEnumWorkItems_Next(tasks
, 2, &names
, NULL
);
263 ok(hr
== E_INVALIDARG
, "got %#x\n", hr
);
264 ok(names
== (void *)0xdeadbeef, "got %p\n", names
);
266 hr
= IEnumWorkItems_Reset(tasks
);
267 ok(hr
== S_OK
, "got %#x\n", hr
);
270 fetched
= 0xdeadbeef;
271 hr
= IEnumWorkItems_Next(tasks
, 1, &names
, &fetched
);
272 ok(hr
== S_OK
, "got %#x\n", hr
);
273 ok(names
!= NULL
, "got NULL\n");
274 ok(names
[0] != NULL
, "got NULL\n");
275 ok(fetched
== 1, "got %u\n", fetched
);
276 CoTaskMemFree(names
[0]);
277 CoTaskMemFree(names
);
279 while (IEnumWorkItems_Skip(tasks
, 1) == S_OK
)
282 hr
= IEnumWorkItems_Skip(tasks
, 1);
283 ok(hr
== S_FALSE
, "got %#x\n", hr
);
285 names
= (void *)0xdeadbeef;
286 fetched
= 0xdeadbeef;
287 hr
= IEnumWorkItems_Next(tasks
, 1, &names
, &fetched
);
288 ok(hr
== S_FALSE
, "got %#x\n", hr
);
289 ok(names
== NULL
, "got %p\n", names
);
290 ok(fetched
== 0, "got %u\n", fetched
);
292 IEnumWorkItems_Release(tasks
);
294 hr
= ITaskScheduler_Delete(scheduler
, Task1
);
295 ok(hr
== S_OK
, "got %#x\n", hr
);
297 ITaskScheduler_Release(scheduler
);
300 static BOOL
file_exists(const WCHAR
*name
)
302 return GetFileAttributesW(name
) != INVALID_FILE_ATTRIBUTES
;
305 static void test_save_task_curfile(ITask
*task
)
311 hr
= ITask_QueryInterface(task
, &IID_IPersistFile
, (void **)&pfile
);
312 ok(hr
== S_OK
, "QueryInterface error %#x\n", hr
);
315 hr
= IPersistFile_GetCurFile(pfile
, &curfile
);
316 ok(hr
== S_OK
, "GetCurFile error %#x\n", hr
);
317 ok(curfile
&& curfile
[0], "curfile should not be NULL\n");
319 ok(file_exists(curfile
), "curfile should exist\n");
321 hr
= IPersistFile_Save(pfile
, curfile
, FALSE
);
322 ok(hr
== HRESULT_FROM_WIN32(ERROR_FILE_EXISTS
), "wrong error %#x\n", hr
);
324 hr
= IPersistFile_Save(pfile
, curfile
, TRUE
);
325 ok(hr
== HRESULT_FROM_WIN32(ERROR_FILE_EXISTS
), "wrong error %#x\n", hr
);
327 hr
= IPersistFile_Save(pfile
, NULL
, FALSE
);
328 ok(hr
== S_OK
, "Save error %#x\n", hr
);
330 hr
= IPersistFile_Save(pfile
, NULL
, TRUE
);
331 ok(hr
== S_OK
, "Save error %#x\n", hr
);
332 CoTaskMemFree(curfile
);
335 hr
= IPersistFile_GetCurFile(pfile
, &curfile
);
336 ok(hr
== S_OK
, "GetCurFile error %#x\n", hr
);
337 ok(curfile
&& curfile
[0] , "curfile should not be NULL\n");
338 CoTaskMemFree(curfile
);
340 IPersistFile_Release(pfile
);
343 static WCHAR
*get_task_curfile(ITask
*task
, BOOL should_exist
, BOOL is_dirty
, int line
)
350 hr
= ITask_QueryInterface(task
, &IID_IPersistFile
, (void **)&pfile
);
351 ok_(__FILE__
, line
)(hr
== S_OK
, "QueryInterface error %#x\n", hr
);
353 hr
= IPersistFile_IsDirty(pfile
);
354 ok_(__FILE__
, line
)(hr
== is_dirty
? S_OK
: S_FALSE
, "got %#x\n", hr
);
357 hr
= IPersistFile_GetCurFile(pfile
, &curfile
);
358 ok_(__FILE__
, line
)(hr
== S_OK
, "GetCurFile error %#x\n", hr
);
359 ok_(__FILE__
, line
)(curfile
&& curfile
[0] , "curfile should not be NULL\n");
361 hr
= IPersistFile_Load(pfile
, curfile
, STGM_READ
);
363 ok_(__FILE__
, line
)(hr
== S_OK
, "Load error %#x\n", hr
);
365 ok_(__FILE__
, line
)(hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), "wrong error %#x\n", hr
);
367 if (0) /* crashes under Windows */
368 hr
= IPersistFile_GetClassID(pfile
, NULL
);
370 hr
= IPersistFile_GetClassID(pfile
, &clsid
);
371 ok_(__FILE__
, line
)(hr
== S_OK
, "GetClassID error %#x\n", hr
);
372 ok_(__FILE__
, line
)(IsEqualCLSID(&clsid
, &CLSID_CTask
), "got %s\n", wine_dbgstr_guid(&clsid
));
374 IPersistFile_Release(pfile
);
379 static void test_task_storage(void)
381 static const WCHAR Task1
[] = { 'w','i','n','e','t','a','s','k','1',0 };
382 static const WCHAR Task2
[] = { 'w','i','n','e','t','a','s','k','2',0 };
383 static const WCHAR Task3
[] = { 'w','i','n','e','t','a','s','k','3',0 };
384 static const WCHAR Task1_ext
[] = { 'w','i','n','e','t','a','s','k','.','e','x','t',0 };
385 static const WCHAR Task1_job
[] = { '\\','T','a','s','k','s','\\','w','i','n','e','t','a','s','k','1','.','j','o','b',0 };
386 static const WCHAR Task2_job
[] = { '\\','T','a','s','k','s','\\','w','i','n','e','t','a','s','k','2','.','j','o','b',0 };
387 static const WCHAR Task3_job
[] = { '\\','T','a','s','k','s','\\','w','i','n','e','t','a','s','k','3','.','j','o','b',0 };
388 WCHAR task1_full_name
[MAX_PATH
], task2_full_name
[MAX_PATH
], task3_full_name
[MAX_PATH
];
390 ITaskScheduler
*scheduler
;
392 WCHAR
*curfile
, *curfile2
;
394 GetWindowsDirectoryW(task1_full_name
, MAX_PATH
);
395 lstrcatW(task1_full_name
, Task1_job
);
396 GetWindowsDirectoryW(task2_full_name
, MAX_PATH
);
397 lstrcatW(task2_full_name
, Task2_job
);
398 GetWindowsDirectoryW(task3_full_name
, MAX_PATH
);
399 lstrcatW(task3_full_name
, Task3_job
);
401 /* cleanup after previous runs */
402 DeleteFileW(task1_full_name
);
403 DeleteFileW(task2_full_name
);
404 DeleteFileW(task3_full_name
);
406 hr
= CoCreateInstance(&CLSID_CTaskScheduler
, NULL
, CLSCTX_INPROC_SERVER
, &IID_ITaskScheduler
, (void **)&scheduler
);
409 win_skip("CoCreateInstance(CLSID_CTaskScheduler) error %#x\n", hr
);
413 hr
= ITaskScheduler_Delete(scheduler
, Task1_ext
);
414 ok(hr
== E_INVALIDARG
, "wrong error %#x\n", hr
);
416 hr
= ITaskScheduler_Delete(scheduler
, Task1
);
417 ok(hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), "wrong error %#x\n", hr
);
419 hr
= ITaskScheduler_NewWorkItem(scheduler
, Task1_ext
, &CLSID_CTask
, &IID_ITask
, (IUnknown
**)&task
);
420 ok(hr
== E_INVALIDARG
, "wrong error %#x\n", hr
);
422 hr
= ITaskScheduler_NewWorkItem(scheduler
, Task1
, &CLSID_CTask
, &IID_ITask
, (IUnknown
**)&task
);
423 ok(hr
== S_OK
, "NewWorkItem error %#x\n", hr
);
425 curfile
= get_task_curfile(task
, FALSE
, FALSE
, __LINE__
);
426 ok(!file_exists(curfile
), "curfile should not exist\n");
427 ok(!lstrcmpW(curfile
, task1_full_name
), "name is wrong %s\n", wine_dbgstr_w(curfile
));
429 hr
= ITask_SetComment(task
, Task1
);
430 ok(hr
== S_OK
, "got %#x\n", hr
);
432 curfile2
= get_task_curfile(task
, FALSE
, TRUE
, __LINE__
);
433 ok(!file_exists(curfile2
), "curfile should not exist\n");
434 ok(!lstrcmpW(curfile2
, task1_full_name
), "name is wrong %s\n", wine_dbgstr_w(curfile2
));
435 CoTaskMemFree(curfile2
);
437 hr
= ITaskScheduler_NewWorkItem(scheduler
, Task1
, &CLSID_CTask
, &IID_ITask
, (IUnknown
**)&task2
);
438 ok(hr
== S_OK
, "NewWorkItem error %#x\n", hr
);
439 ok(task2
!= task
, "tasks should not be equal\n");
441 curfile2
= get_task_curfile(task2
, FALSE
, FALSE
, __LINE__
);
442 ok(!file_exists(curfile2
), "curfile2 should not exist\n");
443 ok(!lstrcmpW(curfile2
, task1_full_name
), "name is wrong %s\n", wine_dbgstr_w(curfile2
));
445 CoTaskMemFree(curfile
);
446 CoTaskMemFree(curfile2
);
447 ITask_Release(task2
);
449 task2
= (ITask
*)0xdeadbeef;
450 hr
= ITaskScheduler_Activate(scheduler
, Task1
, &IID_ITask
, (IUnknown
**)&task2
);
451 ok(hr
== HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
), "wrong error %#x\n", hr
);
452 ok(task2
== (ITask
*)0xdeadbeef, "task should not be set to NULL\n");
454 hr
= ITaskScheduler_AddWorkItem(scheduler
, Task2
, (IScheduledWorkItem
*)task
);
455 ok(hr
== S_OK
, "AddWorkItem error %#x\n", hr
);
456 curfile
= get_task_curfile(task
, TRUE
, FALSE
, __LINE__
);
457 ok(file_exists(curfile
), "curfile should exist\n");
458 ok(!lstrcmpW(curfile
, task2_full_name
), "name is wrong %s\n", wine_dbgstr_w(curfile
));
459 CoTaskMemFree(curfile
);
461 hr
= ITaskScheduler_AddWorkItem(scheduler
, Task3
, (IScheduledWorkItem
*)task
);
462 ok(hr
== S_OK
, "AddWorkItem error %#x\n", hr
);
463 curfile
= get_task_curfile(task
, TRUE
, FALSE
, __LINE__
);
464 ok(file_exists(curfile
), "curfile should exist\n");
465 ok(!lstrcmpW(curfile
, task3_full_name
), "name is wrong %s\n", wine_dbgstr_w(curfile
));
466 CoTaskMemFree(curfile
);
468 hr
= ITaskScheduler_AddWorkItem(scheduler
, Task1
, (IScheduledWorkItem
*)task
);
469 ok(hr
== S_OK
, "AddWorkItem error %#x\n", hr
);
470 curfile
= get_task_curfile(task
, TRUE
, FALSE
, __LINE__
);
471 ok(file_exists(curfile
), "curfile should exist\n");
472 ok(!lstrcmpW(curfile
, task1_full_name
), "name is wrong %s\n", wine_dbgstr_w(curfile
));
473 CoTaskMemFree(curfile
);
475 hr
= ITaskScheduler_AddWorkItem(scheduler
, Task1
, (IScheduledWorkItem
*)task
);
476 ok(hr
== HRESULT_FROM_WIN32(ERROR_FILE_EXISTS
), "wrong error %#x\n", hr
);
478 curfile
= get_task_curfile(task
, TRUE
, FALSE
, __LINE__
);
479 ok(file_exists(curfile
), "curfile should exist\n");
481 CoTaskMemFree(curfile
);
485 hr
= ITaskScheduler_Activate(scheduler
, Task1
, &IID_ITask
, (IUnknown
**)&task
);
486 ok(hr
== S_OK
, "Activate error %#x\n", hr
);
487 ok(task
!= NULL
, "task should not be set to NULL\n");
489 curfile
= get_task_curfile(task
, TRUE
, FALSE
, __LINE__
);
490 ok(file_exists(curfile
), "curfile2 should exist\n");
491 ok(!lstrcmpW(curfile
, task1_full_name
), "name is wrong %s\n", wine_dbgstr_w(curfile
));
493 CoTaskMemFree(curfile
);
495 test_save_task_curfile(task
);
497 hr
= ITaskScheduler_Delete(scheduler
, Task1
);
498 ok(hr
== S_OK
, "got %#x\n", hr
);
499 hr
= ITaskScheduler_Delete(scheduler
, Task2
);
500 ok(hr
== S_OK
, "got %#x\n", hr
);
501 hr
= ITaskScheduler_Delete(scheduler
, Task3
);
502 ok(hr
== S_OK
, "got %#x\n", hr
);
505 ITaskScheduler_Release(scheduler
);
508 START_TEST(task_scheduler
)
515 test_GetTargetComputer();
516 test_SetTargetComputer();