shell32: Release the returned imagelist.
[wine.git] / dlls / taskschd / regtask.c
blob10562fe08d9eb4f22c4ffc01c21af146f90e7138
1 /*
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
19 #include <stdarg.h>
21 #define COBJMACROS
23 #include "windef.h"
24 #include "winbase.h"
25 #include "winreg.h"
26 #include "objbase.h"
27 #include "taskschd.h"
28 #include "schrpc.h"
29 #include "taskschd_private.h"
31 #include "wine/unicode.h"
32 #include "wine/debug.h"
34 WINE_DEFAULT_DEBUG_CHANNEL(taskschd);
36 typedef struct
38 IRegisteredTask IRegisteredTask_iface;
39 LONG ref;
40 WCHAR *path;
41 ITaskDefinition *taskdef;
42 } RegisteredTask;
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(&regtask->ref);
55 static ULONG WINAPI regtask_Release(IRegisteredTask *iface)
57 RegisteredTask *regtask = impl_from_IRegisteredTask(iface);
58 LONG ref = InterlockedDecrement(&regtask->ref);
60 if (!ref)
62 TRACE("destroying %p\n", iface);
63 ITaskDefinition_Release(regtask->taskdef);
64 heap_free(regtask->path);
65 heap_free(regtask);
68 return ref;
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);
82 *obj = iface;
83 return S_OK;
86 FIXME("interface %s is not implemented\n", debugstr_guid(riid));
87 *obj = NULL;
88 return E_NOINTERFACE;
91 static HRESULT WINAPI regtask_GetTypeInfoCount(IRegisteredTask *iface, UINT *count)
93 FIXME("%p,%p: stub\n", iface, count);
94 return E_NOTIMPL;
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);
100 return E_NOTIMPL;
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);
107 return E_NOTIMPL;
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);
115 return E_NOTIMPL;
118 static HRESULT WINAPI regtask_get_Name(IRegisteredTask *iface, BSTR *name)
120 RegisteredTask *regtask = impl_from_IRegisteredTask(iface);
121 const WCHAR *p_name;
123 TRACE("%p,%p\n", iface, name);
125 if (!name) return E_POINTER;
127 p_name = strrchrW(regtask->path, '\\');
128 if (!p_name)
129 p_name = regtask->path;
130 else
131 if (p_name[1] != 0) p_name++;
133 *name = SysAllocString(p_name);
134 if (!*name) return E_OUTOFMEMORY;
136 return S_OK;
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;
150 return S_OK;
153 static HRESULT WINAPI regtask_get_State(IRegisteredTask *iface, TASK_STATE *state)
155 RegisteredTask *regtask = impl_from_IRegisteredTask(iface);
156 DWORD enabled;
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;
169 HRESULT hr;
171 TRACE("%p,%p\n", iface, v_enabled);
173 if (!v_enabled) return E_POINTER;
175 hr = SchRpcGetTaskInfo(regtask->path, 0, &enabled, &state);
176 if (hr == S_OK)
177 *v_enabled = enabled ? VARIANT_TRUE : VARIANT_FALSE;
178 return hr;
181 static HRESULT WINAPI regtask_put_Enabled(IRegisteredTask *iface, VARIANT_BOOL enabled)
183 FIXME("%p,%d: stub\n", iface, enabled);
184 return E_NOTIMPL;
187 static HRESULT WINAPI regtask_Run(IRegisteredTask *iface, VARIANT params, IRunningTask **task)
189 FIXME("%p,%s,%p: stub\n", iface, debugstr_variant(&params), task);
190 return E_NOTIMPL;
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(&params), flags, session_id, debugstr_w(user), task);
197 return E_NOTIMPL;
200 static HRESULT WINAPI regtask_GetInstances(IRegisteredTask *iface, LONG flags, IRunningTaskCollection **tasks)
202 FIXME("%p,%x,%p: stub\n", iface, flags, tasks);
203 return E_NOTIMPL;
206 static HRESULT WINAPI regtask_get_LastRunTime(IRegisteredTask *iface, DATE *date)
208 FIXME("%p,%p: stub\n", iface, date);
209 return E_NOTIMPL;
212 static HRESULT WINAPI regtask_get_LastTaskResult(IRegisteredTask *iface, LONG *result)
214 FIXME("%p,%p: stub\n", iface, result);
215 return E_NOTIMPL;
218 static HRESULT WINAPI regtask_get_NumberOfMissedRuns(IRegisteredTask *iface, LONG *runs)
220 FIXME("%p,%p: stub\n", iface, runs);
221 return E_NOTIMPL;
224 static HRESULT WINAPI regtask_get_NextRunTime(IRegisteredTask *iface, DATE *date)
226 FIXME("%p,%p: stub\n", iface, date);
227 return E_NOTIMPL;
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;
241 return S_OK;
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);
258 return E_NOTIMPL;
261 static HRESULT WINAPI regtask_SetSecurityDescriptor(IRegisteredTask *iface, BSTR sddl, LONG flags)
263 FIXME("%p,%s,%x: stub\n", iface, debugstr_w(sddl), flags);
264 return E_NOTIMPL;
267 static HRESULT WINAPI regtask_Stop(IRegisteredTask *iface, LONG flags)
269 FIXME("%p,%x: stub\n", iface, flags);
270 return E_NOTIMPL;
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);
277 return E_NOTIMPL;
280 static const IRegisteredTaskVtbl RegisteredTask_vtbl =
282 regtask_QueryInterface,
283 regtask_AddRef,
284 regtask_Release,
285 regtask_GetTypeInfoCount,
286 regtask_GetTypeInfo,
287 regtask_GetIDsOfNames,
288 regtask_Invoke,
289 regtask_get_Name,
290 regtask_get_Path,
291 regtask_get_State,
292 regtask_get_Enabled,
293 regtask_put_Enabled,
294 regtask_Run,
295 regtask_RunEx,
296 regtask_GetInstances,
297 regtask_get_LastRunTime,
298 regtask_get_LastTaskResult,
299 regtask_get_NumberOfMissedRuns,
300 regtask_get_NextRunTime,
301 regtask_get_Definition,
302 regtask_get_Xml,
303 regtask_GetSecurityDescriptor,
304 regtask_SetSecurityDescriptor,
305 regtask_Stop,
306 regtask_GetRunTimes
309 HRESULT RegisteredTask_create(const WCHAR *path, const WCHAR *name, ITaskDefinition *definition, LONG flags,
310 TASK_LOGON_TYPE logon, IRegisteredTask **obj, BOOL create)
312 WCHAR *full_name;
313 RegisteredTask *regtask;
314 HRESULT hr;
316 if (!name)
318 if (!create) return E_INVALIDARG;
320 /* NULL task name is allowed only in the root folder */
321 if (path[0] != '\\' || path[1])
322 return E_INVALIDARG;
324 full_name = NULL;
326 else
328 full_name = get_full_path(path, name);
329 if (!full_name) return E_OUTOFMEMORY;
332 regtask = heap_alloc(sizeof(*regtask));
333 if (!regtask)
335 heap_free(full_name);
336 return E_OUTOFMEMORY;
339 if (create)
341 WCHAR *actual_path = NULL;
342 TASK_XML_ERROR_INFO *error_info = NULL;
343 BSTR xml = 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);
349 heap_free(regtask);
350 SysFreeString(xml);
351 return hr;
354 heap_free(full_name);
355 full_name = heap_strdupW(actual_path);
356 MIDL_user_free(actual_path);
358 else
360 static const WCHAR languages[] = { 0 };
361 DWORD count = 0;
362 WCHAR *xml = NULL;
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);
368 heap_free(regtask);
369 return hr;
371 MIDL_user_free(xml);
374 regtask->IRegisteredTask_iface.lpVtbl = &RegisteredTask_vtbl;
375 regtask->path = full_name;
376 regtask->ref = 1;
377 regtask->taskdef = definition;
378 *obj = &regtask->IRegisteredTask_iface;
380 TRACE("created %p\n", *obj);
382 return S_OK;
385 typedef struct
387 IRegisteredTaskCollection IRegisteredTaskCollection_iface;
388 LONG ref;
389 WCHAR *path;
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(&regtasks->ref);
403 static ULONG WINAPI regtasks_Release(IRegisteredTaskCollection *iface)
405 RegisteredTaskCollection *regtasks = impl_from_IRegisteredTaskCollection(iface);
406 LONG ref = InterlockedDecrement(&regtasks->ref);
408 if (!ref)
410 TRACE("destroying %p\n", iface);
411 heap_free(regtasks->path);
412 heap_free(regtasks);
415 return ref;
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);
429 *obj = iface;
430 return S_OK;
433 FIXME("interface %s is not implemented\n", debugstr_guid(riid));
434 *obj = NULL;
435 return E_NOINTERFACE;
438 static HRESULT WINAPI regtasks_GetTypeInfoCount(IRegisteredTaskCollection *iface, UINT *count)
440 FIXME("%p,%p: stub\n", iface, count);
441 return E_NOTIMPL;
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);
447 return E_NOTIMPL;
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);
454 return E_NOTIMPL;
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);
462 return E_NOTIMPL;
465 static HRESULT WINAPI regtasks_get_Count(IRegisteredTaskCollection *iface, LONG *count)
467 FIXME("%p,%p: stub\n", iface, count);
468 return E_NOTIMPL;
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);
474 return E_NOTIMPL;
477 static HRESULT WINAPI regtasks_get__NewEnum(IRegisteredTaskCollection *iface, IUnknown **penum)
479 FIXME("%p,%p: stub\n", iface, penum);
480 return E_NOTIMPL;
483 static const IRegisteredTaskCollectionVtbl RegisteredTaskCollection_vtbl =
485 regtasks_QueryInterface,
486 regtasks_AddRef,
487 regtasks_Release,
488 regtasks_GetTypeInfoCount,
489 regtasks_GetTypeInfo,
490 regtasks_GetIDsOfNames,
491 regtasks_Invoke,
492 regtasks_get_Count,
493 regtasks_get_Item,
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;
505 regtasks->ref = 1;
506 regtasks->path = heap_strdupW(path);
507 *obj = &regtasks->IRegisteredTaskCollection_iface;
509 TRACE("created %p\n", *obj);
511 return S_OK;