2018-01-05 23:12:48 +01:00
|
|
|
/*
|
|
|
|
* Copyright 2018 Jacek Caban for CodeWeavers
|
|
|
|
*
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
|
|
* License as published by the Free Software Foundation; either
|
|
|
|
* version 2.1 of the License, or (at your option) any later version.
|
|
|
|
*
|
|
|
|
* This library is distributed in the hope that it will be useful,
|
|
|
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
|
|
* Lesser General Public License for more details.
|
|
|
|
*
|
|
|
|
* You should have received a copy of the GNU Lesser General Public
|
|
|
|
* License along with this library; if not, write to the Free Software
|
|
|
|
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
|
|
|
|
*/
|
|
|
|
|
|
|
|
#define COBJMACROS
|
|
|
|
|
|
|
|
#include "initguid.h"
|
|
|
|
#include "taskschd.h"
|
|
|
|
|
|
|
|
#include "wine/test.h"
|
|
|
|
|
|
|
|
static ITaskService *service;
|
|
|
|
static ITaskFolder *root;
|
|
|
|
|
2018-01-19 19:16:29 +01:00
|
|
|
static const char xml_a[] =
|
|
|
|
"<?xml version=\"1.0\"?>\n"
|
|
|
|
"<Task xmlns=\"http://schemas.microsoft.com/windows/2004/02/mit/task\">\n"
|
|
|
|
" <RegistrationInfo>\n"
|
|
|
|
" <Description>\"Task1\"</Description>\n"
|
|
|
|
" </RegistrationInfo>\n"
|
|
|
|
" <Settings>\n"
|
|
|
|
" <Enabled>false</Enabled>\n"
|
|
|
|
" <Hidden>false</Hidden>\n"
|
|
|
|
" </Settings>\n"
|
|
|
|
" <Actions>\n"
|
|
|
|
" <Exec>\n"
|
|
|
|
" <Command>\"task1.exe\"</Command>\n"
|
|
|
|
" </Exec>\n"
|
|
|
|
" </Actions>\n"
|
|
|
|
"</Task>\n";
|
|
|
|
|
2018-01-05 23:12:48 +01:00
|
|
|
static WCHAR *a2w(const char *str)
|
|
|
|
{
|
|
|
|
WCHAR *ret;
|
|
|
|
int len;
|
|
|
|
|
|
|
|
if(!str)
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
len = MultiByteToWideChar(CP_ACP, 0, str, -1, NULL, 0);
|
|
|
|
ret = HeapAlloc(GetProcessHeap(), 0, len*sizeof(WCHAR));
|
|
|
|
MultiByteToWideChar(CP_ACP, 0, str, -1, ret, len);
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define run_command(a) _run_command(__LINE__,a)
|
|
|
|
static DWORD _run_command(unsigned line, const char *cmd)
|
|
|
|
{
|
|
|
|
STARTUPINFOA si = {sizeof(STARTUPINFOA)};
|
|
|
|
PROCESS_INFORMATION pi;
|
|
|
|
char command[1024];
|
|
|
|
BOOL r;
|
|
|
|
DWORD ret;
|
|
|
|
|
|
|
|
si.dwFlags = STARTF_USESTDHANDLES;
|
|
|
|
si.hStdInput = INVALID_HANDLE_VALUE;
|
|
|
|
si.hStdOutput = INVALID_HANDLE_VALUE;
|
|
|
|
si.hStdError = INVALID_HANDLE_VALUE;
|
|
|
|
|
|
|
|
strcpy(command, cmd);
|
|
|
|
r = CreateProcessA(NULL, command, NULL, NULL, TRUE, 0, NULL, NULL, &si, &pi);
|
2022-02-03 12:04:34 +01:00
|
|
|
ok_(__FILE__,line)(r, "CreateProcess failed: %lu\n", GetLastError());
|
2018-01-05 23:12:48 +01:00
|
|
|
if(!r) return -1;
|
|
|
|
|
|
|
|
ret = WaitForSingleObject(pi.hProcess, 10000);
|
|
|
|
ok_(__FILE__,line)(ret == WAIT_OBJECT_0, "wait failed\n");
|
|
|
|
if (ret == WAIT_TIMEOUT)
|
|
|
|
TerminateProcess(pi.hProcess, -1);
|
|
|
|
|
|
|
|
r = GetExitCodeProcess(pi.hProcess, &ret);
|
2022-02-03 12:04:34 +01:00
|
|
|
ok_(__FILE__,line)(r, "GetExitCodeProcess failed: %lu\n", GetLastError());
|
2018-01-05 23:12:48 +01:00
|
|
|
|
|
|
|
CloseHandle(pi.hThread);
|
|
|
|
CloseHandle(pi.hProcess);
|
|
|
|
return ret;
|
|
|
|
}
|
|
|
|
|
|
|
|
#define register_task(a) _register_task(__LINE__,a)
|
|
|
|
static void _register_task(unsigned line, const char *task_name_a)
|
|
|
|
{
|
|
|
|
IRegisteredTask *task;
|
|
|
|
VARIANT empty;
|
|
|
|
WCHAR *task_name, *xml;
|
|
|
|
HRESULT hres;
|
|
|
|
|
|
|
|
V_VT(&empty) = VT_EMPTY;
|
|
|
|
task_name = a2w(task_name_a);
|
|
|
|
xml = a2w(xml_a);
|
|
|
|
|
|
|
|
/* make sure it's not registered */
|
|
|
|
ITaskFolder_DeleteTask(root, task_name, 0);
|
|
|
|
|
|
|
|
hres = ITaskFolder_RegisterTask(root, task_name, xml, TASK_CREATE, empty, empty,
|
|
|
|
TASK_LOGON_NONE, empty, &task);
|
2022-02-03 12:04:34 +01:00
|
|
|
ok_(__FILE__,line)(hres == S_OK, "RegisterTask failed: %08lx\n", hres);
|
2018-01-05 23:12:48 +01:00
|
|
|
HeapFree(GetProcessHeap(), 0, task_name);
|
|
|
|
HeapFree(GetProcessHeap(), 0, xml);
|
|
|
|
|
|
|
|
IRegisteredTask_Release(task);
|
|
|
|
}
|
|
|
|
|
|
|
|
#define unregister_task(a) _unregister_task(__LINE__,a)
|
|
|
|
static void _unregister_task(unsigned line, const char *task_name_a)
|
|
|
|
{
|
|
|
|
WCHAR *task_name;
|
|
|
|
HRESULT hres;
|
|
|
|
|
|
|
|
task_name = a2w(task_name_a);
|
|
|
|
|
|
|
|
hres = ITaskFolder_DeleteTask(root, task_name, 0);
|
2022-02-03 12:04:34 +01:00
|
|
|
ok_(__FILE__,line)(hres == S_OK, "DeleteTask failed: %08lx\n", hres);
|
2018-01-05 23:12:48 +01:00
|
|
|
|
|
|
|
HeapFree(GetProcessHeap(), 0, task_name);
|
|
|
|
}
|
|
|
|
|
2018-01-19 19:16:29 +01:00
|
|
|
static void create_file(const char *file_name, const char *data)
|
|
|
|
{
|
|
|
|
HANDLE file;
|
|
|
|
DWORD size;
|
|
|
|
BOOL r;
|
|
|
|
|
|
|
|
file = CreateFileA(file_name, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
|
|
|
|
FILE_ATTRIBUTE_NORMAL, NULL);
|
|
|
|
ok(file != INVALID_HANDLE_VALUE, "CreateFile failed\n");
|
|
|
|
if(file == INVALID_HANDLE_VALUE)
|
|
|
|
return;
|
|
|
|
|
|
|
|
r = WriteFile(file, data, strlen(data), &size, NULL);
|
2022-02-03 12:04:34 +01:00
|
|
|
ok(r, "WriteFile failed: %lu\n", GetLastError());
|
2018-01-19 19:16:29 +01:00
|
|
|
CloseHandle(file);
|
|
|
|
}
|
|
|
|
|
2018-01-05 23:12:48 +01:00
|
|
|
static BOOL initialize_task_service(void)
|
|
|
|
{
|
|
|
|
VARIANT empty;
|
|
|
|
HRESULT hres;
|
|
|
|
|
|
|
|
hres = CoCreateInstance(&CLSID_TaskScheduler, NULL, CLSCTX_INPROC_SERVER,
|
|
|
|
&IID_ITaskService, (void **)&service);
|
|
|
|
if(hres != S_OK) {
|
2022-02-03 12:04:34 +01:00
|
|
|
ok(hres == REGDB_E_CLASSNOTREG, "Could not create task service: %08lx\n", hres);
|
2018-01-05 23:12:48 +01:00
|
|
|
win_skip("Task service not available\n");
|
|
|
|
return FALSE;
|
|
|
|
}
|
|
|
|
|
|
|
|
V_VT(&empty) = VT_EMPTY;
|
|
|
|
hres = ITaskService_Connect(service, empty, empty, empty, empty);
|
2022-02-03 12:04:34 +01:00
|
|
|
ok(hres == S_OK, "Connect failed: %08lx\n", hres);
|
2018-01-05 23:12:48 +01:00
|
|
|
|
|
|
|
hres = ITaskService_GetFolder(service, NULL, &root);
|
2022-02-03 12:04:34 +01:00
|
|
|
ok(hres == S_OK, "GetFolder error %08lx\n", hres);
|
2018-01-05 23:12:48 +01:00
|
|
|
return TRUE;
|
|
|
|
}
|
|
|
|
|
|
|
|
START_TEST(schtasks)
|
|
|
|
{
|
2020-10-20 00:31:42 +02:00
|
|
|
static WCHAR wineW[] = L"\\wine";
|
|
|
|
static WCHAR wine_testW[] = L"\\wine\\test";
|
2018-01-05 23:12:48 +01:00
|
|
|
DWORD r;
|
|
|
|
|
|
|
|
CoInitialize(NULL);
|
|
|
|
if(!initialize_task_service()) {
|
|
|
|
CoUninitialize();
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
r = run_command("schtasks");
|
2022-02-03 12:04:34 +01:00
|
|
|
ok(r == 0, "r = %lu\n", r);
|
2018-01-05 23:12:48 +01:00
|
|
|
|
|
|
|
register_task("winetest");
|
|
|
|
|
|
|
|
r = run_command("schtasks /change /tn winetest /enable");
|
2022-02-03 12:04:34 +01:00
|
|
|
ok(r == 0, "r = %lu\n", r);
|
2018-01-05 23:12:48 +01:00
|
|
|
|
|
|
|
unregister_task("winetest");
|
|
|
|
|
|
|
|
r = run_command("schtasks /change /tn winetest /enable");
|
2022-02-03 12:04:34 +01:00
|
|
|
ok(r == 1, "r = %lu\n", r);
|
2018-01-05 23:12:48 +01:00
|
|
|
|
|
|
|
register_task("wine\\test\\winetest");
|
|
|
|
|
2018-01-09 13:08:06 +01:00
|
|
|
r = run_command("schtasks /CHANGE /tn wine\\test\\winetest /enable");
|
2022-02-03 12:04:34 +01:00
|
|
|
ok(r == 0, "r = %lu\n", r);
|
2018-01-05 23:12:48 +01:00
|
|
|
|
2018-01-19 19:16:20 +01:00
|
|
|
r = run_command("schtasks /delete /f /tn wine\\test\\winetest");
|
2022-02-03 12:04:34 +01:00
|
|
|
ok(r == 0, "r = %lu\n", r);
|
2018-01-05 23:12:48 +01:00
|
|
|
|
2018-01-09 13:08:06 +01:00
|
|
|
r = run_command("schtasks /Change /tn wine\\test\\winetest /enable");
|
2022-02-03 12:04:34 +01:00
|
|
|
ok(r == 1, "r = %lu\n", r);
|
2018-01-05 23:12:48 +01:00
|
|
|
|
2018-01-19 19:16:29 +01:00
|
|
|
create_file("test.xml", xml_a);
|
|
|
|
|
|
|
|
r = run_command("schtasks /create /xml test.xml /tn wine\\winetest");
|
2022-02-03 12:04:34 +01:00
|
|
|
ok(r == 0, "r = %lu\n", r);
|
2018-01-19 19:16:29 +01:00
|
|
|
|
|
|
|
r = run_command("schtasks /change /tn wine\\winetest /enable");
|
2022-02-03 12:04:34 +01:00
|
|
|
ok(r == 0, "r = %lu\n", r);
|
2018-01-19 19:16:29 +01:00
|
|
|
|
2018-01-22 17:35:55 +01:00
|
|
|
r = run_command("schtasks /create /xml test.xml /f /tn wine\\winetest");
|
2022-02-03 12:04:34 +01:00
|
|
|
ok(r == 0, "r = %lu\n", r); /* task already exists, but /f argument provided */
|
2018-01-22 17:35:55 +01:00
|
|
|
|
2018-01-19 19:16:29 +01:00
|
|
|
r = run_command("schtasks /create /xml test.xml /tn wine\\winetest");
|
2022-02-03 12:04:34 +01:00
|
|
|
ok(r == 1, "r = %lu\n", r); /* task already exists */
|
2018-01-19 19:16:29 +01:00
|
|
|
|
|
|
|
r = run_command("schtasks /create /tn wine\\winetest");
|
2022-02-03 12:04:34 +01:00
|
|
|
ok(r == E_FAIL, "r = %lx\n", r); /* missing arguments */
|
2018-01-19 19:16:29 +01:00
|
|
|
|
|
|
|
r = run_command("schtasks /Delete /f /tn wine\\winetest");
|
2022-02-03 12:04:34 +01:00
|
|
|
ok(r == 0, "r = %lu\n", r);
|
2018-01-19 19:16:29 +01:00
|
|
|
|
|
|
|
r = DeleteFileA("test.xml");
|
2022-02-03 12:04:34 +01:00
|
|
|
ok(r, "DeleteFileA failed: %lu\n", GetLastError());
|
2018-01-19 19:16:29 +01:00
|
|
|
|
2018-01-09 17:28:03 +01:00
|
|
|
ITaskFolder_DeleteFolder(root, wine_testW, 0);
|
|
|
|
ITaskFolder_DeleteFolder(root, wineW, 0);
|
2018-01-19 19:16:29 +01:00
|
|
|
|
2018-01-05 23:12:48 +01:00
|
|
|
ITaskFolder_Release(root);
|
|
|
|
ITaskService_Release(service);
|
|
|
|
CoUninitialize();
|
|
|
|
}
|