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/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(taskschd
);
37 IRegisteredTask IRegisteredTask_iface
;
40 ITaskDefinition
*taskdef
;
43 static inline RegisteredTask
*impl_from_IRegisteredTask(IRegisteredTask
*iface
)
45 return CONTAINING_RECORD(iface
, RegisteredTask
, IRegisteredTask_iface
);
48 static ULONG WINAPI
regtask_AddRef(IRegisteredTask
*iface
)
50 RegisteredTask
*regtask
= impl_from_IRegisteredTask(iface
);
51 return InterlockedIncrement(®task
->ref
);
54 static ULONG WINAPI
regtask_Release(IRegisteredTask
*iface
)
56 RegisteredTask
*regtask
= impl_from_IRegisteredTask(iface
);
57 LONG ref
= InterlockedDecrement(®task
->ref
);
61 TRACE("destroying %p\n", iface
);
62 ITaskDefinition_Release(regtask
->taskdef
);
70 static HRESULT WINAPI
regtask_QueryInterface(IRegisteredTask
*iface
, REFIID riid
, void **obj
)
72 if (!riid
|| !obj
) return E_INVALIDARG
;
74 TRACE("%p,%s,%p\n", iface
, debugstr_guid(riid
), obj
);
76 if (IsEqualGUID(riid
, &IID_IRegisteredTask
) ||
77 IsEqualGUID(riid
, &IID_IDispatch
) ||
78 IsEqualGUID(riid
, &IID_IUnknown
))
80 IRegisteredTask_AddRef(iface
);
85 FIXME("interface %s is not implemented\n", debugstr_guid(riid
));
90 static HRESULT WINAPI
regtask_GetTypeInfoCount(IRegisteredTask
*iface
, UINT
*count
)
92 FIXME("%p,%p: stub\n", iface
, count
);
96 static HRESULT WINAPI
regtask_GetTypeInfo(IRegisteredTask
*iface
, UINT index
, LCID lcid
, ITypeInfo
**info
)
98 FIXME("%p,%u,%lu,%p: stub\n", iface
, index
, lcid
, info
);
102 static HRESULT WINAPI
regtask_GetIDsOfNames(IRegisteredTask
*iface
, REFIID riid
, LPOLESTR
*names
,
103 UINT count
, LCID lcid
, DISPID
*dispid
)
105 FIXME("%p,%s,%p,%u,%lu,%p: stub\n", iface
, debugstr_guid(riid
), names
, count
, lcid
, dispid
);
109 static HRESULT WINAPI
regtask_Invoke(IRegisteredTask
*iface
, DISPID dispid
, REFIID riid
, LCID lcid
, WORD flags
,
110 DISPPARAMS
*params
, VARIANT
*result
, EXCEPINFO
*excepinfo
, UINT
*argerr
)
112 FIXME("%p,%ld,%s,%04lx,%04x,%p,%p,%p,%p: stub\n", iface
, dispid
, debugstr_guid(riid
), lcid
, flags
,
113 params
, result
, excepinfo
, argerr
);
117 static HRESULT WINAPI
regtask_get_Name(IRegisteredTask
*iface
, BSTR
*name
)
119 RegisteredTask
*regtask
= impl_from_IRegisteredTask(iface
);
122 TRACE("%p,%p\n", iface
, name
);
124 if (!name
) return E_POINTER
;
126 p_name
= wcsrchr(regtask
->path
, '\\');
128 p_name
= regtask
->path
;
130 if (p_name
[1] != 0) p_name
++;
132 *name
= SysAllocString(p_name
);
133 if (!*name
) return E_OUTOFMEMORY
;
138 static HRESULT WINAPI
regtask_get_Path(IRegisteredTask
*iface
, BSTR
*path
)
140 RegisteredTask
*regtask
= impl_from_IRegisteredTask(iface
);
142 TRACE("%p,%p\n", iface
, path
);
144 if (!path
) return E_POINTER
;
146 *path
= SysAllocString(regtask
->path
);
147 if (!*path
) return E_OUTOFMEMORY
;
152 static HRESULT WINAPI
regtask_get_State(IRegisteredTask
*iface
, TASK_STATE
*state
)
154 RegisteredTask
*regtask
= impl_from_IRegisteredTask(iface
);
157 TRACE("%p,%p\n", iface
, state
);
159 if (!state
) return E_POINTER
;
161 return SchRpcGetTaskInfo(regtask
->path
, SCH_FLAG_STATE
, &enabled
, (DWORD
*)state
);
164 static HRESULT WINAPI
regtask_get_Enabled(IRegisteredTask
*iface
, VARIANT_BOOL
*v_enabled
)
166 RegisteredTask
*regtask
= impl_from_IRegisteredTask(iface
);
167 DWORD enabled
, state
;
170 TRACE("%p,%p\n", iface
, v_enabled
);
172 if (!v_enabled
) return E_POINTER
;
174 hr
= SchRpcGetTaskInfo(regtask
->path
, 0, &enabled
, &state
);
176 *v_enabled
= enabled
? VARIANT_TRUE
: VARIANT_FALSE
;
180 static HRESULT WINAPI
regtask_put_Enabled(IRegisteredTask
*iface
, VARIANT_BOOL enabled
)
182 FIXME("%p,%d: stub\n", iface
, enabled
);
186 static HRESULT WINAPI
regtask_Run(IRegisteredTask
*iface
, VARIANT params
, IRunningTask
**task
)
188 FIXME("%p,%s,%p: stub\n", iface
, debugstr_variant(¶ms
), task
);
192 static HRESULT WINAPI
regtask_RunEx(IRegisteredTask
*iface
, VARIANT params
, LONG flags
,
193 LONG session_id
, BSTR user
, IRunningTask
**task
)
195 FIXME("%p,%s,%lx,%lx,%s,%p: stub\n", iface
, debugstr_variant(¶ms
), flags
, session_id
, debugstr_w(user
), task
);
199 static HRESULT WINAPI
regtask_GetInstances(IRegisteredTask
*iface
, LONG flags
, IRunningTaskCollection
**tasks
)
201 FIXME("%p,%lx,%p: stub\n", iface
, flags
, tasks
);
205 static HRESULT WINAPI
regtask_get_LastRunTime(IRegisteredTask
*iface
, DATE
*date
)
207 FIXME("%p,%p: stub\n", iface
, date
);
208 return SCHED_S_TASK_HAS_NOT_RUN
;
211 static HRESULT WINAPI
regtask_get_LastTaskResult(IRegisteredTask
*iface
, LONG
*result
)
213 FIXME("%p,%p: stub\n", iface
, result
);
217 static HRESULT WINAPI
regtask_get_NumberOfMissedRuns(IRegisteredTask
*iface
, LONG
*runs
)
219 FIXME("%p,%p: stub\n", iface
, runs
);
223 static HRESULT WINAPI
regtask_get_NextRunTime(IRegisteredTask
*iface
, DATE
*date
)
225 FIXME("%p,%p: stub\n", iface
, date
);
229 static HRESULT WINAPI
regtask_get_Definition(IRegisteredTask
*iface
, ITaskDefinition
**task
)
231 RegisteredTask
*regtask
= impl_from_IRegisteredTask(iface
);
233 TRACE("%p,%p\n", iface
, task
);
235 if (!task
) return E_POINTER
;
237 ITaskDefinition_AddRef(regtask
->taskdef
);
238 *task
= regtask
->taskdef
;
243 static HRESULT WINAPI
regtask_get_Xml(IRegisteredTask
*iface
, BSTR
*xml
)
245 RegisteredTask
*regtask
= impl_from_IRegisteredTask(iface
);
247 TRACE("%p,%p\n", iface
, xml
);
249 if (!xml
) return E_POINTER
;
251 return ITaskDefinition_get_XmlText(regtask
->taskdef
, xml
);
254 static HRESULT WINAPI
regtask_GetSecurityDescriptor(IRegisteredTask
*iface
, LONG info
, BSTR
*sddl
)
256 FIXME("%p,%lx,%p: stub\n", iface
, info
, sddl
);
260 static HRESULT WINAPI
regtask_SetSecurityDescriptor(IRegisteredTask
*iface
, BSTR sddl
, LONG flags
)
262 FIXME("%p,%s,%lx: stub\n", iface
, debugstr_w(sddl
), flags
);
266 static HRESULT WINAPI
regtask_Stop(IRegisteredTask
*iface
, LONG flags
)
268 FIXME("%p,%lx: stub\n", iface
, flags
);
272 static HRESULT WINAPI
regtask_GetRunTimes(IRegisteredTask
*iface
, const LPSYSTEMTIME start
, const LPSYSTEMTIME end
,
273 DWORD
*count
, LPSYSTEMTIME
*time
)
275 FIXME("%p,%p.%p,%p,%p: stub\n", iface
, start
, end
, count
, time
);
279 static const IRegisteredTaskVtbl RegisteredTask_vtbl
=
281 regtask_QueryInterface
,
284 regtask_GetTypeInfoCount
,
286 regtask_GetIDsOfNames
,
295 regtask_GetInstances
,
296 regtask_get_LastRunTime
,
297 regtask_get_LastTaskResult
,
298 regtask_get_NumberOfMissedRuns
,
299 regtask_get_NextRunTime
,
300 regtask_get_Definition
,
302 regtask_GetSecurityDescriptor
,
303 regtask_SetSecurityDescriptor
,
308 HRESULT
RegisteredTask_create(const WCHAR
*path
, const WCHAR
*name
, ITaskDefinition
*definition
, LONG flags
,
309 TASK_LOGON_TYPE logon
, IRegisteredTask
**obj
, BOOL create
)
312 RegisteredTask
*regtask
;
317 if (!create
) return E_INVALIDARG
;
319 /* NULL task name is allowed only in the root folder */
320 if (path
[0] != '\\' || path
[1])
327 full_name
= get_full_path(path
, name
);
328 if (!full_name
) return E_OUTOFMEMORY
;
331 regtask
= malloc(sizeof(*regtask
));
335 return E_OUTOFMEMORY
;
340 WCHAR
*actual_path
= NULL
;
341 TASK_XML_ERROR_INFO
*error_info
= NULL
;
344 hr
= ITaskDefinition_get_XmlText(definition
, &xml
);
345 if (hr
!= S_OK
|| (hr
= SchRpcRegisterTask(full_name
, xml
, flags
, NULL
, logon
, 0, NULL
, &actual_path
, &error_info
)) != S_OK
)
355 full_name
= wcsdup(actual_path
);
356 MIDL_user_free(actual_path
);
363 hr
= SchRpcRetrieveTask(full_name
, L
"", &count
, &xml
);
364 if (hr
!= S_OK
|| (hr
= ITaskDefinition_put_XmlText(definition
, xml
)) != S_OK
)
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 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,%lu,%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,%lu,%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,%ld,%s,%04lx,%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
);
468 if (count
) *count
= 0;
472 static HRESULT WINAPI
regtasks_get_Item(IRegisteredTaskCollection
*iface
, VARIANT index
, IRegisteredTask
**regtask
)
474 FIXME("%p,%s,%p: stub\n", iface
, debugstr_variant(&index
), regtask
);
478 static HRESULT WINAPI
regtasks_get__NewEnum(IRegisteredTaskCollection
*iface
, IUnknown
**penum
)
480 FIXME("%p,%p: stub\n", iface
, penum
);
484 static const IRegisteredTaskCollectionVtbl RegisteredTaskCollection_vtbl
=
486 regtasks_QueryInterface
,
489 regtasks_GetTypeInfoCount
,
490 regtasks_GetTypeInfo
,
491 regtasks_GetIDsOfNames
,
495 regtasks_get__NewEnum
498 HRESULT
RegisteredTaskCollection_create(const WCHAR
*path
, IRegisteredTaskCollection
**obj
)
500 RegisteredTaskCollection
*regtasks
;
502 regtasks
= malloc(sizeof(*regtasks
));
503 if (!regtasks
) return E_OUTOFMEMORY
;
505 regtasks
->IRegisteredTaskCollection_iface
.lpVtbl
= &RegisteredTaskCollection_vtbl
;
507 regtasks
->path
= wcsdup(path
);
508 *obj
= ®tasks
->IRegisteredTaskCollection_iface
;
510 TRACE("created %p\n", *obj
);