Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47152
This is initial part which ignores the options.
-- v14: schtasks: Stub implementation of /sc option in create command. schtasks: Ignore /tr /sc /rl options in create command. schtasks: Fix return codes and add new tests.
From: Vijay Kiran Kamuju infyquest@gmail.com
--- programs/schtasks/schtasks.c | 69 ++++++++++++++++-------------- programs/schtasks/tests/schtasks.c | 22 ++++++++++ 2 files changed, 58 insertions(+), 33 deletions(-)
diff --git a/programs/schtasks/schtasks.c b/programs/schtasks/schtasks.c index c9434801db8..10f17d7601b 100644 --- a/programs/schtasks/schtasks.c +++ b/programs/schtasks/schtasks.c @@ -111,7 +111,7 @@ static BSTR read_file_to_bstr(const WCHAR *file_name)
if (read_size > 2 && data[0] == 0xff && data[1] == 0xfe) { /* UTF-16 BOM */ ret = SysAllocStringLen((const WCHAR *)(data + 2), (read_size - 2) / sizeof(WCHAR)); - }else { + } else { size = MultiByteToWideChar(CP_ACP, 0, (const char *)data, read_size, NULL, 0); ret = SysAllocStringLen(NULL, size); if (ret) @@ -131,13 +131,13 @@ static int change_command(int argc, WCHAR *argv[])
while (argc) { if (!wcsicmp(argv[0], L"/tn")) { - if (argc < 2) { - FIXME("Missing /tn value\n"); + if (argc < 2 || !wcsncmp(argv[1], L"/", 1)) { + ERR("Missing /tn value\n"); return 1; }
if (task_name) { - FIXME("Duplicated /tn argument\n"); + ERR("Duplicated /tn argument\n"); return 1; }
@@ -150,8 +150,8 @@ static int change_command(int argc, WCHAR *argv[]) argc--; argv++; } else if (!wcsicmp(argv[0], L"/tr")) { - if (argc < 2) { - FIXME("Missing /tr value\n"); + if (argc < 2 || !wcsncmp(argv[1], L"/", 1)) { + ERR("Missing /tr value\n"); return 1; }
@@ -159,19 +159,19 @@ static int change_command(int argc, WCHAR *argv[]) have_option = TRUE; argc -= 2; argv += 2; - }else { + } else { FIXME("Unsupported arguments %s\n", debugstr_w(argv[0])); return 1; } }
if (!task_name) { - FIXME("Missing /tn option\n"); + ERR("Missing /tn option\n"); return 1; }
if (!have_option) { - FIXME("Missing change options\n"); + ERR("Missing change options\n"); return 1; }
@@ -204,28 +204,28 @@ static int create_command(int argc, WCHAR *argv[])
while (argc) { if (!wcsicmp(argv[0], L"/xml")) { - if (argc < 2) { - FIXME("Missing /xml value\n"); - return 1; + if (argc < 2 || !wcsncmp(argv[1], L"/", 1)) { + ERR("Missing /xml value\n"); + return E_FAIL; }
if (xml_file) { - FIXME("Duplicated /xml argument\n"); - return 1; + ERR("Duplicated /xml argument\n"); + return E_FAIL; }
xml_file = argv[1]; argc -= 2; argv += 2; } else if (!wcsicmp(argv[0], L"/tn")) { - if (argc < 2) { - FIXME("Missing /tn value\n"); - return 1; + if (argc < 2 || !wcsncmp(argv[1], L"/", 1)) { + ERR("Missing /tn value\n"); + return E_FAIL; }
if (task_name) { - FIXME("Duplicated /tn argument\n"); - return 1; + ERR("Duplicated /tn argument\n"); + return E_FAIL; }
task_name = argv[1]; @@ -236,33 +236,33 @@ static int create_command(int argc, WCHAR *argv[]) argc--; argv++; } else if (!wcsicmp(argv[0], L"/ru")) { - if (argc < 2) { - FIXME("Missing /ru value\n"); - return 1; + if (argc < 2 || !wcsncmp(argv[1], L"/", 1)) { + ERR("Missing /ru value\n"); + return E_FAIL; }
FIXME("Unsupported /ru option %s\n", debugstr_w(argv[1])); argc -= 2; argv += 2; - }else { + } else { FIXME("Unsupported argument %s\n", debugstr_w(argv[0])); - return 1; + return E_FAIL; } }
if (!task_name) { - FIXME("Missing /tn argument\n"); - return 1; + ERR("Missing /tn argument\n"); + return E_FAIL; }
if (!xml_file) { - FIXME("Missing /xml argument\n"); + ERR("Missing /xml argument\n"); return E_FAIL; }
xml = read_file_to_bstr(xml_file); if (!xml) - return 1; + return E_FAIL;
root = get_tasks_root_folder(); if (!root) { @@ -297,27 +297,27 @@ static int delete_command(int argc, WCHAR *argv[]) argc--; argv++; } else if (!wcsicmp(argv[0], L"/tn")) { - if (argc < 2) { - FIXME("Missing /tn value\n"); + if (argc < 2 || !wcsncmp(argv[1], L"/", 1)) { + ERR("Missing /tn value\n"); return 1; }
if (task_name) { - FIXME("Duplicated /tn argument\n"); + ERR("Duplicated /tn argument\n"); return 1; }
task_name = argv[1]; argc -= 2; argv += 2; - }else { + } else { FIXME("Unsupported argument %s\n", debugstr_w(argv[0])); return 1; } }
if (!task_name) { - FIXME("Missing /tn argument\n"); + ERR("Missing /tn argument\n"); return 1; }
@@ -354,7 +354,10 @@ int __cdecl wmain(int argc, WCHAR *argv[]) else if (!wcsicmp(argv[1], L"/delete")) ret = delete_command(argc - 2, argv + 2); else + { FIXME("Unsupported command %s\n", debugstr_w(argv[1])); + ret = 1; + }
CoUninitialize(); return ret; diff --git a/programs/schtasks/tests/schtasks.c b/programs/schtasks/tests/schtasks.c index 3ed2378c90c..e896449fa32 100644 --- a/programs/schtasks/tests/schtasks.c +++ b/programs/schtasks/tests/schtasks.c @@ -222,11 +222,17 @@ START_TEST(schtasks) r = run_command("schtasks"); ok(r == 0, "r = %lu\n", r);
+ r = run_command("schtasks /wine"); + ok(r == 1, "r = %lu\n", r); + register_task("winetest");
r = run_command("schtasks /change /tn winetest /enable"); ok(r == 0, "r = %lu\n", r);
+ r = run_command("schtasks /change /tn winetest /tn /enable"); + ok(r == 1, "r = %lu\n", r); + unregister_task("winetest");
r = run_command("schtasks /change /tn winetest /enable"); @@ -237,6 +243,9 @@ START_TEST(schtasks) r = run_command("schtasks /CHANGE /tn wine\test\winetest /enable"); ok(r == 0, "r = %lu\n", r);
+ r = run_command("schtasks /delete /f /tn /tn wine\test\winetest"); + ok(r == 1, "r = %lu\n", r); + r = run_command("schtasks /delete /f /tn wine\test\winetest"); ok(r == 0, "r = %lu\n", r);
@@ -248,6 +257,18 @@ START_TEST(schtasks) r = run_command("schtasks /create /xml test.xml /tn wine\winetest"); ok(r == 0, "r = %lu\n", r);
+ r = run_command("schtasks /create /xml test.xml /tn wine\winetest /tn"); + ok(r == E_FAIL, "r = %lx\n", r); /* missing arguments */ + + r = run_command("schtasks /create /xml test.xml /tn wine\winetest /xml"); + ok(r == E_FAIL, "r = %lx\n", r); /* missing arguments */ + + r = run_command("schtasks /create /xml test.xml /tn wine\winetest /tn test"); + ok(r == E_FAIL, "r = %lx\n", r); /* duplicate arguments */ + + r = run_command("schtasks /create /xml test.xml /tn wine\winetest /xml empty.xml"); + ok(r == E_FAIL, "r = %lx\n", r); /* duplicate arguments */ + r = run_command("schtasks /change /tn wine\winetest /enable"); ok(r == 0, "r = %lu\n", r);
@@ -268,6 +289,7 @@ START_TEST(schtasks)
r = ITaskFolder_DeleteFolder(root, wine_testW, 0); ok(r == S_OK, "DeleteFolder(\wine\test) failed: %lx\n", r); + r = ITaskFolder_DeleteFolder(root, wineW, 0); ok(r == S_OK, "DeleteFolder(\wine) failed: %lx\n", r);
From: Vijay Kiran Kamuju infyquest@gmail.com
--- programs/schtasks/schtasks.c | 109 +++++++++++++++++++++++------ programs/schtasks/tests/schtasks.c | 22 +++++- 2 files changed, 107 insertions(+), 24 deletions(-)
diff --git a/programs/schtasks/schtasks.c b/programs/schtasks/schtasks.c index 10f17d7601b..bb52e7e7bc0 100644 --- a/programs/schtasks/schtasks.c +++ b/programs/schtasks/schtasks.c @@ -194,13 +194,14 @@ static int change_command(int argc, WCHAR *argv[])
static int create_command(int argc, WCHAR *argv[]) { - const WCHAR *task_name = NULL, *xml_file = NULL; + const WCHAR *task_name = NULL, *xml_file = NULL, *task_run = NULL, *schedule = NULL; ITaskFolder *root = NULL; LONG flags = TASK_CREATE; IRegisteredTask *task; VARIANT empty; BSTR str, xml; HRESULT hres; + BOOL xml_mode = FALSE, tr_mode = FALSE;
while (argc) { if (!wcsicmp(argv[0], L"/xml")) { @@ -215,6 +216,7 @@ static int create_command(int argc, WCHAR *argv[]) }
xml_file = argv[1]; + xml_mode = TRUE; argc -= 2; argv += 2; } else if (!wcsicmp(argv[0], L"/tn")) { @@ -231,6 +233,48 @@ static int create_command(int argc, WCHAR *argv[]) task_name = argv[1]; argc -= 2; argv += 2; + } else if (!wcsicmp(argv[0], L"/tr")) { + if (argc < 2 || !wcsncmp(argv[1], L"/", 1)) { + ERR("Missing /tr value\n"); + return E_FAIL; + } + + if (task_run) { + ERR("Duplicated /tr argument\n"); + return E_FAIL; + } + + FIXME("Unsupported /tr option %s\n", debugstr_w(argv[1])); + task_run = argv[1]; + tr_mode = TRUE; + argc -= 2; + argv += 2; + } else if (!wcsicmp(argv[0], L"/sc")) { + if (argc < 2 || !wcsncmp(argv[1], L"/", 1)) { + ERR("Missing /sc value\n"); + return E_FAIL; + } + + if (schedule) { + ERR("Duplicated /sc argument\n"); + return E_FAIL; + } + + FIXME("Unsupported /sc option %s\n", debugstr_w(argv[1])); + schedule = argv[1]; + tr_mode = TRUE; + argc -= 2; + argv += 2; + } else if (!wcsicmp(argv[0], L"/rl")) { + if (argc < 2 || !wcsncmp(argv[1], L"/", 1)) { + ERR("Missing /rl value\n"); + return E_FAIL; + } + + FIXME("Unsupported /rl option %s\n", debugstr_w(argv[1])); + tr_mode = TRUE; + argc -= 2; + argv += 2; } else if (!wcsicmp(argv[0], L"/f")) { flags = TASK_CREATE_OR_UPDATE; argc--; @@ -255,33 +299,54 @@ static int create_command(int argc, WCHAR *argv[]) return E_FAIL; }
- if (!xml_file) { - ERR("Missing /xml argument\n"); - return E_FAIL; - } + if (xml_mode) { + if (tr_mode) { + ERR("/xml option can only be used with /ru /f /tn\n"); + return E_FAIL; + }
- xml = read_file_to_bstr(xml_file); - if (!xml) - return E_FAIL; + if (!xml_file) { + ERR("Missing /xml argument\n"); + return E_FAIL; + }
- root = get_tasks_root_folder(); - if (!root) { + xml = read_file_to_bstr(xml_file); + if (!xml) + return 1; + + root = get_tasks_root_folder(); + if (!root) { + SysFreeString(xml); + return 1; + } + + V_VT(&empty) = VT_EMPTY; + str = SysAllocString(task_name); + hres = ITaskFolder_RegisterTask(root, str, xml, flags, empty, empty, + TASK_LOGON_NONE, empty, &task); + SysFreeString(str); SysFreeString(xml); - return 1; + ITaskFolder_Release(root); + if (FAILED(hres)) + return 1; + + IRegisteredTask_Release(task); + return 0; }
- V_VT(&empty) = VT_EMPTY; - str = SysAllocString(task_name); - hres = ITaskFolder_RegisterTask(root, str, xml, flags, empty, empty, - TASK_LOGON_NONE, empty, &task); - SysFreeString(str); - SysFreeString(xml); - ITaskFolder_Release(root); - if (FAILED(hres)) - return 1; + if (tr_mode) { + if (!task_run) { + ERR("Missing /tr argument\n"); + return E_FAIL; + }
- IRegisteredTask_Release(task); - return 0; + if (!schedule) { + ERR("Missing /sc argument\n"); + return E_FAIL; + } + return 0; + } + return E_FAIL; }
static int delete_command(int argc, WCHAR *argv[]) diff --git a/programs/schtasks/tests/schtasks.c b/programs/schtasks/tests/schtasks.c index e896449fa32..248dd1b8c1e 100644 --- a/programs/schtasks/tests/schtasks.c +++ b/programs/schtasks/tests/schtasks.c @@ -269,20 +269,38 @@ START_TEST(schtasks) r = run_command("schtasks /create /xml test.xml /tn wine\winetest /xml empty.xml"); ok(r == E_FAIL, "r = %lx\n", r); /* duplicate arguments */
+ r = run_command("schtasks /create /xml test.xml /tn wine\winetest /tr c:\windows\hh.exe"); + ok(r == E_FAIL, "r = %lu\n", r); + r = run_command("schtasks /change /tn wine\winetest /enable"); ok(r == 0, "r = %lu\n", r);
r = run_command("schtasks /create /xml test.xml /f /tn wine\winetest"); ok(r == 0, "r = %lu\n", r); /* task already exists, but /f argument provided */
+ r = run_command("schtasks /create /xml test.xml /f /tn wine\winetest /tr c:\windows\hh.exe"); + ok(r == E_FAIL, "r = %lu\n", r); /* tr argument provided along with xml argument */ + r = run_command("schtasks /create /xml test.xml /tn wine\winetest"); ok(r == 1, "r = %lu\n", r); /* task already exists */
+ r = run_command("schtasks /Delete /f /tn wine\winetest"); + ok(r == 0, "r = %lu\n", r); + r = run_command("schtasks /create /tn wine\winetest"); ok(r == E_FAIL, "r = %lx\n", r); /* missing arguments */
- r = run_command("schtasks /Delete /f /tn wine\winetest"); - ok(r == 0, "r = %lu\n", r); + r = run_command("schtasks /create /tn wine\winetest /tr c:\windows\hh.exe"); + ok(r == E_FAIL, "r = %lx\n", r); /* missing arguments */ + + r = run_command("schtasks /create /tn wine\winetest /tr c:\windows\hh.exe /sc wine"); + ok(r == E_FAIL, "r = %lx\n", r); /* invalid schedule */ + + r = run_command("schtasks /create /tn wine\winetest /tr c:\windows\hh.exe /sc daily"); + todo_wine ok(r == 0, "r = %lx\n", r); /* daily schedule */ + + r = run_command("schtasks /DELETE /f /tn wine\winetest"); + todo_wine ok(r == 0, "r = %lu\n", r);
r = DeleteFileA("test.xml"); ok(r, "DeleteFileA failed: %lu\n", GetLastError());
From: Vijay Kiran Kamuju infyquest@gmail.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=47152 --- programs/schtasks/schtasks.c | 27 +++++++++++++++++++++++++-- programs/schtasks/tests/schtasks.c | 26 +++++++++++++++++++++++--- 2 files changed, 48 insertions(+), 5 deletions(-)
diff --git a/programs/schtasks/schtasks.c b/programs/schtasks/schtasks.c index bb52e7e7bc0..a5be5ce3ec4 100644 --- a/programs/schtasks/schtasks.c +++ b/programs/schtasks/schtasks.c @@ -244,7 +244,6 @@ static int create_command(int argc, WCHAR *argv[]) return E_FAIL; }
- FIXME("Unsupported /tr option %s\n", debugstr_w(argv[1])); task_run = argv[1]; tr_mode = TRUE; argc -= 2; @@ -260,7 +259,6 @@ static int create_command(int argc, WCHAR *argv[]) return E_FAIL; }
- FIXME("Unsupported /sc option %s\n", debugstr_w(argv[1])); schedule = argv[1]; tr_mode = TRUE; argc -= 2; @@ -340,12 +338,37 @@ static int create_command(int argc, WCHAR *argv[]) return E_FAIL; }
+ FIXME("Unsupported /tr option %s\n", wine_dbgstr_w(task_run)); if (!schedule) { ERR("Missing /sc argument\n"); return E_FAIL; + } else if (!wcsicmp(schedule, L"minute")){ + FIXME("Unsupported /sc minute\n"); + } else if (!wcsicmp(schedule, L"hourly")){ + FIXME("Unsupported /sc hourly\n"); + } else if (!wcsicmp(schedule, L"daily")){ + FIXME("Unsupported /sc daily\n"); + } else if (!wcsicmp(schedule, L"weekly")){ + FIXME("Unsupported /sc weekly\n"); + } else if (!wcsicmp(schedule, L"monthly")){ + FIXME("Unsupported /sc monthly\n"); + } else if (!wcsicmp(schedule, L"once")){ + FIXME("Unsupported /sc once\n"); + } else if (!wcsicmp(schedule, L"onstart")){ + FIXME("Unsupported /sc onstart\n"); + } else if (!wcsicmp(schedule, L"onlogon")){ + FIXME("Unsupported /sc onlogon\n"); + } else if (!wcsicmp(schedule, L"onidle")){ + FIXME("Unsupported /sc onidle\n"); + } else if (!wcsicmp(schedule, L"onevent")){ + FIXME("Unsupported /sc onevent\n"); + } else { + ERR("Invalid schedule type %s\n", debugstr_w(schedule)); + return E_FAIL; } return 0; } + return E_FAIL; }
diff --git a/programs/schtasks/tests/schtasks.c b/programs/schtasks/tests/schtasks.c index 248dd1b8c1e..f92333af9f2 100644 --- a/programs/schtasks/tests/schtasks.c +++ b/programs/schtasks/tests/schtasks.c @@ -254,8 +254,16 @@ START_TEST(schtasks)
create_file("test.xml", xml_a);
- r = run_command("schtasks /create /xml test.xml /tn wine\winetest"); - ok(r == 0, "r = %lu\n", r); + create_file("empty.xml", ""); + + r = run_command("schtasks /create /xml test.xml"); + ok(r == E_FAIL, "r = %lx\n", r); /* missing arguments */ + + r = run_command("schtasks /create /xml test.xml /tn"); + ok(r == E_FAIL, "r = %lx\n", r); /* missing arguments */ + + r = run_command("schtasks /create /xml /tn wine\winetest"); + ok(r == E_FAIL, "r = %lx\n", r); /* missing arguments */
r = run_command("schtasks /create /xml test.xml /tn wine\winetest /tn"); ok(r == E_FAIL, "r = %lx\n", r); /* missing arguments */ @@ -269,6 +277,12 @@ START_TEST(schtasks) r = run_command("schtasks /create /xml test.xml /tn wine\winetest /xml empty.xml"); ok(r == E_FAIL, "r = %lx\n", r); /* duplicate arguments */
+ r = run_command("schtasks /create /xml test.xml /tn wine\winetest"); + ok(r == 0, "r = %lu\n", r); + + r = run_command("schtasks /create /xml empty.xml /tn wine\winetest"); + ok(r == 1, "r = %lu\n", r); + r = run_command("schtasks /create /xml test.xml /tn wine\winetest /tr c:\windows\hh.exe"); ok(r == E_FAIL, "r = %lu\n", r);
@@ -290,6 +304,9 @@ START_TEST(schtasks) r = run_command("schtasks /create /tn wine\winetest"); ok(r == E_FAIL, "r = %lx\n", r); /* missing arguments */
+ r = run_command("schtasks /create /tn"); + ok(r == E_FAIL, "r = %lx\n", r); /* missing arguments */ + r = run_command("schtasks /create /tn wine\winetest /tr c:\windows\hh.exe"); ok(r == E_FAIL, "r = %lx\n", r); /* missing arguments */
@@ -297,11 +314,14 @@ START_TEST(schtasks) ok(r == E_FAIL, "r = %lx\n", r); /* invalid schedule */
r = run_command("schtasks /create /tn wine\winetest /tr c:\windows\hh.exe /sc daily"); - todo_wine ok(r == 0, "r = %lx\n", r); /* daily schedule */ + ok(r == 0, "r = %lx\n", r); /* daily schedule */
r = run_command("schtasks /DELETE /f /tn wine\winetest"); todo_wine ok(r == 0, "r = %lu\n", r);
+ r = DeleteFileA("empty.xml"); + ok(r, "DeleteFileA failed: %lu\n", GetLastError()); + r = DeleteFileA("test.xml"); ok(r, "DeleteFileA failed: %lu\n", GetLastError());
On Wed Feb 28 06:57:50 2024 +0000, Vijay Kiran Kamuju wrote:
I just followed the existing pattern in the code. I can change it to a WARN, but it needs to be changed a lot places in this program and it warrants a separate MR as we also need to change how the errors are shown on command line and error messages dont match the native windows.
I have changed the FIXME's to ERR's as they are actually error messages.
This needs to use some kind of table, both in the code and in the tests, instead of copy/pasting the same thing a dozen times.