windows.applicationmodel/tests: Use PathRemoveFileSpecW() instead of PathCchRemoveFil...
[wine.git] / dlls / taskschd / regtask.c
blobbae0d4cb0b294d6e0b49a5e77b132439a89c3d2f
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/debug.h"
33 WINE_DEFAULT_DEBUG_CHANNEL(taskschd);
35 typedef struct
37 IRegisteredTask IRegisteredTask_iface;
38 LONG ref;
39 WCHAR *path;
40 ITaskDefinition *taskdef;
41 } RegisteredTask;
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(&regtask->ref);
54 static ULONG WINAPI regtask_Release(IRegisteredTask *iface)
56 RegisteredTask *regtask = impl_from_IRegisteredTask(iface);
57 LONG ref = InterlockedDecrement(&regtask->ref);
59 if (!ref)
61 TRACE("destroying %p\n", iface);
62 ITaskDefinition_Release(regtask->taskdef);
63 free(regtask->path);
64 free(regtask);
67 return ref;
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);
81 *obj = iface;
82 return S_OK;
85 FIXME("interface %s is not implemented\n", debugstr_guid(riid));
86 *obj = NULL;
87 return E_NOINTERFACE;
90 static HRESULT WINAPI regtask_GetTypeInfoCount(IRegisteredTask *iface, UINT *count)
92 FIXME("%p,%p: stub\n", iface, count);
93 return E_NOTIMPL;
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);
99 return E_NOTIMPL;
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);
106 return E_NOTIMPL;
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);
114 return E_NOTIMPL;
117 static HRESULT WINAPI regtask_get_Name(IRegisteredTask *iface, BSTR *name)
119 RegisteredTask *regtask = impl_from_IRegisteredTask(iface);
120 const WCHAR *p_name;
122 TRACE("%p,%p\n", iface, name);
124 if (!name) return E_POINTER;
126 p_name = wcsrchr(regtask->path, '\\');
127 if (!p_name)
128 p_name = regtask->path;
129 else
130 if (p_name[1] != 0) p_name++;
132 *name = SysAllocString(p_name);
133 if (!*name) return E_OUTOFMEMORY;
135 return S_OK;
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;
149 return S_OK;
152 static HRESULT WINAPI regtask_get_State(IRegisteredTask *iface, TASK_STATE *state)
154 RegisteredTask *regtask = impl_from_IRegisteredTask(iface);
155 DWORD enabled;
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;
168 HRESULT hr;
170 TRACE("%p,%p\n", iface, v_enabled);
172 if (!v_enabled) return E_POINTER;
174 hr = SchRpcGetTaskInfo(regtask->path, 0, &enabled, &state);
175 if (hr == S_OK)
176 *v_enabled = enabled ? VARIANT_TRUE : VARIANT_FALSE;
177 return hr;
180 static HRESULT WINAPI regtask_put_Enabled(IRegisteredTask *iface, VARIANT_BOOL enabled)
182 FIXME("%p,%d: stub\n", iface, enabled);
183 return S_OK;
186 static HRESULT WINAPI regtask_Run(IRegisteredTask *iface, VARIANT params, IRunningTask **task)
188 FIXME("%p,%s,%p: stub\n", iface, debugstr_variant(&params), task);
189 return E_NOTIMPL;
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(&params), flags, session_id, debugstr_w(user), task);
196 return E_NOTIMPL;
199 static HRESULT WINAPI regtask_GetInstances(IRegisteredTask *iface, LONG flags, IRunningTaskCollection **tasks)
201 FIXME("%p,%lx,%p: stub\n", iface, flags, tasks);
202 return E_NOTIMPL;
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);
214 return E_NOTIMPL;
217 static HRESULT WINAPI regtask_get_NumberOfMissedRuns(IRegisteredTask *iface, LONG *runs)
219 FIXME("%p,%p: stub\n", iface, runs);
220 return E_NOTIMPL;
223 static HRESULT WINAPI regtask_get_NextRunTime(IRegisteredTask *iface, DATE *date)
225 FIXME("%p,%p: stub\n", iface, date);
226 return E_NOTIMPL;
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;
240 return S_OK;
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);
257 return E_NOTIMPL;
260 static HRESULT WINAPI regtask_SetSecurityDescriptor(IRegisteredTask *iface, BSTR sddl, LONG flags)
262 FIXME("%p,%s,%lx: stub\n", iface, debugstr_w(sddl), flags);
263 return E_NOTIMPL;
266 static HRESULT WINAPI regtask_Stop(IRegisteredTask *iface, LONG flags)
268 FIXME("%p,%lx: stub\n", iface, flags);
269 return E_NOTIMPL;
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);
276 return E_NOTIMPL;
279 static const IRegisteredTaskVtbl RegisteredTask_vtbl =
281 regtask_QueryInterface,
282 regtask_AddRef,
283 regtask_Release,
284 regtask_GetTypeInfoCount,
285 regtask_GetTypeInfo,
286 regtask_GetIDsOfNames,
287 regtask_Invoke,
288 regtask_get_Name,
289 regtask_get_Path,
290 regtask_get_State,
291 regtask_get_Enabled,
292 regtask_put_Enabled,
293 regtask_Run,
294 regtask_RunEx,
295 regtask_GetInstances,
296 regtask_get_LastRunTime,
297 regtask_get_LastTaskResult,
298 regtask_get_NumberOfMissedRuns,
299 regtask_get_NextRunTime,
300 regtask_get_Definition,
301 regtask_get_Xml,
302 regtask_GetSecurityDescriptor,
303 regtask_SetSecurityDescriptor,
304 regtask_Stop,
305 regtask_GetRunTimes
308 HRESULT RegisteredTask_create(const WCHAR *path, const WCHAR *name, ITaskDefinition *definition, LONG flags,
309 TASK_LOGON_TYPE logon, IRegisteredTask **obj, BOOL create)
311 WCHAR *full_name;
312 RegisteredTask *regtask;
313 HRESULT hr;
315 if (!name)
317 if (!create) return E_INVALIDARG;
319 /* NULL task name is allowed only in the root folder */
320 if (path[0] != '\\' || path[1])
321 return E_INVALIDARG;
323 full_name = NULL;
325 else
327 full_name = get_full_path(path, name);
328 if (!full_name) return E_OUTOFMEMORY;
331 regtask = malloc(sizeof(*regtask));
332 if (!regtask)
334 free(full_name);
335 return E_OUTOFMEMORY;
338 if (create)
340 WCHAR *actual_path = NULL;
341 TASK_XML_ERROR_INFO *error_info = NULL;
342 BSTR xml = 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)
347 free(full_name);
348 free(regtask);
349 SysFreeString(xml);
350 return hr;
352 SysFreeString(xml);
354 free(full_name);
355 full_name = wcsdup(actual_path);
356 MIDL_user_free(actual_path);
358 else
360 DWORD count = 0;
361 WCHAR *xml = NULL;
363 hr = SchRpcRetrieveTask(full_name, L"", &count, &xml);
364 if (hr != S_OK || (hr = ITaskDefinition_put_XmlText(definition, xml)) != S_OK)
366 free(full_name);
367 free(regtask);
368 MIDL_user_free(xml);
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 free(regtasks->path);
412 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,%lu,%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,%lu,%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,%ld,%s,%04lx,%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 if (count) *count = 0;
469 return E_NOTIMPL;
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);
475 return E_NOTIMPL;
478 static HRESULT WINAPI regtasks_get__NewEnum(IRegisteredTaskCollection *iface, IUnknown **penum)
480 FIXME("%p,%p: stub\n", iface, penum);
481 return E_NOTIMPL;
484 static const IRegisteredTaskCollectionVtbl RegisteredTaskCollection_vtbl =
486 regtasks_QueryInterface,
487 regtasks_AddRef,
488 regtasks_Release,
489 regtasks_GetTypeInfoCount,
490 regtasks_GetTypeInfo,
491 regtasks_GetIDsOfNames,
492 regtasks_Invoke,
493 regtasks_get_Count,
494 regtasks_get_Item,
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;
506 regtasks->ref = 1;
507 regtasks->path = wcsdup(path);
508 *obj = &regtasks->IRegisteredTaskCollection_iface;
510 TRACE("created %p\n", *obj);
512 return S_OK;