schedsvc: Mark service as auto-start once a task is registered.

Dmitry Timoshkov dmitry at baikal.ru
Thu Mar 13 22:58:16 CDT 2014


---
 dlls/schedsvc/schedsvc.c         |  6 ++++-
 dlls/schedsvc/schedsvc_private.h |  2 ++
 dlls/schedsvc/svc_main.c         | 53 ++++++++++++++++++++++++++++++++++++++--
 3 files changed, 58 insertions(+), 3 deletions(-)

diff --git a/dlls/schedsvc/schedsvc.c b/dlls/schedsvc/schedsvc.c
index 538a423..6ce8064 100644
--- a/dlls/schedsvc/schedsvc.c
+++ b/dlls/schedsvc/schedsvc.c
@@ -208,7 +208,11 @@ HRESULT __cdecl SchRpcRegisterTask(const WCHAR *path, const WCHAR *xml, DWORD fl
     }
 
     hr = write_xml_utf8(full_name, disposition, xml);
-    if (hr == S_OK) *actual_path = heap_strdupW(relative_path);
+    if (hr == S_OK)
+    {
+        *actual_path = heap_strdupW(relative_path);
+        schedsvc_auto_start();
+    }
 
     heap_free(full_name);
     return hr;
diff --git a/dlls/schedsvc/schedsvc_private.h b/dlls/schedsvc/schedsvc_private.h
index 082bda5..fd0225f 100644
--- a/dlls/schedsvc/schedsvc_private.h
+++ b/dlls/schedsvc/schedsvc_private.h
@@ -21,6 +21,8 @@
 
 #include "wine/unicode.h"
 
+void schedsvc_auto_start(void) DECLSPEC_HIDDEN;
+
 static void *heap_alloc_zero(SIZE_T size) __WINE_ALLOC_SIZE(1);
 static inline void *heap_alloc_zero(SIZE_T size)
 {
diff --git a/dlls/schedsvc/svc_main.c b/dlls/schedsvc/svc_main.c
index fe5d4fc..95872cd 100644
--- a/dlls/schedsvc/svc_main.c
+++ b/dlls/schedsvc/svc_main.c
@@ -29,9 +29,60 @@
 
 WINE_DEFAULT_DEBUG_CHANNEL(schedsvc);
 
+static const WCHAR scheduleW[] = {'S','c','h','e','d','u','l','e',0};
 static SERVICE_STATUS_HANDLE schedsvc_handle;
 static HANDLE done_event;
 
+void schedsvc_auto_start(void)
+{
+    static DWORD start_type;
+    SC_HANDLE scm, service;
+    QUERY_SERVICE_CONFIGW *cfg;
+    DWORD cfg_size;
+
+    if (start_type == SERVICE_AUTO_START) return;
+
+    TRACE("changing service start type to SERVICE_AUTO_START\n");
+
+    scm = OpenSCManagerW(NULL, NULL, 0);
+    if (!scm)
+    {
+        WARN("failed to open SCM (%u)\n", GetLastError());
+        return;
+    }
+
+    service = OpenServiceW(scm, scheduleW, SERVICE_QUERY_CONFIG | SERVICE_CHANGE_CONFIG);
+    if (service)
+    {
+        if (!QueryServiceConfigW(service, NULL, 0, &cfg_size) && GetLastError() == ERROR_INSUFFICIENT_BUFFER)
+        {
+            cfg = HeapAlloc(GetProcessHeap(), 0, cfg_size);
+            if (cfg)
+            {
+                if (QueryServiceConfigW(service, cfg, cfg_size, &cfg_size))
+                {
+                    start_type = cfg->dwStartType;
+                    if (start_type != SERVICE_AUTO_START)
+                    {
+                        if (ChangeServiceConfigW(service, SERVICE_NO_CHANGE, SERVICE_AUTO_START, SERVICE_NO_CHANGE,
+                                                 NULL, NULL, NULL, NULL, NULL, NULL, NULL))
+                            start_type = SERVICE_AUTO_START;
+                    }
+                }
+                HeapFree(GetProcessHeap(), 0, cfg);
+            }
+        }
+        else
+            WARN("failed to query service config (%u)\n", GetLastError());
+
+        CloseServiceHandle(service);
+    }
+    else
+        WARN("failed to open service (%u)\n", GetLastError());
+
+    CloseServiceHandle(scm);
+}
+
 static void schedsvc_update_status(DWORD state)
 {
     SERVICE_STATUS status;
@@ -122,8 +173,6 @@ static void RPC_finish(void)
 
 void WINAPI ServiceMain(DWORD argc, LPWSTR *argv)
 {
-    static const WCHAR scheduleW[] = {'S','c','h','e','d','u','l','e',0};
-
     WINE_TRACE("starting Task Scheduler Service\n");
 
     if (RPC_init() != RPC_S_OK) return;
-- 
1.8.5.5




More information about the wine-patches mailing list