Commit 88df3688 authored by Dmitry Timoshkov's avatar Dmitry Timoshkov Committed by Alexandre Julliard

schedsvc: Add Task Scheduler service.

parent 69bee9f0
......@@ -1195,6 +1195,7 @@ enable_sane_ds
enable_scarddlg
enable_sccbase
enable_schannel
enable_schedsvc
enable_scrrun
enable_scsiport_sys
enable_secur32
......@@ -17106,6 +17107,7 @@ wine_fn_config_dll scarddlg enable_scarddlg
wine_fn_config_dll sccbase enable_sccbase
wine_fn_config_dll schannel enable_schannel
wine_fn_config_test dlls/schannel/tests schannel_test
wine_fn_config_dll schedsvc enable_schedsvc clean
wine_fn_config_dll scrrun enable_scrrun clean
wine_fn_config_test dlls/scrrun/tests scrrun_test clean
wine_fn_config_dll scsiport.sys enable_scsiport_sys
......
......@@ -3111,6 +3111,7 @@ WINE_CONFIG_DLL(scarddlg)
WINE_CONFIG_DLL(sccbase)
WINE_CONFIG_DLL(schannel)
WINE_CONFIG_TEST(dlls/schannel/tests)
WINE_CONFIG_DLL(schedsvc,,[clean])
WINE_CONFIG_DLL(scrrun,,[clean])
WINE_CONFIG_TEST(dlls/scrrun/tests,[clean])
WINE_CONFIG_DLL(scsiport.sys)
......
MODULE = schedsvc.dll
IMPORTS = rpcrt4 advapi32
C_SRCS = \
schedsvc.c \
svc_main.c
IDL_SRCS = schrpc.idl
/*
* Task Scheduler Service
*
* Copyright 2014 Dmitry Timoshkov
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdarg.h>
#include "windef.h"
#include "schrpc.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(schedsvc);
HRESULT __cdecl SchRpcHighestVersion(DWORD *version)
{
WINE_FIXME("%p: stub\n", version);
return E_NOTIMPL;
}
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,
wine_dbgstr_w(sddl), task_logon_type, n_creds, creds, actual_path, xml_error_info);
return E_NOTIMPL;
}
HRESULT __cdecl SchRpcRetrieveTask(const WCHAR *path, const WCHAR *languages, ULONG *n_languages, WCHAR **xml)
{
WINE_FIXME("%s,%s,%p,%p: stub\n", wine_dbgstr_w(path), wine_dbgstr_w(languages), n_languages, xml);
return E_NOTIMPL;
}
HRESULT __cdecl SchRpcCreateFolder(const WCHAR *path, const WCHAR *sddl, DWORD flags)
{
WINE_FIXME("%s,%s,%#x: stub\n", wine_dbgstr_w(path), wine_dbgstr_w(sddl), flags);
return E_NOTIMPL;
}
HRESULT __cdecl SchRpcSetSecurity(const WCHAR *path, const WCHAR *sddl, DWORD flags)
{
WINE_FIXME("%s,%s,%#x: stub\n", wine_dbgstr_w(path), wine_dbgstr_w(sddl), flags);
return E_NOTIMPL;
}
HRESULT __cdecl SchRpcGetSecurity(const WCHAR *path, DWORD flags, WCHAR **sddl)
{
WINE_FIXME("%s,%#x,%p: stub\n", wine_dbgstr_w(path), flags, sddl);
return E_NOTIMPL;
}
HRESULT __cdecl SchRpcEnumFolders(const WCHAR *path, DWORD flags, DWORD *start_index, DWORD n_requested,
DWORD *n_names, TASK_NAMES *names)
{
WINE_FIXME("%s,%#x,%p,%u,%p,%p: stub\n", wine_dbgstr_w(path), flags, start_index, n_requested, n_names, names);
return E_NOTIMPL;
}
HRESULT __cdecl SchRpcEnumTasks(const WCHAR *path, DWORD flags, DWORD *start_index, DWORD n_requested,
DWORD *n_names, TASK_NAMES *names)
{
WINE_FIXME("%s,%#x,%p,%u,%p,%p: stub\n", wine_dbgstr_w(path), flags, start_index, n_requested, n_names, names);
return E_NOTIMPL;
}
HRESULT __cdecl SchRpcEnumInstances(const WCHAR *path, DWORD flags, DWORD *n_guids, GUID **guids)
{
WINE_FIXME("%s,%#x,%p,%p: stub\n", wine_dbgstr_w(path), flags, n_guids, guids);
return E_NOTIMPL;
}
HRESULT __cdecl SchRpcGetInstanceInfo(GUID guid, WCHAR **path, DWORD *task_state, WCHAR **action,
WCHAR **info, DWORD *n_instances, GUID **instances, DWORD *pid)
{
WINE_FIXME("%s,%p,%p,%p,%p,%p,%p,%p: stub\n", wine_dbgstr_guid(&guid), path, task_state, action,
info, n_instances, instances, pid);
return E_NOTIMPL;
}
HRESULT __cdecl SchRpcStopInstance(GUID guid, DWORD flags)
{
WINE_FIXME("%s,%#x: stub\n", wine_dbgstr_guid(&guid), flags);
return E_NOTIMPL;
}
HRESULT __cdecl SchRpcStop(const WCHAR *path, DWORD flags)
{
WINE_FIXME("%s,%#x: stub\n", wine_dbgstr_w(path), flags);
return E_NOTIMPL;
}
HRESULT __cdecl SchRpcRun(const WCHAR *path, DWORD n_args, const WCHAR **args, DWORD flags,
DWORD session_id, const WCHAR *user, GUID *guid)
{
WINE_FIXME("%s,%u,%p,%#x,%#x,%s,%p: stub\n", wine_dbgstr_w(path), n_args, args, flags,
session_id, wine_dbgstr_w(user), guid);
return E_NOTIMPL;
}
HRESULT __cdecl SchRpcDelete(const WCHAR *path, DWORD flags)
{
WINE_FIXME("%s,%#x: stub\n", wine_dbgstr_w(path), flags);
return E_NOTIMPL;
}
HRESULT __cdecl SchRpcRename(const WCHAR *path, const WCHAR *name, DWORD flags)
{
WINE_FIXME("%s,%s,%#x: stub\n", wine_dbgstr_w(path), wine_dbgstr_w(name), flags);
return E_NOTIMPL;
}
HRESULT __cdecl SchRpcScheduledRuntimes(const WCHAR *path, SYSTEMTIME *start, SYSTEMTIME *end, DWORD flags,
DWORD n_requested, DWORD *n_runtimes, SYSTEMTIME **runtimes)
{
WINE_FIXME("%s,%p,%p,%#x,%u,%p,%p: stub\n", wine_dbgstr_w(path), start, end, flags,
n_requested, n_runtimes, runtimes);
return E_NOTIMPL;
}
HRESULT __cdecl SchRpcGetLastRunInfo(const WCHAR *path, SYSTEMTIME *last_runtime, DWORD *last_return_code)
{
WINE_FIXME("%s,%p,%p: stub\n", wine_dbgstr_w(path), last_runtime, last_return_code);
return E_NOTIMPL;
}
HRESULT __cdecl SchRpcGetTaskInfo(const WCHAR *path, DWORD flags, DWORD *enabled, DWORD *task_state)
{
WINE_FIXME("%s,%#x,%p,%p: stub\n", wine_dbgstr_w(path), flags, enabled, task_state);
return E_NOTIMPL;
}
HRESULT __cdecl SchRpcGetNumberOfMissedRuns(const WCHAR *path, DWORD *runs)
{
WINE_FIXME("%s,%p: stub\n", wine_dbgstr_w(path), runs);
return E_NOTIMPL;
}
HRESULT __cdecl SchRpcEnableTask(const WCHAR *path, DWORD enabled)
{
WINE_FIXME("%s,%u: stub\n", wine_dbgstr_w(path), enabled);
return E_NOTIMPL;
}
@ stdcall -private ServiceMain(long ptr)
#pragma makedep server
#include "wine/schrpc.idl"
/*
* Task Scheduler Service
*
* Copyright 2014 Dmitry Timoshkov
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "winsvc.h"
#include "rpc.h"
#include "schrpc.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(schedsvc);
static SERVICE_STATUS_HANDLE schedsvc_handle;
static HANDLE done_event;
static void schedsvc_update_status(DWORD state)
{
SERVICE_STATUS status;
status.dwServiceType = SERVICE_WIN32;
status.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_SHUTDOWN;
status.dwWin32ExitCode = 0;
status.dwServiceSpecificExitCode = 0;
status.dwCheckPoint = 0;
status.dwWaitHint = 0;
status.dwControlsAccepted = 0;
status.dwCurrentState = state;
SetServiceStatus(schedsvc_handle, &status);
}
static void WINAPI schedsvc_handler(DWORD control)
{
WINE_TRACE("%#x\n", control);
switch (control)
{
case SERVICE_CONTROL_STOP:
case SERVICE_CONTROL_SHUTDOWN:
schedsvc_update_status(SERVICE_STOP_PENDING);
SetEvent(done_event);
break;
default:
schedsvc_update_status(SERVICE_RUNNING);
break;
}
}
static RPC_BINDING_VECTOR *sched_bindings;
static RPC_STATUS RPC_init(void)
{
WCHAR transport[] = SCHEDSVC_TRANSPORT;
RPC_STATUS status;
WINE_TRACE("using %s\n", wine_dbgstr_w(transport));
status = RpcServerUseProtseqEpW(transport, 0, NULL, NULL);
if (status != RPC_S_OK)
{
WINE_ERR("RpcServerUseProtseqEp error %#x\n", status);
return status;
}
status = RpcServerRegisterIf(ITaskSchedulerService_v1_0_s_ifspec, 0, 0);
if (status != RPC_S_OK)
{
WINE_ERR("RpcServerRegisterIf error %#x\n", status);
return status;
}
status = RpcServerInqBindings(&sched_bindings);
if (status != RPC_S_OK)
{
WINE_ERR("RpcServerInqBindings error %#x\n", status);
return status;
}
status = RpcEpRegisterW(ITaskSchedulerService_v1_0_s_ifspec, sched_bindings, NULL, NULL);
if (status != RPC_S_OK)
{
WINE_ERR("RpcEpRegister error %#x\n", status);
return status;
}
status = RpcServerListen(1, RPC_C_LISTEN_MAX_CALLS_DEFAULT, TRUE);
if (status != RPC_S_OK)
{
WINE_ERR("RpcServerListen error %#x\n", status);
return status;
}
return RPC_S_OK;
}
static void RPC_finish(void)
{
RpcMgmtStopServerListening(NULL);
RpcEpUnregister(ITaskSchedulerService_v1_0_s_ifspec, sched_bindings, NULL);
RpcBindingVectorFree(&sched_bindings);
RpcServerUnregisterIf(NULL, NULL, FALSE);
}
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;
schedsvc_handle = RegisterServiceCtrlHandlerW(scheduleW, schedsvc_handler);
if (!schedsvc_handle)
{
WINE_ERR("RegisterServiceCtrlHandler error %d\n", GetLastError());
return;
}
done_event = CreateEventW(NULL, TRUE, FALSE, NULL);
schedsvc_update_status(SERVICE_RUNNING);
WaitForSingleObject(done_event, INFINITE);
RPC_finish();
schedsvc_update_status(SERVICE_STOPPED);
WINE_TRACE("exiting Task Scheduler Service\n");
}
void __RPC_FAR * __RPC_USER MIDL_user_allocate(SIZE_T len)
{
return HeapAlloc(GetProcessHeap(), 0, len);
}
void __RPC_USER MIDL_user_free(void __RPC_FAR * ptr)
{
HeapFree(GetProcessHeap(), 0, ptr);
}
/*
* Task Scheduler Service definitions
*
* Copyright 2014 Dmitry Timoshkov
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
cpp_quote("#define SCHEDSVC_TRANSPORT {'n','c','a','l','r','p','c',0}")
import "oaidl.idl";
import "ocidl.idl";
[
uuid(86d35949-83c9-4044-b424-db363231fd0c),
implicit_handle(handle_t rpc_handle),
version(1.0),
pointer_default(unique)
]
interface ITaskSchedulerService
{
typedef struct _TASK_USER_CRED
{
[string] const WCHAR *user;
[string] const WCHAR *password;
DWORD flags;
} TASK_USER_CRED;
typedef struct _TASK_XML_ERROR_INFO
{
DWORD line, column;
[string] WCHAR *node;
[string] WCHAR *value;
} TASK_XML_ERROR_INFO;
typedef [string] WCHAR **TASK_NAMES;
HRESULT SchRpcHighestVersion([out] DWORD *version);
HRESULT SchRpcRegisterTask([in, string, unique] const WCHAR *path,
[in, string] const WCHAR *xml, [in] DWORD flags,
[in, string, unique] const WCHAR *sddl,
[in] DWORD task_logon_type, [in] DWORD n_creds,
[in, size_is(n_creds), unique] const TASK_USER_CRED *creds,
[out, string] WCHAR **actual_path,
[out] TASK_XML_ERROR_INFO **xml_error_info);
HRESULT SchRpcRetrieveTask([in, string] const WCHAR *path,
[in, string] const WCHAR *languages,
[in] unsigned long *n_languages, [out, string] WCHAR **xml);
HRESULT SchRpcCreateFolder([in, string] const WCHAR *path,
[in, string, unique] const WCHAR *sddl, [in] DWORD flags);
HRESULT SchRpcSetSecurity([in, string] const WCHAR *path,
[in, string] const WCHAR *sddl, [in] DWORD flags);
HRESULT SchRpcGetSecurity([in, string] const WCHAR *path,
[in] DWORD flags, [out, string] WCHAR **sddl);
HRESULT SchRpcEnumFolders([in, string] const WCHAR *path,
[in] DWORD flags, [in, out] DWORD *start_index,
[in] DWORD n_requested, [out] DWORD *n_names,
[out, size_is(,*n_names)] TASK_NAMES *names);
HRESULT SchRpcEnumTasks([in, string] const WCHAR *path,
[in] DWORD flags, [in, out] DWORD *start_index,
[in] DWORD n_requested, [out] DWORD *n_names,
[out, size_is(,*n_names)] TASK_NAMES *names);
HRESULT SchRpcEnumInstances([in, string, unique] const WCHAR *path,
[in] DWORD flags, [out] DWORD *n_guids,
[out, size_is(,*n_guids)] GUID **guids);
HRESULT SchRpcGetInstanceInfo([in] GUID guid, [out, string] WCHAR **path,
[out] DWORD *task_state, [out, string] WCHAR **action,
[out, string] WCHAR **info, [out] DWORD *n_instances,
[out, size_is(,*n_instances)] GUID **instances, [out] DWORD *pid);
HRESULT SchRpcStopInstance([in] GUID guid, [in] DWORD flags);
HRESULT SchRpcStop([in, string, unique] const WCHAR *path, [in] DWORD flags);
HRESULT SchRpcRun([in, string] const WCHAR *path,
[in] DWORD n_args, [in, size_is(n_args),unique] const WCHAR **args,
[in] DWORD flags, [in] DWORD session_id,
[in, unique, string] const WCHAR *user, [out] GUID *guid);
HRESULT SchRpcDelete([in, string] const WCHAR *path, [in] DWORD flags);
HRESULT SchRpcRename([in, string] const WCHAR *path, [in, string] const WCHAR *name, [in] DWORD flags);
HRESULT SchRpcScheduledRuntimes([in, string] const WCHAR *path,
[in, unique] SYSTEMTIME *start, [in, unique] SYSTEMTIME *end,
[in] DWORD flags, [in] DWORD n_requested, [out] DWORD *n_runtimes,
[out, size_is(,*n_runtimes)] SYSTEMTIME **runtimes);
HRESULT SchRpcGetLastRunInfo([in, string] const WCHAR *path,
[out] SYSTEMTIME *last_runtime, [out] DWORD *last_return_code);
HRESULT SchRpcGetTaskInfo([in, string] const WCHAR *path, [in] DWORD flags,
[out] DWORD *enabled, [out] DWORD *task_state);
HRESULT SchRpcGetNumberOfMissedRuns([in, string] const WCHAR *path, [out] DWORD *runs);
HRESULT SchRpcEnableTask([in, string] const WCHAR *path, [in] DWORD enabled);
}
......@@ -124,6 +124,7 @@ AddService=PlugPlay,0,PlugPlayService
AddService=FontCache3.0.0.0,0,WPFFontCacheService
AddService=LanmanServer,0,LanmanServerService
AddService=FontCache,0,FontCacheService
AddService=Schedule,0,TaskSchedulerService
[DefaultInstall.NT.Services]
AddService=BITS,0,BITSService
......@@ -136,6 +137,7 @@ AddService=PlugPlay,0,PlugPlayService
AddService=FontCache3.0.0.0,0,WPFFontCacheService
AddService=LanmanServer,0,LanmanServerService
AddService=FontCache,0,FontCacheService
AddService=Schedule,0,TaskSchedulerService
[DefaultInstall.ntamd64.Services]
AddService=BITS,0,BITSService
......@@ -148,6 +150,7 @@ AddService=PlugPlay,0,PlugPlayService
AddService=FontCache3.0.0.0,0,WPFFontCacheService
AddService=LanmanServer,0,LanmanServerService
AddService=FontCache,0,FontCacheService
AddService=Schedule,0,TaskSchedulerService
[Strings]
MciExtStr="Software\Microsoft\Windows NT\CurrentVersion\MCI Extensions"
......@@ -3026,6 +3029,19 @@ ErrorControl=1
HKR,Parameters,"ServiceDll",,"%11%\fntcache.dll"
;; HKLM,%CurrentVersionNT%\SvcHost,"netsvcs",0x00010008,"fontcache"
[TaskSchedulerService]
AddReg=TaskSchedulerServiceKeys
Description="Task Scheduler"
DisplayName="Task Scheduler"
ServiceBinary="%11%\svchost.exe -k netsvcs"
ServiceType=32
StartType=3
ErrorControl=1
[TaskSchedulerServiceKeys]
HKR,Parameters,"ServiceDll",,"%11%\schedsvc.dll"
HKLM,%CurrentVersionNT%\SvcHost,"netsvcs",0x00010008,"Schedule"
[Services]
HKLM,%CurrentVersion%\RunServices,"winemenubuilder",2,"%11%\winemenubuilder.exe -a -r"
HKLM,"System\CurrentControlSet\Services\Eventlog\Application",,16
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment