Dmitry Timoshkov : taskschd: Implement ITaskService::get_HighestVersion.

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


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

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

taskschd: Implement ITaskService::get_HighestVersion.

---

 dlls/taskschd/Makefile.in |    6 ++-
 dlls/taskschd/schrpc.idl  |    3 ++
 dlls/taskschd/task.c      |  101 ++++++++++++++++++++++++++++++++++++++++++++-
 3 files changed, 106 insertions(+), 4 deletions(-)

diff --git a/dlls/taskschd/Makefile.in b/dlls/taskschd/Makefile.in
index afbb2ad..c6df2a3 100644
--- a/dlls/taskschd/Makefile.in
+++ b/dlls/taskschd/Makefile.in
@@ -1,5 +1,5 @@
 MODULE    = taskschd.dll
-IMPORTS   = oleaut32 ole32 advapi32 xmllite
+IMPORTS   = oleaut32 ole32 advapi32 xmllite rpcrt4
 
 C_SRCS = \
 	folder.c \
@@ -8,4 +8,6 @@ C_SRCS = \
 	task.c \
 	taskschd.c
 
-IDL_SRCS = taskschd_tlb.idl
+IDL_SRCS = \
+	schrpc.idl \
+	taskschd_tlb.idl
diff --git a/dlls/taskschd/schrpc.idl b/dlls/taskschd/schrpc.idl
new file mode 100644
index 0000000..d8bca06
--- /dev/null
+++ b/dlls/taskschd/schrpc.idl
@@ -0,0 +1,3 @@
+#pragma makedep client
+
+#include "wine/schrpc.idl"
diff --git a/dlls/taskschd/task.c b/dlls/taskschd/task.c
index 41ff843..e6e61c7 100644
--- a/dlls/taskschd/task.c
+++ b/dlls/taskschd/task.c
@@ -26,6 +26,8 @@
 #include "objbase.h"
 #include "xmllite.h"
 #include "taskschd.h"
+#include "winsvc.h"
+#include "schrpc.h"
 #include "taskschd_private.h"
 
 #include "wine/unicode.h"
@@ -2257,6 +2259,7 @@ typedef struct
     ITaskService ITaskService_iface;
     LONG ref;
     BOOL connected;
+    DWORD version;
     WCHAR comp_name[MAX_COMPUTERNAME_LENGTH + 1];
 } TaskService;
 
@@ -2370,11 +2373,70 @@ static inline BOOL is_variant_null(const VARIANT *var)
           (V_VT(var) == VT_BSTR && (V_BSTR(var) == NULL || !*V_BSTR(var)));
 }
 
+static HRESULT start_schedsvc(void)
+{
+    static const WCHAR scheduleW[] = { 'S','c','h','e','d','u','l','e',0 };
+    SC_HANDLE scm, service;
+    SERVICE_STATUS_PROCESS status;
+    ULONGLONG start_time;
+    HRESULT hr = SCHED_E_SERVICE_NOT_RUNNING;
+
+    TRACE("Trying to start %s service\n", debugstr_w(scheduleW));
+
+    scm = OpenSCManagerW(NULL, NULL, 0);
+    if (!scm) return SCHED_E_SERVICE_NOT_INSTALLED;
+
+    service = OpenServiceW(scm, scheduleW, SERVICE_START | SERVICE_QUERY_STATUS);
+    if (service)
+    {
+        if (StartServiceW(service, 0, NULL) || GetLastError() == ERROR_SERVICE_ALREADY_RUNNING)
+        {
+            start_time = GetTickCount64();
+            do
+            {
+                DWORD dummy;
+
+                if (!QueryServiceStatusEx(service, SC_STATUS_PROCESS_INFO, (BYTE *)&status, sizeof(status), &dummy))
+                {
+                    WARN("failed to query scheduler status (%u)\n", GetLastError());
+                    break;
+                }
+
+                if (status.dwCurrentState == SERVICE_RUNNING)
+                {
+                    hr = S_OK;
+                    break;
+                }
+
+                if (GetTickCount64() - start_time > 30000) break;
+                Sleep(1000);
+
+            } while (status.dwCurrentState == SERVICE_START_PENDING);
+
+            if (status.dwCurrentState != SERVICE_RUNNING)
+                WARN("scheduler failed to start %u\n", status.dwCurrentState);
+        }
+        else
+            WARN("failed to start scheduler service (%u)\n", GetLastError());
+
+        CloseServiceHandle(service);
+    }
+    else
+        WARN("failed to open scheduler service (%u)\n", GetLastError());
+
+    CloseServiceHandle(scm);
+    return hr;
+}
+
 static HRESULT WINAPI TaskService_Connect(ITaskService *iface, VARIANT server, VARIANT user, VARIANT domain, VARIANT password)
 {
+    static WCHAR ncalrpc[] = { 'n','c','a','l','r','p','c',0 };
     TaskService *task_svc = impl_from_ITaskService(iface);
     WCHAR comp_name[MAX_COMPUTERNAME_LENGTH + 1];
     DWORD len;
+    HRESULT hr;
+    RPC_WSTR binding_str;
+    extern handle_t rpc_handle;
 
     TRACE("%p,%s,%s,%s,%s\n", iface, debugstr_variant(&server), debugstr_variant(&user),
           debugstr_variant(&domain), debugstr_variant(&password));
@@ -2408,6 +2470,21 @@ static HRESULT WINAPI TaskService_Connect(ITaskService *iface, VARIANT server, V
         }
     }
 
+    hr = start_schedsvc();
+    if (hr != S_OK) return hr;
+
+    hr = RpcStringBindingComposeW(NULL, ncalrpc, NULL, NULL, NULL, &binding_str);
+    if (hr != RPC_S_OK) return hr;
+    hr = RpcBindingFromStringBindingW(binding_str, &rpc_handle);
+    if (hr != RPC_S_OK) return hr;
+    RpcStringFreeW(&binding_str);
+
+    /* Make sure that the connection works */
+    hr = SchRpcHighestVersion(&task_svc->version);
+    if (hr != S_OK) return hr;
+
+    TRACE("server version %#x\n", task_svc->version);
+
     strcpyW(task_svc->comp_name, comp_name);
     task_svc->connected = TRUE;
 
@@ -2458,8 +2535,18 @@ static HRESULT WINAPI TaskService_get_ConnectedDomain(ITaskService *iface, BSTR
 
 static HRESULT WINAPI TaskService_get_HighestVersion(ITaskService *iface, DWORD *version)
 {
-    FIXME("%p,%p: stub\n", iface, version);
-    return E_NOTIMPL;
+    TaskService *task_svc = impl_from_ITaskService(iface);
+
+    TRACE("%p,%p\n", iface, version);
+
+    if (!version) return E_POINTER;
+
+    if (!task_svc->connected)
+        return HRESULT_FROM_WIN32(ERROR_ONLY_IF_CONNECTED);
+
+    *version = task_svc->version;
+
+    return S_OK;
 }
 
 static const ITaskServiceVtbl TaskService_vtbl =
@@ -2498,3 +2585,13 @@ HRESULT TaskService_create(void **obj)
 
     return S_OK;
 }
+
+void __RPC_FAR *__RPC_USER MIDL_user_allocate(SIZE_T n)
+{
+    return HeapAlloc(GetProcessHeap(), 0, n);
+}
+
+void __RPC_USER MIDL_user_free(void __RPC_FAR *p)
+{
+    HeapFree(GetProcessHeap(), 0, p);
+}




More information about the wine-cvs mailing list