Jacek Caban : schtests: Added /create command implementation.

Alexandre Julliard julliard at winehq.org
Fri Jan 19 15:43:21 CST 2018


Module: wine
Branch: master
Commit: 74b386d4a25d6823e2c7f5f03d52f299fac1fe7b
URL:    https://source.winehq.org/git/wine.git/?a=commit;h=74b386d4a25d6823e2c7f5f03d52f299fac1fe7b

Author: Jacek Caban <jacek at codeweavers.com>
Date:   Fri Jan 19 19:16:29 2018 +0100

schtests: Added /create command implementation.

Signed-off-by: Jacek Caban <jacek at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>

---

 programs/schtasks/schtasks.c       | 127 +++++++++++++++++++++++++++++++++++++
 programs/schtasks/tests/schtasks.c |  72 ++++++++++++++++-----
 2 files changed, 182 insertions(+), 17 deletions(-)

diff --git a/programs/schtasks/schtasks.c b/programs/schtasks/schtasks.c
index 88a004f..5967e4a 100644
--- a/programs/schtasks/schtasks.c
+++ b/programs/schtasks/schtasks.c
@@ -27,10 +27,12 @@
 WINE_DEFAULT_DEBUG_CHANNEL(schtasks);
 
 static const WCHAR change_optW[] = {'/','c','h','a','n','g','e',0};
+static const WCHAR create_optW[] = {'/','c','r','e','a','t','e',0};
 static const WCHAR delete_optW[] = {'/','d','e','l','e','t','e',0};
 static const WCHAR enable_optW[] = {'/','e','n','a','b','l','e',0};
 static const WCHAR f_optW[] = {'/','f',0};
 static const WCHAR tn_optW[] = {'/','t','n',0};
+static const WCHAR xml_optW[] = {'/','x','m','l',0};
 
 static ITaskFolder *get_tasks_root_folder(void)
 {
@@ -84,6 +86,51 @@ static IRegisteredTask *get_registered_task(const WCHAR *name)
     return registered_task;
 }
 
+static BSTR read_file_to_bstr(const WCHAR *file_name)
+{
+    LARGE_INTEGER file_size;
+    DWORD read_size, size;
+    unsigned char *data;
+    HANDLE file;
+    BOOL r = FALSE;
+    BSTR ret;
+
+    file = CreateFileW(file_name, GENERIC_READ, FILE_SHARE_READ, NULL,
+                       OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
+    if (file == INVALID_HANDLE_VALUE) {
+        FIXME("Could not open file\n");
+        return NULL;
+    }
+
+    if (!GetFileSizeEx(file, &file_size) || !file_size.QuadPart) {
+        FIXME("Empty file\n");
+        CloseHandle(file);
+        return NULL;
+    }
+
+    data = HeapAlloc(GetProcessHeap(), 0, file_size.QuadPart);
+    if (data)
+        r = ReadFile(file, data, file_size.QuadPart, &read_size, NULL);
+    CloseHandle(file);
+    if (!r) {
+        FIXME("Read filed\n");
+        HeapFree(GetProcessHeap(), 0, data);
+        return NULL;
+    }
+
+    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 {
+        size = MultiByteToWideChar(CP_ACP, 0, (const char *)data, read_size, NULL, 0);
+        ret = SysAllocStringLen(NULL, size);
+        if (ret)
+            MultiByteToWideChar(CP_ACP, 0, (const char *)data, read_size, ret, size);
+    }
+    HeapFree(GetProcessHeap(), 0, data);
+
+    return ret;
+}
+
 static int change_command(int argc, WCHAR *argv[])
 {
     const WCHAR *task_name;
@@ -132,6 +179,84 @@ static int change_command(int argc, WCHAR *argv[])
     return 0;
 }
 
+static int create_command(int argc, WCHAR *argv[])
+{
+    const WCHAR *task_name = NULL, *xml_file = NULL;
+    ITaskFolder *root = NULL;
+    IRegisteredTask *task;
+    VARIANT empty;
+    BSTR str, xml;
+    HRESULT hres;
+
+    while (argc) {
+        if (!strcmpiW(argv[0], xml_optW)) {
+            if (argc < 2) {
+                FIXME("Missing /xml value\n");
+                return 1;
+            }
+
+            if (xml_file) {
+                FIXME("Duplicated /xml argument\n");
+                return 1;
+            }
+
+            xml_file = argv[1];
+            argc -= 2;
+            argv += 2;
+        }else if(!strcmpiW(argv[0], tn_optW)) {
+            if (argc < 2) {
+                FIXME("Missing /tn value\n");
+                return 1;
+            }
+
+            if (task_name) {
+                FIXME("Duplicated /tn argument\n");
+                return 1;
+            }
+
+            task_name = argv[1];
+            argc -= 2;
+            argv += 2;
+        }else {
+            FIXME("Unsupported argument %s\n", debugstr_w(argv[0]));
+            return 1;
+        }
+    }
+
+    if (!task_name) {
+        FIXME("Missing /tn argument\n");
+        return 1;
+    }
+
+    if (!xml_file) {
+        FIXME("Missing /xml argument\n");
+        return E_FAIL;
+    }
+
+    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, TASK_CREATE, empty, empty,
+                                    TASK_LOGON_NONE, empty, &task);
+    SysFreeString(str);
+    SysFreeString(xml);
+    ITaskFolder_Release(root);
+    if (FAILED(hres))
+        return 1;
+
+    IRegisteredTask_Release(task);
+    return 0;
+}
+
 static int delete_command(int argc, WCHAR *argv[])
 {
     const WCHAR *task_name = NULL;
@@ -197,6 +322,8 @@ int wmain(int argc, WCHAR *argv[])
         FIXME("Print current tasks state\n");
     else if (!strcmpiW(argv[1], change_optW))
         ret = change_command(argc - 2, argv + 2);
+    else if (!strcmpiW(argv[1], create_optW))
+        ret = create_command(argc - 2, argv + 2);
     else if (!strcmpiW(argv[1], delete_optW))
         ret = delete_command(argc - 2, argv + 2);
     else
diff --git a/programs/schtasks/tests/schtasks.c b/programs/schtasks/tests/schtasks.c
index 7765038..9f1b920 100644
--- a/programs/schtasks/tests/schtasks.c
+++ b/programs/schtasks/tests/schtasks.c
@@ -26,6 +26,23 @@
 static ITaskService *service;
 static ITaskFolder *root;
 
+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";
+
 static WCHAR *a2w(const char *str)
 {
     WCHAR *ret;
@@ -81,23 +98,6 @@ static void _register_task(unsigned line, const char *task_name_a)
     WCHAR *task_name, *xml;
     HRESULT hres;
 
-    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";
-
     V_VT(&empty) = VT_EMPTY;
     task_name = a2w(task_name_a);
     xml = a2w(xml_a);
@@ -128,6 +128,23 @@ static void _unregister_task(unsigned line, const char *task_name_a)
     HeapFree(GetProcessHeap(), 0, task_name);
 }
 
+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);
+    ok(r, "WriteFile failed: %u\n", GetLastError());
+    CloseHandle(file);
+}
+
 static BOOL initialize_task_service(void)
 {
     VARIANT empty;
@@ -186,8 +203,29 @@ START_TEST(schtasks)
     r = run_command("schtasks /Change /tn wine\\test\\winetest /enable");
     ok(r == 1, "r = %u\n", r);
 
+    create_file("test.xml", xml_a);
+
+    r = run_command("schtasks /create /xml test.xml /tn wine\\winetest");
+    ok(r == 0, "r = %u\n", r);
+
+    r = run_command("schtasks /change /tn wine\\winetest /enable");
+    ok(r == 0, "r = %u\n", r);
+
+    r = run_command("schtasks /create /xml test.xml /tn wine\\winetest");
+    ok(r == 1, "r = %u\n", r); /* task already exists */
+
+    r = run_command("schtasks /create /tn wine\\winetest");
+    ok(r == E_FAIL, "r = %x\n", r); /* missing arguments */
+
+    r = run_command("schtasks /Delete /f /tn wine\\winetest");
+    ok(r == 0, "r = %u\n", r);
+
+    r = DeleteFileA("test.xml");
+    ok(r, "DeleteFileA failed: %u\n", GetLastError());
+
     ITaskFolder_DeleteFolder(root, wine_testW, 0);
     ITaskFolder_DeleteFolder(root, wineW, 0);
+
     ITaskFolder_Release(root);
     ITaskService_Release(service);
     CoUninitialize();




More information about the wine-cvs mailing list