2 * Copyright 2014 Dmitry Timoshkov
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
29 #include "taskschd_private.h"
31 #include "wine/unicode.h"
32 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(taskschd
);
38 IRegisteredTask IRegisteredTask_iface
;
41 ITaskDefinition
*taskdef
;
44 static inline RegisteredTask
*impl_from_IRegisteredTask(IRegisteredTask
*iface
)
46 return CONTAINING_RECORD(iface
, RegisteredTask
, IRegisteredTask_iface
);
49 static ULONG WINAPI
regtask_AddRef(IRegisteredTask
*iface
)
51 RegisteredTask
*regtask
= impl_from_IRegisteredTask(iface
);
52 return InterlockedIncrement(®task
->ref
);
55 static ULONG WINAPI
regtask_Release(IRegisteredTask
*iface
)
57 RegisteredTask
*regtask
= impl_from_IRegisteredTask(iface
);
58 LONG ref
= InterlockedDecrement(®task
->ref
);
62 TRACE("destroying %p\n", iface
);
63 ITaskDefinition_Release(regtask
->taskdef
);
64 heap_free(regtask
->path
);
71 static HRESULT WINAPI
regtask_QueryInterface(IRegisteredTask
*iface
, REFIID riid
, void **obj
)
73 if (!riid
|| !obj
) return E_INVALIDARG
;
75 TRACE("%p,%s,%p\n", iface
, debugstr_guid(riid
), obj
);
77 if (IsEqualGUID(riid
, &IID_IRegisteredTask
) ||
78 IsEqualGUID(riid
, &IID_IDispatch
) ||
79 IsEqualGUID(riid
, &IID_IUnknown
))
81 IRegisteredTask_AddRef(iface
);
86 FIXME("interface %s is not implemented\n", debugstr_guid(riid
));
91 static HRESULT WINAPI
regtask_GetTypeInfoCount(IRegisteredTask
*iface
, UINT
*count
)
93 FIXME("%p,%p: stub\n", iface
, count
);
97 static HRESULT WINAPI
regtask_GetTypeInfo(IRegisteredTask
*iface
, UINT index
, LCID lcid
, ITypeInfo
**info
)
99 FIXME("%p,%u,%u,%p: stub\n", iface
, index
, lcid
, info
);
103 static HRESULT WINAPI
regtask_GetIDsOfNames(IRegisteredTask
*iface
, REFIID riid
, LPOLESTR
*names
,
104 UINT count
, LCID lcid
, DISPID
*dispid
)
106 FIXME("%p,%s,%p,%u,%u,%p: stub\n", iface
, debugstr_guid(riid
), names
, count
, lcid
, dispid
);
110 static HRESULT WINAPI
regtask_Invoke(IRegisteredTask
*iface
, DISPID dispid
, REFIID riid
, LCID lcid
, WORD flags
,
111 DISPPARAMS
*params
, VARIANT
*result
, EXCEPINFO
*excepinfo
, UINT
*argerr
)
113 FIXME("%p,%d,%s,%04x,%04x,%p,%p,%p,%p: stub\n", iface
, dispid
, debugstr_guid(riid
), lcid
, flags
,
114 params
, result
, excepinfo
, argerr
);
118 static HRESULT WINAPI
regtask_get_Name(IRegisteredTask
*iface
, BSTR
*name
)
120 RegisteredTask
*regtask
= impl_from_IRegisteredTask(iface
);
123 TRACE("%p,%p\n", iface
, name
);
125 if (!name
) return E_POINTER
;
127 p_name
= strrchrW(regtask
->path
, '\\');
129 p_name
= regtask
->path
;
131 if (p_name
[1] != 0) p_name
++;
133 *name
= SysAllocString(p_name
);
134 if (!*name
) return E_OUTOFMEMORY
;
139 static HRESULT WINAPI
regtask_get_Path(IRegisteredTask
*iface
, BSTR
*path
)
141 RegisteredTask
*regtask
= impl_from_IRegisteredTask(iface
);
143 TRACE("%p,%p\n", iface
, path
);
145 if (!path
) return E_POINTER
;
147 *path
= SysAllocString(regtask
->path
);
148 if (!*path
) return E_OUTOFMEMORY
;
153 static HRESULT WINAPI
regtask_get_State(IRegisteredTask
*iface
, TASK_STATE
*state
)
155 RegisteredTask
*regtask
= impl_from_IRegisteredTask(iface
);
158 TRACE("%p,%p\n", iface
, state
);
160 if (!state
) return E_POINTER
;
162 return SchRpcGetTaskInfo(regtask
->path
, SCH_FLAG_STATE
, &enabled
, state
);
165 static HRESULT WINAPI
regtask_get_Enabled(IRegisteredTask
*iface
, VARIANT_BOOL
*v_enabled
)
167 RegisteredTask
*regtask
= impl_from_IRegisteredTask(iface
);
168 DWORD enabled
, state
;
171 TRACE("%p,%p\n", iface
, v_enabled
);
173 if (!v_enabled
) return E_POINTER
;
175 hr
= SchRpcGetTaskInfo(regtask
->path
, 0, &enabled
, &state
);
177 *v_enabled
= enabled
? VARIANT_TRUE
: VARIANT_FALSE
;
181 static HRESULT WINAPI
regtask_put_Enabled(IRegisteredTask
*iface
, VARIANT_BOOL enabled
)
183 FIXME("%p,%d: stub\n", iface
, enabled
);
187 static HRESULT WINAPI
regtask_Run(IRegisteredTask
*iface
, VARIANT params
, IRunningTask
**task
)
189 FIXME("%p,%s,%p: stub\n", iface
, debugstr_variant(¶ms
), task
);
193 static HRESULT WINAPI
regtask_RunEx(IRegisteredTask
*iface
, VARIANT params
, LONG flags
,
194 LONG session_id
, BSTR user
, IRunningTask
**task
)
196 FIXME("%p,%s,%x,%x,%s,%p: stub\n", iface
, debugstr_variant(¶ms
), flags
, session_id
, debugstr_w(user
), task
);
200 static HRESULT WINAPI
regtask_GetInstances(IRegisteredTask
*iface
, LONG flags
, IRunningTaskCollection
**tasks
)
202 FIXME("%p,%x,%p: stub\n", iface
, flags
, tasks
);
206 static HRESULT WINAPI
regtask_get_LastRunTime(IRegisteredTask
*iface
, DATE
*date
)
208 FIXME("%p,%p: stub\n", iface
, date
);
212 static HRESULT WINAPI
regtask_get_LastTaskResult(IRegisteredTask
*iface
, LONG
*result
)
214 FIXME("%p,%p: stub\n", iface
, result
);
218 static HRESULT WINAPI
regtask_get_NumberOfMissedRuns(IRegisteredTask
*iface
, LONG
*runs
)
220 FIXME("%p,%p: stub\n", iface
, runs
);
224 static HRESULT WINAPI
regtask_get_NextRunTime(IRegisteredTask
*iface
, DATE
*date
)
226 FIXME("%p,%p: stub\n", iface
, date
);
230 static HRESULT WINAPI
regtask_get_Definition(IRegisteredTask
*iface
, ITaskDefinition
**task
)
232 RegisteredTask
*regtask
= impl_from_IRegisteredTask(iface
);
234 TRACE("%p,%p\n", iface
, task
);
236 if (!task
) return E_POINTER
;
238 ITaskDefinition_AddRef(regtask
->taskdef
);
239 *task
= regtask
->taskdef
;
244 static HRESULT WINAPI
regtask_get_Xml(IRegisteredTask
*iface
, BSTR
*xml
)
246 RegisteredTask
*regtask
= impl_from_IRegisteredTask(iface
);
248 TRACE("%p,%p\n", iface
, xml
);
250 if (!xml
) return E_POINTER
;
252 return ITaskDefinition_get_XmlText(regtask
->taskdef
, xml
);
255 static HRESULT WINAPI
regtask_GetSecurityDescriptor(IRegisteredTask
*iface
, LONG info
, BSTR
*sddl
)
257 FIXME("%p,%x,%p: stub\n", iface
, info
, sddl
);
261 static HRESULT WINAPI
regtask_SetSecurityDescriptor(IRegisteredTask
*iface
, BSTR sddl
, LONG flags
)
263 FIXME("%p,%s,%x: stub\n", iface
, debugstr_w(sddl
), flags
);
267 static HRESULT WINAPI
regtask_Stop(IRegisteredTask
*iface
, LONG flags
)
269 FIXME("%p,%x: stub\n", iface
, flags
);
273 static HRESULT WINAPI
regtask_GetRunTimes(IRegisteredTask
*iface
, const LPSYSTEMTIME start
, const LPSYSTEMTIME end
,
274 DWORD
*count
, LPSYSTEMTIME
*time
)
276 FIXME("%p,%p.%p,%p,%p: stub\n", iface
, start
, end
, count
, time
);
280 static const IRegisteredTaskVtbl RegisteredTask_vtbl
=
282 regtask_QueryInterface
,
285 regtask_GetTypeInfoCount
,
287 regtask_GetIDsOfNames
,
296 regtask_GetInstances
,
297 regtask_get_LastRunTime
,
298 regtask_get_LastTaskResult
,
299 regtask_get_NumberOfMissedRuns
,
300 regtask_get_NextRunTime
,
301 regtask_get_Definition
,
303 regtask_GetSecurityDescriptor
,
304 regtask_SetSecurityDescriptor
,
309 HRESULT
RegisteredTask_create(const WCHAR
*path
, const WCHAR
*name
, ITaskDefinition
*definition
, LONG flags
,
310 TASK_LOGON_TYPE logon
, IRegisteredTask
**obj
, BOOL create
)
313 RegisteredTask
*regtask
;
318 if (!create
) return E_INVALIDARG
;
320 /* NULL task name is allowed only in the root folder */
321 if (path
[0] != '\\' || path
[1])
328 full_name
= get_full_path(path
, name
);
329 if (!full_name
) return E_OUTOFMEMORY
;
332 regtask
= heap_alloc(sizeof(*regtask
));
335 heap_free(full_name
);
336 return E_OUTOFMEMORY
;
341 WCHAR
*actual_path
= NULL
;
342 TASK_XML_ERROR_INFO
*error_info
= NULL
;
345 hr
= ITaskDefinition_get_XmlText(definition
, &xml
);
346 if (hr
!= S_OK
|| (hr
= SchRpcRegisterTask(full_name
, xml
, flags
, NULL
, logon
, 0, NULL
, &actual_path
, &error_info
)) != S_OK
)
348 heap_free(full_name
);
354 heap_free(full_name
);
355 full_name
= heap_strdupW(actual_path
);
356 MIDL_user_free(actual_path
);
360 static const WCHAR languages
[] = { 0 };
364 hr
= SchRpcRetrieveTask(full_name
, languages
, &count
, &xml
);
365 if (hr
!= S_OK
|| (hr
= ITaskDefinition_put_XmlText(definition
, xml
)) != S_OK
)
367 heap_free(full_name
);
374 regtask
->IRegisteredTask_iface
.lpVtbl
= &RegisteredTask_vtbl
;
375 regtask
->path
= full_name
;
377 regtask
->taskdef
= definition
;
378 *obj
= ®task
->IRegisteredTask_iface
;
380 TRACE("created %p\n", *obj
);
387 IRegisteredTaskCollection IRegisteredTaskCollection_iface
;
390 } RegisteredTaskCollection
;
392 static inline RegisteredTaskCollection
*impl_from_IRegisteredTaskCollection(IRegisteredTaskCollection
*iface
)
394 return CONTAINING_RECORD(iface
, RegisteredTaskCollection
, IRegisteredTaskCollection_iface
);
397 static ULONG WINAPI
regtasks_AddRef(IRegisteredTaskCollection
*iface
)
399 RegisteredTaskCollection
*regtasks
= impl_from_IRegisteredTaskCollection(iface
);
400 return InterlockedIncrement(®tasks
->ref
);
403 static ULONG WINAPI
regtasks_Release(IRegisteredTaskCollection
*iface
)
405 RegisteredTaskCollection
*regtasks
= impl_from_IRegisteredTaskCollection(iface
);
406 LONG ref
= InterlockedDecrement(®tasks
->ref
);
410 TRACE("destroying %p\n", iface
);
411 heap_free(regtasks
->path
);
418 static HRESULT WINAPI
regtasks_QueryInterface(IRegisteredTaskCollection
*iface
, REFIID riid
, void **obj
)
420 if (!riid
|| !obj
) return E_INVALIDARG
;
422 TRACE("%p,%s,%p\n", iface
, debugstr_guid(riid
), obj
);
424 if (IsEqualGUID(riid
, &IID_IRegisteredTaskCollection
) ||
425 IsEqualGUID(riid
, &IID_IDispatch
) ||
426 IsEqualGUID(riid
, &IID_IUnknown
))
428 IRegisteredTaskCollection_AddRef(iface
);
433 FIXME("interface %s is not implemented\n", debugstr_guid(riid
));
435 return E_NOINTERFACE
;
438 static HRESULT WINAPI
regtasks_GetTypeInfoCount(IRegisteredTaskCollection
*iface
, UINT
*count
)
440 FIXME("%p,%p: stub\n", iface
, count
);
444 static HRESULT WINAPI
regtasks_GetTypeInfo(IRegisteredTaskCollection
*iface
, UINT index
, LCID lcid
, ITypeInfo
**info
)
446 FIXME("%p,%u,%u,%p: stub\n", iface
, index
, lcid
, info
);
450 static HRESULT WINAPI
regtasks_GetIDsOfNames(IRegisteredTaskCollection
*iface
, REFIID riid
, LPOLESTR
*names
,
451 UINT count
, LCID lcid
, DISPID
*dispid
)
453 FIXME("%p,%s,%p,%u,%u,%p: stub\n", iface
, debugstr_guid(riid
), names
, count
, lcid
, dispid
);
457 static HRESULT WINAPI
regtasks_Invoke(IRegisteredTaskCollection
*iface
, DISPID dispid
, REFIID riid
, LCID lcid
, WORD flags
,
458 DISPPARAMS
*params
, VARIANT
*result
, EXCEPINFO
*excepinfo
, UINT
*argerr
)
460 FIXME("%p,%d,%s,%04x,%04x,%p,%p,%p,%p: stub\n", iface
, dispid
, debugstr_guid(riid
), lcid
, flags
,
461 params
, result
, excepinfo
, argerr
);
465 static HRESULT WINAPI
regtasks_get_Count(IRegisteredTaskCollection
*iface
, LONG
*count
)
467 FIXME("%p,%p: stub\n", iface
, count
);
471 static HRESULT WINAPI
regtasks_get_Item(IRegisteredTaskCollection
*iface
, VARIANT index
, IRegisteredTask
**regtask
)
473 FIXME("%p,%s,%p: stub\n", iface
, debugstr_variant(&index
), regtask
);
477 static HRESULT WINAPI
regtasks_get__NewEnum(IRegisteredTaskCollection
*iface
, IUnknown
**penum
)
479 FIXME("%p,%p: stub\n", iface
, penum
);
483 static const IRegisteredTaskCollectionVtbl RegisteredTaskCollection_vtbl
=
485 regtasks_QueryInterface
,
488 regtasks_GetTypeInfoCount
,
489 regtasks_GetTypeInfo
,
490 regtasks_GetIDsOfNames
,
494 regtasks_get__NewEnum
497 HRESULT
RegisteredTaskCollection_create(const WCHAR
*path
, IRegisteredTaskCollection
**obj
)
499 RegisteredTaskCollection
*regtasks
;
501 regtasks
= heap_alloc(sizeof(*regtasks
));
502 if (!regtasks
) return E_OUTOFMEMORY
;
504 regtasks
->IRegisteredTaskCollection_iface
.lpVtbl
= &RegisteredTaskCollection_vtbl
;
506 regtasks
->path
= heap_strdupW(path
);
507 *obj
= ®tasks
->IRegisteredTaskCollection_iface
;
509 TRACE("created %p\n", *obj
);