[2/4] taskschd: Implement task management using RPC APIs.

Dmitry Timoshkov dmitry at baikal.ru
Tue Apr 8 01:49:23 CDT 2014


---
 dlls/taskschd/folder.c           | 30 ++++++++++++++++++++----
 dlls/taskschd/regtask.c          | 49 ++++++++++++++++++++++++++++++++++++----
 dlls/taskschd/taskschd_private.h |  5 ++--
 dlls/taskschd/tests/scheduler.c  | 33 +++++++++------------------
 4 files changed, 84 insertions(+), 33 deletions(-)

diff --git a/dlls/taskschd/folder.c b/dlls/taskschd/folder.c
index d9b201e..c0eb1fb 100644
--- a/dlls/taskschd/folder.c
+++ b/dlls/taskschd/folder.c
@@ -202,7 +202,7 @@ static HRESULT WINAPI TaskFolder_CreateFolder(ITaskFolder *iface, BSTR path, VAR
     return hr;
 }
 
-static WCHAR *get_full_path(const WCHAR *parent, const WCHAR *path)
+WCHAR *get_full_path(const WCHAR *parent, const WCHAR *path)
 {
     static const WCHAR bslash[] = { '\\', 0 };
     WCHAR *folder_path;
@@ -262,12 +262,20 @@ static HRESULT WINAPI TaskFolder_DeleteFolder(ITaskFolder *iface, BSTR name, LON
 static HRESULT WINAPI TaskFolder_GetTask(ITaskFolder *iface, BSTR name, IRegisteredTask **task)
 {
     TaskFolder *folder = impl_from_ITaskFolder(iface);
+    ITaskDefinition *taskdef;
+    HRESULT hr;
 
     TRACE("%p,%s,%p\n", iface, debugstr_w(name), task);
 
     if (!task) return E_POINTER;
 
-    return RegisteredTask_create(folder->path, name, NULL, 0, task, FALSE);
+    hr = TaskDefinition_create(&taskdef);
+    if (hr != S_OK) return hr;
+
+    hr = RegisteredTask_create(folder->path, name, taskdef, 0, 0, task, FALSE);
+    if (hr != S_OK)
+        ITaskDefinition_Release(taskdef);
+    return hr;
 }
 
 static HRESULT WINAPI TaskFolder_GetTasks(ITaskFolder *iface, LONG flags, IRegisteredTaskCollection **tasks)
@@ -306,6 +314,8 @@ static HRESULT WINAPI TaskFolder_RegisterTask(ITaskFolder *iface, BSTR name, BST
                                               VARIANT user, VARIANT password, TASK_LOGON_TYPE logon,
                                               VARIANT sddl, IRegisteredTask **task)
 {
+    TaskFolder *folder = impl_from_ITaskFolder(iface);
+    IRegisteredTask *regtask = NULL;
     ITaskDefinition *taskdef;
     HRESULT hr;
 
@@ -314,14 +324,21 @@ static HRESULT WINAPI TaskFolder_RegisterTask(ITaskFolder *iface, BSTR name, BST
 
     if (!xml) return HRESULT_FROM_WIN32(RPC_X_NULL_REF_POINTER);
 
+    if (!task) task = ®task;
+
     hr = TaskDefinition_create(&taskdef);
     if (hr != S_OK) return hr;
 
     hr = ITaskDefinition_put_XmlText(taskdef, xml);
     if (hr == S_OK)
-        hr = ITaskFolder_RegisterTaskDefinition(iface, name, taskdef, flags, user, password, logon, sddl, task);
+        hr = RegisteredTask_create(folder->path, name, taskdef, flags, logon, task, TRUE);
+
+    if (hr != S_OK)
+        ITaskDefinition_Release(taskdef);
+
+    if (regtask)
+        IRegisteredTask_Release(regtask);
 
-    ITaskDefinition_Release(taskdef);
     return hr;
 }
 
@@ -344,7 +361,10 @@ static HRESULT WINAPI TaskFolder_RegisterTaskDefinition(ITaskFolder *iface, BSTR
 
     if (!task) task = ®task;
 
-    hr = RegisteredTask_create(folder->path, name, definition, logon, task, TRUE);
+    ITaskDefinition_AddRef(definition);
+    hr = RegisteredTask_create(folder->path, name, definition, flags, logon, task, TRUE);
+    if (hr != S_OK)
+        ITaskDefinition_Release(definition);
 
     if (regtask)
         IRegisteredTask_Release(regtask);
diff --git a/dlls/taskschd/regtask.c b/dlls/taskschd/regtask.c
index 8201304..bf50f4f 100644
--- a/dlls/taskschd/regtask.c
+++ b/dlls/taskschd/regtask.c
@@ -25,6 +25,7 @@
 #include "winreg.h"
 #include "objbase.h"
 #include "taskschd.h"
+#include "schrpc.h"
 #include "taskschd_private.h"
 
 #include "wine/unicode.h"
@@ -266,18 +267,58 @@ static const IRegisteredTaskVtbl RegisteredTask_vtbl =
     regtask_GetRunTimes
 };
 
-HRESULT RegisteredTask_create(const WCHAR *path, const WCHAR *name, ITaskDefinition *definition,
+HRESULT RegisteredTask_create(const WCHAR *path, const WCHAR *name, ITaskDefinition *definition, LONG flags,
                               TASK_LOGON_TYPE logon, IRegisteredTask **obj, BOOL create)
 {
+    WCHAR *full_name;
     RegisteredTask *regtask;
+    HRESULT hr;
+
+    full_name = get_full_path(path, name);
+    if (!full_name) return E_OUTOFMEMORY;
 
     regtask = heap_alloc(sizeof(*regtask));
-    if (!regtask) return E_OUTOFMEMORY;
+    if (!regtask)
+    {
+        heap_free(full_name);
+        return E_OUTOFMEMORY;
+    }
+
+    if (create)
+    {
+        WCHAR *actual_path = NULL;
+        TASK_XML_ERROR_INFO *error_info = NULL;
+        BSTR xml = NULL;
+
+        hr = ITaskDefinition_get_XmlText(definition, &xml);
+        if (hr != S_OK || (hr = SchRpcRegisterTask(full_name, xml, flags, NULL, logon, 0, NULL, &actual_path, &error_info)) != S_OK)
+        {
+            heap_free(full_name);
+            heap_free(regtask);
+            SysFreeString(xml);
+            return hr;
+        }
+        MIDL_user_free(actual_path);
+    }
+    else
+    {
+        static const WCHAR languages[] = { 0 };
+        DWORD count = 0;
+        WCHAR *xml = NULL;
+
+        hr = SchRpcRetrieveTask(full_name, languages, &count, &xml);
+        if (hr != S_OK || (hr = ITaskDefinition_put_XmlText(definition, xml)) != S_OK)
+        {
+            heap_free(full_name);
+            heap_free(regtask);
+            return hr;
+        }
+        MIDL_user_free(xml);
+    }
 
     regtask->IRegisteredTask_iface.lpVtbl = &RegisteredTask_vtbl;
-    regtask->path = heap_strdupW(path);
+    regtask->path = full_name;
     regtask->ref = 1;
-    ITaskDefinition_AddRef(definition);
     regtask->taskdef = definition;
     *obj = &regtask->IRegisteredTask_iface;
 
diff --git a/dlls/taskschd/taskschd_private.h b/dlls/taskschd/taskschd_private.h
index 1046e2f..053000f 100644
--- a/dlls/taskschd/taskschd_private.h
+++ b/dlls/taskschd/taskschd_private.h
@@ -25,10 +25,11 @@ HRESULT TaskService_create(void **obj) DECLSPEC_HIDDEN;
 HRESULT TaskDefinition_create(ITaskDefinition **obj) DECLSPEC_HIDDEN;
 HRESULT TaskFolder_create(const WCHAR *parent, const WCHAR *path, ITaskFolder **obj, BOOL create) DECLSPEC_HIDDEN;
 HRESULT TaskFolderCollection_create(const WCHAR *path, ITaskFolderCollection **obj) DECLSPEC_HIDDEN;
-HRESULT RegisteredTask_create(const WCHAR *path, const WCHAR *name, ITaskDefinition *definition, TASK_LOGON_TYPE logon,
-                              IRegisteredTask **obj, BOOL create) DECLSPEC_HIDDEN;
+HRESULT RegisteredTask_create(const WCHAR *path, const WCHAR *name, ITaskDefinition *definition, LONG flags,
+                              TASK_LOGON_TYPE logon, IRegisteredTask **obj, BOOL create) DECLSPEC_HIDDEN;
 HRESULT RegisteredTaskCollection_create(const WCHAR *path, IRegisteredTaskCollection **obj) DECLSPEC_HIDDEN;
 
+WCHAR *get_full_path(const WCHAR *parent, const WCHAR *path) DECLSPEC_HIDDEN;
 const char *debugstr_variant(const VARIANT *v) DECLSPEC_HIDDEN;
 
 static void *heap_alloc_zero(SIZE_T size) __WINE_ALLOC_SIZE(1);
diff --git a/dlls/taskschd/tests/scheduler.c b/dlls/taskschd/tests/scheduler.c
index 7f0669b..e0944fc 100644
--- a/dlls/taskschd/tests/scheduler.c
+++ b/dlls/taskschd/tests/scheduler.c
@@ -753,34 +753,25 @@ static void test_GetTask(void)
     ITaskFolder_DeleteTask(root, Wine_Task2, 0);
     ITaskFolder_DeleteFolder(root, Wine, 0);
 
-    if (0) /* FIXME: Uncomment once implemented */
-    {
-        hr = ITaskFolder_GetTask(root, Wine_Task1, &task1);
-        ok(hr == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), "expected ERROR_PATH_NOT_FOUND, got %#x\n", hr);
-    }
+    hr = ITaskFolder_GetTask(root, Wine_Task1, &task1);
+    ok(hr == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), "expected ERROR_PATH_NOT_FOUND, got %#x\n", hr);
+
     hr = ITaskFolder_CreateFolder(root, Wine, v_null, &folder);
     ok(hr == S_OK, "CreateFolder error %#x\n", hr);
 
-    if (0) /* FIXME: Uncomment once implemented */
-    {
-        hr = ITaskFolder_GetTask(root, Wine, &task1);
-        ok(hr == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), "expected ERROR_PATH_NOT_FOUND, got %#x\n", hr);
-    }
+    hr = ITaskFolder_GetTask(root, Wine, &task1);
+todo_wine
+    ok(hr == HRESULT_FROM_WIN32(ERROR_PATH_NOT_FOUND), "expected ERROR_PATH_NOT_FOUND, got %#x\n", hr);
 
     MultiByteToWideChar(CP_ACP, 0, xml1, -1, xmlW, sizeof(xmlW)/sizeof(xmlW[0]));
 
     for (i = 0; i < sizeof(create_new_task)/sizeof(create_new_task[0]); i++)
     {
         hr = ITaskFolder_RegisterTask(root, Wine_Task1, xmlW, create_new_task[i].flags, v_null, v_null, TASK_LOGON_NONE, v_null, &task1);
-/* FIXME: Remove once Wine is fixed */
-if (create_new_task[i].hr != S_OK) todo_wine
-        ok(hr == create_new_task[i].hr, "%d: expected %#x, got %#x\n", i, create_new_task[i].hr, hr);
-else
         ok(hr == create_new_task[i].hr, "%d: expected %#x, got %#x\n", i, create_new_task[i].hr, hr);
         if (hr == S_OK)
         {
             hr = ITaskFolder_DeleteTask(root, Wine_Task1, 0);
-todo_wine
             ok(hr == S_OK, "DeleteTask error %#x\n", hr);
         }
     }
@@ -799,11 +790,9 @@ todo_wine
     ok(hr == S_OK, "RegisterTask error %#x\n", hr);
 
     hr = ITaskFolder_RegisterTask(root, Wine_Task1, xmlW, TASK_CREATE, v_null, v_null, TASK_LOGON_NONE, v_null, &task1);
-todo_wine
     ok(hr == HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS), "expected ERROR_ALREADY_EXISTS, got %#x\n", hr);
 
     hr = ITaskFolder_RegisterTask(root, Wine_Task1, xmlW, 0, v_null, v_null, TASK_LOGON_NONE, v_null, NULL);
-todo_wine
     ok(hr == HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS), "expected ERROR_ALREADY_EXISTS, got %#x\n", hr);
 
     hr = ITaskFolder_RegisterTask(root, Wine_Task1, xmlW, TASK_CREATE_OR_UPDATE, v_null, v_null, TASK_LOGON_NONE, v_null, &task1);
@@ -812,10 +801,6 @@ todo_wine
     for (i = 0; i < sizeof(open_existing_task)/sizeof(open_existing_task[0]); i++)
     {
         hr = ITaskFolder_RegisterTask(root, Wine_Task1, xmlW, open_existing_task[i].flags, v_null, v_null, TASK_LOGON_NONE, v_null, &task1);
-/* FIXME: Remove once Wine is fixed */
-if (open_existing_task[i].hr != S_OK) todo_wine
-        ok(hr == open_existing_task[i].hr, "%d: expected %#x, got %#x\n", i, open_existing_task[i].hr, hr);
-else
         ok(hr == open_existing_task[i].hr, "%d: expected %#x, got %#x\n", i, open_existing_task[i].hr, hr);
     }
 
@@ -827,7 +812,11 @@ todo_wine
 todo_wine
     ok(hr == S_OK, "get_Name error %#x\n", hr);
     /* FIXME: Remove once implemented */
-    if (hr != S_OK) goto failed;
+    if (hr != S_OK)
+    {
+        ITaskFolder_DeleteTask(root, Wine_Task1, 0);
+        goto failed;
+    }
     ok(!lstrcmpW(bstr, Task1), "expected Task1, got %s\n", wine_dbgstr_w(bstr));
     SysFreeString(bstr);
     hr = IRegisteredTask_get_Path(task1, &bstr);
-- 
1.9.1




More information about the wine-patches mailing list