Dmitry Timoshkov : schedsvc: Implement SchRpcRegisterTask.

Alexandre Julliard julliard at winehq.org
Thu Mar 13 14:40:35 CDT 2014


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

Author: Dmitry Timoshkov <dmitry at baikal.ru>
Date:   Fri Mar  7 12:10:45 2014 +0900

schedsvc: Implement SchRpcRegisterTask.

---

 dlls/schedsvc/schedsvc.c |  107 +++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 105 insertions(+), 2 deletions(-)

diff --git a/dlls/schedsvc/schedsvc.c b/dlls/schedsvc/schedsvc.c
index cc52321..a527ab4 100644
--- a/dlls/schedsvc/schedsvc.c
+++ b/dlls/schedsvc/schedsvc.c
@@ -22,6 +22,7 @@
 
 #include "windef.h"
 #include "schrpc.h"
+#include "taskschd.h"
 #include "wine/debug.h"
 
 #include "schedsvc_private.h"
@@ -102,13 +103,115 @@ static HRESULT create_directory(const WCHAR *path)
     return hr;
 }
 
+static HRESULT write_xml_utf8(const WCHAR *name, DWORD disposition, const WCHAR *xmlW)
+{
+    static const char bom_utf8[] = { 0xef,0xbb,0xbf };
+    static const char comment[] = "<!-- Task definition created by Wine -->\n";
+    HANDLE hfile;
+    DWORD size;
+    char *xml;
+    HRESULT hr = S_OK;
+
+    hfile = CreateFileW(name, GENERIC_WRITE, 0, NULL, disposition, 0, 0);
+    if (hfile == INVALID_HANDLE_VALUE)
+    {
+        if (GetLastError() == ERROR_FILE_EXISTS)
+            return HRESULT_FROM_WIN32(ERROR_ALREADY_EXISTS);
+
+        return HRESULT_FROM_WIN32(GetLastError());
+    }
+
+    size = WideCharToMultiByte(CP_UTF8, 0, xmlW, -1, NULL, 0, NULL, NULL);
+    xml = heap_alloc(size);
+    if (!xml)
+    {
+        CloseHandle(hfile);
+        return E_OUTOFMEMORY;
+    }
+    WideCharToMultiByte(CP_UTF8, 0, xmlW, -1, xml, size, NULL, NULL);
+
+    if (!WriteFile(hfile, bom_utf8, sizeof(bom_utf8), &size, NULL))
+    {
+        hr = HRESULT_FROM_WIN32(GetLastError());
+        goto failed;
+    }
+    if (!WriteFile(hfile, comment, strlen(comment), &size, NULL))
+    {
+        hr = HRESULT_FROM_WIN32(GetLastError());
+        goto failed;
+    }
+
+    /* skip XML declaration with UTF-16 specifier */
+    if (!memcmp(xml, "<?xml", 5))
+    {
+        const char *p = strchr(xml, '>');
+        if (p++) while (isspace(*p)) p++;
+        else p = xml;
+        if (!WriteFile(hfile, p, strlen(p), &size, NULL))
+            hr = HRESULT_FROM_WIN32(GetLastError());
+    }
+    else
+    {
+        if (!WriteFile(hfile, xml, strlen(xml), &size, NULL))
+            hr = HRESULT_FROM_WIN32(GetLastError());
+    }
+
+failed:
+    heap_free(xml);
+    CloseHandle(hfile);
+    return hr;
+}
+
 HRESULT __cdecl SchRpcRegisterTask(const WCHAR *path, const WCHAR *xml, DWORD flags, const WCHAR *sddl,
                                    DWORD task_logon_type, DWORD n_creds, const TASK_USER_CRED *creds,
                                    WCHAR **actual_path, TASK_XML_ERROR_INFO **xml_error_info)
 {
-    WINE_FIXME("%s,%s,%#x,%s,%u,%u,%p,%p,%p: stub\n", wine_dbgstr_w(path), wine_dbgstr_w(xml), flags,
+    WCHAR *full_name, *relative_path;
+    DWORD disposition;
+    HRESULT hr;
+
+    WINE_TRACE("%s,%s,%#x,%s,%u,%u,%p,%p,%p\n", wine_dbgstr_w(path), wine_dbgstr_w(xml), flags,
             wine_dbgstr_w(sddl), task_logon_type, n_creds, creds, actual_path, xml_error_info);
-    return E_NOTIMPL;
+
+    *actual_path = NULL;
+    *xml_error_info = NULL;
+
+    /* FIXME: assume that validation is performed on the client side */
+    if (flags & TASK_VALIDATE_ONLY) return S_OK;
+
+    full_name = get_full_name(path, &relative_path);
+    if (!full_name) return E_OUTOFMEMORY;
+
+    if (strchrW(path, '\\') || strchrW(path, '/'))
+    {
+        WCHAR *p = strrchrW(full_name, '/');
+        if (!p) p = strrchrW(full_name, '\\');
+        *p = 0;
+        hr = create_directory(full_name);
+        *p = '\\';
+    }
+
+    switch (flags & (TASK_CREATE | TASK_UPDATE))
+    {
+    default:
+    case TASK_CREATE:
+        disposition = CREATE_NEW;
+        break;
+
+    case TASK_UPDATE:
+        disposition = OPEN_EXISTING;
+        break;
+
+    case (TASK_CREATE | TASK_UPDATE):
+        disposition = OPEN_ALWAYS;
+        break;
+    }
+
+    hr = write_xml_utf8(full_name, disposition, xml);
+    if (hr == S_OK) *actual_path = heap_strdupW(relative_path);
+
+    heap_free(full_name);
+    return hr;
 }
 
 HRESULT __cdecl SchRpcRetrieveTask(const WCHAR *path, const WCHAR *languages, ULONG *n_languages, WCHAR **xml)




More information about the wine-cvs mailing list