Dmitry Timoshkov : taskschd: Add initial version of the task definition XML writer.

Alexandre Julliard julliard at winehq.org
Sat Feb 22 09:50:04 CST 2014


Module: wine
Branch: master
Commit: 890bff26228ce1ce77519c6f29b9f1bde2307ecf
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=890bff26228ce1ce77519c6f29b9f1bde2307ecf

Author: Dmitry Timoshkov <dmitry at baikal.ru>
Date:   Fri Feb 21 11:35:26 2014 +0900

taskschd: Add initial version of the task definition XML writer.

---

 dlls/taskschd/task.c            |  254 +++++++++++++++++++++++++++++++++++++--
 dlls/taskschd/tests/scheduler.c |    2 -
 2 files changed, 246 insertions(+), 10 deletions(-)

diff --git a/dlls/taskschd/task.c b/dlls/taskschd/task.c
index f23a7ad..e1fc713 100644
--- a/dlls/taskschd/task.c
+++ b/dlls/taskschd/task.c
@@ -529,7 +529,7 @@ static HRESULT WINAPI TaskSettings_get_XmlText(ITaskSettings *iface, BSTR *xml)
 
 static HRESULT WINAPI TaskSettings_put_XmlText(ITaskSettings *iface, BSTR xml)
 {
-    TRACE("%p,%s\n", iface, debugstr_w(xml));
+    FIXME("%p,%s: stub\n", iface, debugstr_w(xml));
     return E_NOTIMPL;
 }
 
@@ -832,9 +832,12 @@ static HRESULT TaskSettings_create(ITaskSettings **obj)
 typedef struct
 {
     ITaskDefinition ITaskDefinition_iface;
+    LONG ref;
     IRegistrationInfo *reginfo;
     ITaskSettings *taskset;
-    LONG ref;
+    ITriggerCollection *triggers;
+    IPrincipal *principal;
+    IActionCollection *actions;
 } TaskDefinition;
 
 static inline TaskDefinition *impl_from_ITaskDefinition(ITaskDefinition *iface)
@@ -856,10 +859,18 @@ static ULONG WINAPI TaskDefinition_Release(ITaskDefinition *iface)
     if (!ref)
     {
         TRACE("destroying %p\n", iface);
+
         if (taskdef->reginfo)
             IRegistrationInfo_Release(taskdef->reginfo);
         if (taskdef->taskset)
             ITaskSettings_Release(taskdef->taskset);
+        if (taskdef->triggers)
+            ITriggerCollection_Release(taskdef->triggers);
+        if (taskdef->principal)
+            IPrincipal_Release(taskdef->principal);
+        if (taskdef->actions)
+            IActionCollection_Release(taskdef->actions);
+
         heap_free(taskdef);
     }
 
@@ -1037,12 +1048,6 @@ static HRESULT WINAPI TaskDefinition_put_Actions(ITaskDefinition *iface, IAction
     return E_NOTIMPL;
 }
 
-static HRESULT WINAPI TaskDefinition_get_XmlText(ITaskDefinition *iface, BSTR *xml)
-{
-    FIXME("%p,%p: stub\n", iface, xml);
-    return E_NOTIMPL;
-}
-
 static const WCHAR Task[] = {'T','a','s','k',0};
 static const WCHAR version[] = {'v','e','r','s','i','o','n',0};
 static const WCHAR v1_0[] = {'1','.','0',0};
@@ -1065,6 +1070,7 @@ static const WCHAR InteractiveToken[] = {'I','n','t','e','r','a','c','t','i','v'
 static const WCHAR RunLevel[] = {'R','u','n','L','e','v','e','l',0};
 static const WCHAR LeastPrivilege[] = {'L','e','a','s','t','P','r','i','v','i','l','e','g','e',0};
 static const WCHAR Actions[] = {'A','c','t','i','o','n','s',0};
+static const WCHAR Exec[] = {'E','x','e','c',0};
 static const WCHAR MultipleInstancesPolicy[] = {'M','u','l','t','i','p','l','e','I','n','s','t','a','n','c','e','s','P','o','l','i','c','y',0};
 static const WCHAR IgnoreNew[] = {'I','g','n','o','r','e','N','e','w',0};
 static const WCHAR DisallowStartIfOnBatteries[] = {'D','i','s','a','l','l','o','w','S','t','a','r','t','I','f','O','n','B','a','t','t','e','r','i','e','s',0};
@@ -1081,6 +1087,238 @@ static const WCHAR ExecutionTimeLimit[] = {'E','x','e','c','u','t','i','o','n','
 static const WCHAR Priority[] = {'P','r','i','o','r','i','t','y',0};
 static const WCHAR IdleSettings[] = {'I','d','l','e','S','e','t','t','i','n','g','s',0};
 
+static int xml_indent;
+
+static inline void push_indent(void)
+{
+    xml_indent += 2;
+}
+
+static inline void pop_indent(void)
+{
+    xml_indent -= 2;
+}
+
+static inline HRESULT write_stringW(IStream *stream, const WCHAR *str)
+{
+    return IStream_Write(stream, str, lstrlenW(str) * sizeof(WCHAR), NULL);
+}
+
+static void write_indent(IStream *stream)
+{
+    static const WCHAR spacesW[] = {' ',' ',0};
+    int i;
+    for (i = 0; i < xml_indent; i += 2)
+        write_stringW(stream, spacesW);
+}
+
+static const WCHAR start_element[] = {'<',0};
+static const WCHAR start_end_element[] = {'<','/',0};
+static const WCHAR close_element[] = {'>',0};
+static const WCHAR end_empty_element[] = {'/','>',0};
+static const WCHAR eol[] = {'\n',0};
+
+static inline HRESULT write_empty_element(IStream *stream, const WCHAR *name)
+{
+    write_indent(stream);
+    write_stringW(stream, start_element);
+    write_stringW(stream, name);
+    write_stringW(stream, end_empty_element);
+    return write_stringW(stream, eol);
+}
+
+static inline HRESULT write_element(IStream *stream, const WCHAR *name)
+{
+    write_indent(stream);
+    write_stringW(stream, start_element);
+    write_stringW(stream, name);
+    write_stringW(stream, close_element);
+    return write_stringW(stream, eol);
+}
+
+static inline HRESULT write_element_end(IStream *stream, const WCHAR *name)
+{
+    write_indent(stream);
+    write_stringW(stream, start_end_element);
+    write_stringW(stream, name);
+    write_stringW(stream, close_element);
+    return write_stringW(stream, eol);
+}
+
+static inline HRESULT write_text_value(IStream *stream, const WCHAR *name, const WCHAR *value)
+{
+    write_indent(stream);
+    write_stringW(stream, start_element);
+    write_stringW(stream, name);
+    write_stringW(stream, close_element);
+    write_stringW(stream, value);
+    write_stringW(stream, start_end_element);
+    write_stringW(stream, name);
+    write_stringW(stream, close_element);
+    return write_stringW(stream, eol);
+}
+
+static HRESULT write_task_attributes(IStream *stream, ITaskDefinition *taskdef)
+{
+    static const WCHAR spaceW[] = {' ',0};
+    static const WCHAR equalW[] = {'=',0};
+    static const WCHAR quoteW[] = {'"',0};
+    HRESULT hr;
+    ITaskSettings *taskset;
+    TASK_COMPATIBILITY level;
+    const WCHAR *compatibility;
+
+    hr = ITaskDefinition_get_Settings(taskdef, &taskset);
+    if (hr != S_OK) return hr;
+
+    hr = ITaskSettings_get_Compatibility(taskset, &level);
+    if (hr != S_OK) level = TASK_COMPATIBILITY_V2_1;
+
+    ITaskSettings_Release(taskset);
+
+    switch (level)
+    {
+    case TASK_COMPATIBILITY_AT:
+        compatibility = v1_0;
+        break;
+    case TASK_COMPATIBILITY_V1:
+        compatibility = v1_1;
+        break;
+    case TASK_COMPATIBILITY_V2:
+        compatibility = v1_2;
+        break;
+    default:
+        compatibility = v1_3;
+        break;
+    }
+
+    write_stringW(stream, start_element);
+    write_stringW(stream, Task);
+    write_stringW(stream, spaceW);
+    write_stringW(stream, version);
+    write_stringW(stream, equalW);
+    write_stringW(stream, quoteW);
+    write_stringW(stream, compatibility);
+    write_stringW(stream, quoteW);
+    write_stringW(stream, spaceW);
+    write_stringW(stream, xmlns);
+    write_stringW(stream, equalW);
+    write_stringW(stream, quoteW);
+    write_stringW(stream, task_ns);
+    write_stringW(stream, quoteW);
+    write_stringW(stream, close_element);
+    return write_stringW(stream, eol);
+}
+
+static HRESULT write_registration_info(IStream *stream, IRegistrationInfo *reginfo)
+{
+    if (!reginfo)
+        return write_empty_element(stream, RegistrationInfo);
+
+    FIXME("stub\n");
+    return S_OK;
+}
+
+static HRESULT write_principal(IStream *stream, IPrincipal *principal)
+{
+    if (!principal)
+        return write_empty_element(stream, Principals);
+
+    FIXME("stub\n");
+    return S_OK;
+}
+
+static HRESULT write_settings(IStream *stream, ITaskSettings *settings)
+{
+    if (!settings)
+        return write_empty_element(stream, Settings);
+
+    FIXME("stub\n");
+    return S_OK;
+}
+
+static HRESULT write_triggers(IStream *stream, ITriggerCollection *triggers)
+{
+    if (!triggers)
+        return write_empty_element(stream, Triggers);
+
+    FIXME("stub\n");
+    return S_OK;
+}
+
+static HRESULT write_actions(IStream *stream, IActionCollection *actions)
+{
+    if (!actions)
+    {
+        write_element(stream, Actions);
+        push_indent();
+        write_empty_element(stream, Exec);
+        pop_indent();
+        return write_element_end(stream, Actions);
+    }
+
+    FIXME("stub\n");
+    return S_OK;
+}
+
+static HRESULT WINAPI TaskDefinition_get_XmlText(ITaskDefinition *iface, BSTR *xml)
+{
+    TaskDefinition *taskdef = impl_from_ITaskDefinition(iface);
+    HRESULT hr;
+    IStream *stream;
+    HGLOBAL hmem;
+    void *p;
+
+    TRACE("%p,%p\n", iface, xml);
+
+    hmem = GlobalAlloc(GMEM_MOVEABLE | GMEM_NODISCARD, 16);
+    if (!hmem) return E_OUTOFMEMORY;
+
+    hr = CreateStreamOnHGlobal(hmem, TRUE, &stream);
+    if (hr != S_OK)
+    {
+        GlobalFree(hmem);
+        return hr;
+    }
+
+    hr = write_task_attributes(stream, &taskdef->ITaskDefinition_iface);
+    if (hr != S_OK) goto failed;
+
+    push_indent();
+
+    hr = write_registration_info(stream, taskdef->reginfo);
+    if (hr != S_OK) goto failed;
+
+    hr = write_triggers(stream, taskdef->triggers);
+    if (hr != S_OK) goto failed;
+
+    hr = write_principal(stream, taskdef->principal);
+    if (hr != S_OK) goto failed;
+
+    hr = write_settings(stream, taskdef->taskset);
+    if (hr != S_OK) goto failed;
+
+    hr = write_actions(stream, taskdef->actions);
+    if (hr != S_OK) goto failed;
+
+    pop_indent();
+
+    write_element_end(stream, Task);
+    IStream_Write(stream, "\0\0", 2, NULL);
+
+    p = GlobalLock(hmem);
+    *xml = SysAllocString(p);
+    GlobalUnlock(hmem);
+
+    IStream_Release(stream);
+
+    return *xml ? S_OK : E_OUTOFMEMORY;
+
+failed:
+    IStream_Release(stream);
+    return hr;
+}
+
 static HRESULT read_text_value(IXmlReader *reader, WCHAR **value)
 {
     HRESULT hr;
diff --git a/dlls/taskschd/tests/scheduler.c b/dlls/taskschd/tests/scheduler.c
index 83f5367..34e4625 100644
--- a/dlls/taskschd/tests/scheduler.c
+++ b/dlls/taskschd/tests/scheduler.c
@@ -1112,7 +1112,6 @@ static void test_TaskDefinition(void)
     create_action(taskdef);
 
     hr = ITaskDefinition_get_XmlText(taskdef, &xml);
-todo_wine
     ok(hr == S_OK, "get_XmlText error %#x\n", hr);
 
     ITaskDefinition_Release(taskdef);
@@ -1121,7 +1120,6 @@ todo_wine
     ok(hr == S_OK, "NewTask error %#x\n", hr);
 
     hr = ITaskDefinition_put_XmlText(taskdef, xml);
-todo_wine
     ok(hr == S_OK, "put_XmlText error %#x\n", hr);
     SysFreeString(xml);
 




More information about the wine-cvs mailing list