msvcrt: _filbuf should not lock any file.
[wine.git] / dlls / taskschd / task.c
blobd1bc7eb9b5789bc2616a50095fb14364800bd501
1 /*
2 * Copyright 2013 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 "initguid.h"
26 #include "objbase.h"
27 #include "xmllite.h"
28 #include "taskschd.h"
29 #include "winsvc.h"
30 #include "schrpc.h"
31 #include "taskschd_private.h"
33 #include "wine/unicode.h"
34 #include "wine/debug.h"
36 WINE_DEFAULT_DEBUG_CHANNEL(taskschd);
38 typedef struct
40 IRegistrationInfo IRegistrationInfo_iface;
41 LONG ref;
42 WCHAR *description, *author, *version, *date, *documentation, *uri, *source;
43 } registration_info;
45 static inline registration_info *impl_from_IRegistrationInfo(IRegistrationInfo *iface)
47 return CONTAINING_RECORD(iface, registration_info, IRegistrationInfo_iface);
50 static ULONG WINAPI RegistrationInfo_AddRef(IRegistrationInfo *iface)
52 registration_info *reginfo = impl_from_IRegistrationInfo(iface);
53 return InterlockedIncrement(&reginfo->ref);
56 static ULONG WINAPI RegistrationInfo_Release(IRegistrationInfo *iface)
58 registration_info *reginfo = impl_from_IRegistrationInfo(iface);
59 LONG ref = InterlockedDecrement(&reginfo->ref);
61 if (!ref)
63 TRACE("destroying %p\n", iface);
64 heap_free(reginfo->description);
65 heap_free(reginfo->author);
66 heap_free(reginfo->version);
67 heap_free(reginfo->date);
68 heap_free(reginfo->documentation);
69 heap_free(reginfo->uri);
70 heap_free(reginfo->source);
71 heap_free(reginfo);
74 return ref;
77 static HRESULT WINAPI RegistrationInfo_QueryInterface(IRegistrationInfo *iface, REFIID riid, void **obj)
79 if (!riid || !obj) return E_INVALIDARG;
81 TRACE("%p,%s,%p\n", iface, debugstr_guid(riid), obj);
83 if (IsEqualGUID(riid, &IID_IRegistrationInfo) ||
84 IsEqualGUID(riid, &IID_IDispatch) ||
85 IsEqualGUID(riid, &IID_IUnknown))
87 IRegistrationInfo_AddRef(iface);
88 *obj = iface;
89 return S_OK;
92 FIXME("interface %s is not implemented\n", debugstr_guid(riid));
93 *obj = NULL;
94 return E_NOINTERFACE;
97 static HRESULT WINAPI RegistrationInfo_GetTypeInfoCount(IRegistrationInfo *iface, UINT *count)
99 FIXME("%p,%p: stub\n", iface, count);
100 return E_NOTIMPL;
103 static HRESULT WINAPI RegistrationInfo_GetTypeInfo(IRegistrationInfo *iface, UINT index, LCID lcid, ITypeInfo **info)
105 FIXME("%p,%u,%u,%p: stub\n", iface, index, lcid, info);
106 return E_NOTIMPL;
109 static HRESULT WINAPI RegistrationInfo_GetIDsOfNames(IRegistrationInfo *iface, REFIID riid, LPOLESTR *names,
110 UINT count, LCID lcid, DISPID *dispid)
112 FIXME("%p,%s,%p,%u,%u,%p: stub\n", iface, debugstr_guid(riid), names, count, lcid, dispid);
113 return E_NOTIMPL;
116 static HRESULT WINAPI RegistrationInfo_Invoke(IRegistrationInfo *iface, DISPID dispid, REFIID riid, LCID lcid, WORD flags,
117 DISPPARAMS *params, VARIANT *result, EXCEPINFO *excepinfo, UINT *argerr)
119 FIXME("%p,%d,%s,%04x,%04x,%p,%p,%p,%p: stub\n", iface, dispid, debugstr_guid(riid), lcid, flags,
120 params, result, excepinfo, argerr);
121 return E_NOTIMPL;
124 static HRESULT WINAPI RegistrationInfo_get_Description(IRegistrationInfo *iface, BSTR *description)
126 registration_info *reginfo = impl_from_IRegistrationInfo(iface);
128 TRACE("%p,%p\n", iface, description);
130 if (!description) return E_POINTER;
132 *description = SysAllocString(reginfo->description);
133 return S_OK;
136 static HRESULT WINAPI RegistrationInfo_put_Description(IRegistrationInfo *iface, BSTR description)
138 registration_info *reginfo = impl_from_IRegistrationInfo(iface);
140 TRACE("%p,%p\n", iface, debugstr_w(description));
142 if (!description) return E_INVALIDARG;
144 heap_free(reginfo->description);
145 reginfo->description = heap_strdupW(description);
146 /* FIXME: update XML on the server side */
147 return reginfo->description ? S_OK : E_OUTOFMEMORY;
150 static HRESULT WINAPI RegistrationInfo_get_Author(IRegistrationInfo *iface, BSTR *author)
152 registration_info *reginfo = impl_from_IRegistrationInfo(iface);
154 TRACE("%p,%p\n", iface, author);
156 if (!author) return E_POINTER;
158 *author = SysAllocString(reginfo->author);
159 return S_OK;
162 static HRESULT WINAPI RegistrationInfo_put_Author(IRegistrationInfo *iface, BSTR author)
164 registration_info *reginfo = impl_from_IRegistrationInfo(iface);
166 TRACE("%p,%p\n", iface, debugstr_w(author));
168 if (!author) return E_INVALIDARG;
170 heap_free(reginfo->author);
171 reginfo->author = heap_strdupW(author);
172 /* FIXME: update XML on the server side */
173 return reginfo->author ? S_OK : E_OUTOFMEMORY;
176 static HRESULT WINAPI RegistrationInfo_get_Version(IRegistrationInfo *iface, BSTR *version)
178 registration_info *reginfo = impl_from_IRegistrationInfo(iface);
180 TRACE("%p,%p\n", iface, version);
182 if (!version) return E_POINTER;
184 *version = SysAllocString(reginfo->version);
185 return S_OK;
188 static HRESULT WINAPI RegistrationInfo_put_Version(IRegistrationInfo *iface, BSTR version)
190 registration_info *reginfo = impl_from_IRegistrationInfo(iface);
192 TRACE("%p,%p\n", iface, debugstr_w(version));
194 if (!version) return E_INVALIDARG;
196 heap_free(reginfo->version);
197 reginfo->version = heap_strdupW(version);
198 /* FIXME: update XML on the server side */
199 return reginfo->version ? S_OK : E_OUTOFMEMORY;
202 static HRESULT WINAPI RegistrationInfo_get_Date(IRegistrationInfo *iface, BSTR *date)
204 registration_info *reginfo = impl_from_IRegistrationInfo(iface);
206 TRACE("%p,%p\n", iface, date);
208 if (!date) return E_POINTER;
210 *date = SysAllocString(reginfo->date);
211 return S_OK;
214 static HRESULT WINAPI RegistrationInfo_put_Date(IRegistrationInfo *iface, BSTR date)
216 registration_info *reginfo = impl_from_IRegistrationInfo(iface);
218 TRACE("%p,%p\n", iface, debugstr_w(date));
220 if (!date) return E_INVALIDARG;
222 heap_free(reginfo->date);
223 reginfo->date = heap_strdupW(date);
224 /* FIXME: update XML on the server side */
225 return reginfo->date ? S_OK : E_OUTOFMEMORY;
228 static HRESULT WINAPI RegistrationInfo_get_Documentation(IRegistrationInfo *iface, BSTR *doc)
230 registration_info *reginfo = impl_from_IRegistrationInfo(iface);
232 TRACE("%p,%p\n", iface, doc);
234 if (!doc) return E_POINTER;
236 *doc = SysAllocString(reginfo->documentation);
237 return S_OK;
240 static HRESULT WINAPI RegistrationInfo_put_Documentation(IRegistrationInfo *iface, BSTR doc)
242 registration_info *reginfo = impl_from_IRegistrationInfo(iface);
244 TRACE("%p,%p\n", iface, debugstr_w(doc));
246 if (!doc) return E_INVALIDARG;
248 heap_free(reginfo->documentation);
249 reginfo->documentation = heap_strdupW(doc);
250 /* FIXME: update XML on the server side */
251 return reginfo->documentation ? S_OK : E_OUTOFMEMORY;
254 static HRESULT WINAPI RegistrationInfo_get_XmlText(IRegistrationInfo *iface, BSTR *xml)
256 FIXME("%p,%p: stub\n", iface, xml);
257 return E_NOTIMPL;
260 static HRESULT WINAPI RegistrationInfo_put_XmlText(IRegistrationInfo *iface, BSTR xml)
262 FIXME("%p,%p: stub\n", iface, debugstr_w(xml));
263 return E_NOTIMPL;
266 static HRESULT WINAPI RegistrationInfo_get_URI(IRegistrationInfo *iface, BSTR *uri)
268 registration_info *reginfo = impl_from_IRegistrationInfo(iface);
270 TRACE("%p,%p\n", iface, uri);
272 if (!uri) return E_POINTER;
274 *uri = SysAllocString(reginfo->uri);
275 return S_OK;
278 static HRESULT WINAPI RegistrationInfo_put_URI(IRegistrationInfo *iface, BSTR uri)
280 registration_info *reginfo = impl_from_IRegistrationInfo(iface);
282 TRACE("%p,%p\n", iface, debugstr_w(uri));
284 if (!uri) return E_INVALIDARG;
286 heap_free(reginfo->uri);
287 reginfo->uri = heap_strdupW(uri);
288 /* FIXME: update XML on the server side */
289 return reginfo->uri ? S_OK : E_OUTOFMEMORY;
292 static HRESULT WINAPI RegistrationInfo_get_SecurityDescriptor(IRegistrationInfo *iface, VARIANT *sddl)
294 FIXME("%p,%p: stub\n", iface, sddl);
295 return E_NOTIMPL;
298 static HRESULT WINAPI RegistrationInfo_put_SecurityDescriptor(IRegistrationInfo *iface, VARIANT sddl)
300 FIXME("%p,%p: stub\n", iface, debugstr_variant(&sddl));
301 return E_NOTIMPL;
304 static HRESULT WINAPI RegistrationInfo_get_Source(IRegistrationInfo *iface, BSTR *source)
306 registration_info *reginfo = impl_from_IRegistrationInfo(iface);
308 TRACE("%p,%p\n", iface, source);
310 if (!source) return E_POINTER;
312 *source = SysAllocString(reginfo->source);
313 return S_OK;
316 static HRESULT WINAPI RegistrationInfo_put_Source(IRegistrationInfo *iface, BSTR source)
318 registration_info *reginfo = impl_from_IRegistrationInfo(iface);
320 TRACE("%p,%p\n", iface, debugstr_w(source));
322 if (!source) return E_INVALIDARG;
324 heap_free(reginfo->source);
325 reginfo->source = heap_strdupW(source);
326 /* FIXME: update XML on the server side */
327 return reginfo->source ? S_OK : E_OUTOFMEMORY;
330 static const IRegistrationInfoVtbl RegistrationInfo_vtbl =
332 RegistrationInfo_QueryInterface,
333 RegistrationInfo_AddRef,
334 RegistrationInfo_Release,
335 RegistrationInfo_GetTypeInfoCount,
336 RegistrationInfo_GetTypeInfo,
337 RegistrationInfo_GetIDsOfNames,
338 RegistrationInfo_Invoke,
339 RegistrationInfo_get_Description,
340 RegistrationInfo_put_Description,
341 RegistrationInfo_get_Author,
342 RegistrationInfo_put_Author,
343 RegistrationInfo_get_Version,
344 RegistrationInfo_put_Version,
345 RegistrationInfo_get_Date,
346 RegistrationInfo_put_Date,
347 RegistrationInfo_get_Documentation,
348 RegistrationInfo_put_Documentation,
349 RegistrationInfo_get_XmlText,
350 RegistrationInfo_put_XmlText,
351 RegistrationInfo_get_URI,
352 RegistrationInfo_put_URI,
353 RegistrationInfo_get_SecurityDescriptor,
354 RegistrationInfo_put_SecurityDescriptor,
355 RegistrationInfo_get_Source,
356 RegistrationInfo_put_Source
359 static HRESULT RegistrationInfo_create(IRegistrationInfo **obj)
361 registration_info *reginfo;
363 reginfo = heap_alloc_zero(sizeof(*reginfo));
364 if (!reginfo) return E_OUTOFMEMORY;
366 reginfo->IRegistrationInfo_iface.lpVtbl = &RegistrationInfo_vtbl;
367 reginfo->ref = 1;
368 *obj = &reginfo->IRegistrationInfo_iface;
370 TRACE("created %p\n", *obj);
372 return S_OK;
375 typedef struct
377 ITaskSettings ITaskSettings_iface;
378 LONG ref;
379 WCHAR *restart_interval;
380 WCHAR *execution_time_limit;
381 WCHAR *delete_expired_task_after;
382 int restart_count;
383 int priority;
384 TASK_INSTANCES_POLICY policy;
385 TASK_COMPATIBILITY compatibility;
386 BOOL allow_on_demand_start;
387 BOOL stop_if_going_on_batteries;
388 BOOL disallow_start_if_on_batteries;
389 BOOL allow_hard_terminate;
390 BOOL start_when_available;
391 BOOL run_only_if_network_available;
392 BOOL enabled;
393 BOOL hidden;
394 BOOL run_only_if_idle;
395 BOOL wake_to_run;
396 } TaskSettings;
398 static inline TaskSettings *impl_from_ITaskSettings(ITaskSettings *iface)
400 return CONTAINING_RECORD(iface, TaskSettings, ITaskSettings_iface);
403 static ULONG WINAPI TaskSettings_AddRef(ITaskSettings *iface)
405 TaskSettings *taskset = impl_from_ITaskSettings(iface);
406 return InterlockedIncrement(&taskset->ref);
409 static ULONG WINAPI TaskSettings_Release(ITaskSettings *iface)
411 TaskSettings *taskset = impl_from_ITaskSettings(iface);
412 LONG ref = InterlockedDecrement(&taskset->ref);
414 if (!ref)
416 TRACE("destroying %p\n", iface);
417 heap_free(taskset->restart_interval);
418 heap_free(taskset->execution_time_limit);
419 heap_free(taskset->delete_expired_task_after);
420 heap_free(taskset);
423 return ref;
426 static HRESULT WINAPI TaskSettings_QueryInterface(ITaskSettings *iface, REFIID riid, void **obj)
428 if (!riid || !obj) return E_INVALIDARG;
430 TRACE("%p,%s,%p\n", iface, debugstr_guid(riid), obj);
432 if (IsEqualGUID(riid, &IID_ITaskSettings) ||
433 IsEqualGUID(riid, &IID_IDispatch) ||
434 IsEqualGUID(riid, &IID_IUnknown))
436 ITaskSettings_AddRef(iface);
437 *obj = iface;
438 return S_OK;
441 FIXME("interface %s is not implemented\n", debugstr_guid(riid));
442 *obj = NULL;
443 return E_NOINTERFACE;
446 static HRESULT WINAPI TaskSettings_GetTypeInfoCount(ITaskSettings *iface, UINT *count)
448 FIXME("%p,%p: stub\n", iface, count);
449 return E_NOTIMPL;
452 static HRESULT WINAPI TaskSettings_GetTypeInfo(ITaskSettings *iface, UINT index, LCID lcid, ITypeInfo **info)
454 FIXME("%p,%u,%u,%p: stub\n", iface, index, lcid, info);
455 return E_NOTIMPL;
458 static HRESULT WINAPI TaskSettings_GetIDsOfNames(ITaskSettings *iface, REFIID riid, LPOLESTR *names,
459 UINT count, LCID lcid, DISPID *dispid)
461 FIXME("%p,%s,%p,%u,%u,%p: stub\n", iface, debugstr_guid(riid), names, count, lcid, dispid);
462 return E_NOTIMPL;
465 static HRESULT WINAPI TaskSettings_Invoke(ITaskSettings *iface, DISPID dispid, REFIID riid, LCID lcid, WORD flags,
466 DISPPARAMS *params, VARIANT *result, EXCEPINFO *excepinfo, UINT *argerr)
468 FIXME("%p,%d,%s,%04x,%04x,%p,%p,%p,%p: stub\n", iface, dispid, debugstr_guid(riid), lcid, flags,
469 params, result, excepinfo, argerr);
470 return E_NOTIMPL;
473 static HRESULT WINAPI TaskSettings_get_AllowDemandStart(ITaskSettings *iface, VARIANT_BOOL *allow)
475 TaskSettings *taskset = impl_from_ITaskSettings(iface);
477 TRACE("%p,%p\n", iface, allow);
479 if (!allow) return E_POINTER;
481 *allow = taskset->allow_on_demand_start ? VARIANT_TRUE : VARIANT_FALSE;
483 return S_OK;
486 static HRESULT WINAPI TaskSettings_put_AllowDemandStart(ITaskSettings *iface, VARIANT_BOOL allow)
488 FIXME("%p,%d: stub\n", iface, allow);
489 return E_NOTIMPL;
492 static HRESULT WINAPI TaskSettings_get_RestartInterval(ITaskSettings *iface, BSTR *interval)
494 TaskSettings *taskset = impl_from_ITaskSettings(iface);
496 TRACE("%p,%p\n", iface, interval);
498 if (!interval) return E_POINTER;
500 if (!taskset->restart_interval)
502 *interval = NULL;
503 return S_OK;
506 *interval = SysAllocString(taskset->restart_interval);
507 if (!*interval) return E_OUTOFMEMORY;
509 return S_OK;
512 static HRESULT WINAPI TaskSettings_put_RestartInterval(ITaskSettings *iface, BSTR interval)
514 TRACE("%p,%s\n", iface, debugstr_w(interval));
515 return E_NOTIMPL;
518 static HRESULT WINAPI TaskSettings_get_RestartCount(ITaskSettings *iface, INT *count)
520 TaskSettings *taskset = impl_from_ITaskSettings(iface);
522 TRACE("%p,%p\n", iface, count);
524 if (!count) return E_POINTER;
526 *count = taskset->restart_count;
528 return S_OK;
531 static HRESULT WINAPI TaskSettings_put_RestartCount(ITaskSettings *iface, INT count)
533 FIXME("%p,%d: stub\n", iface, count);
534 return E_NOTIMPL;
537 static HRESULT WINAPI TaskSettings_get_MultipleInstances(ITaskSettings *iface, TASK_INSTANCES_POLICY *policy)
539 TaskSettings *taskset = impl_from_ITaskSettings(iface);
541 TRACE("%p,%p\n", iface, policy);
543 if (!policy) return E_POINTER;
545 *policy = taskset->policy;
547 return S_OK;
550 static HRESULT WINAPI TaskSettings_put_MultipleInstances(ITaskSettings *iface, TASK_INSTANCES_POLICY policy)
552 FIXME("%p,%d: stub\n", iface, policy);
553 return E_NOTIMPL;
556 static HRESULT WINAPI TaskSettings_get_StopIfGoingOnBatteries(ITaskSettings *iface, VARIANT_BOOL *stop)
558 TaskSettings *taskset = impl_from_ITaskSettings(iface);
560 TRACE("%p,%p\n", iface, stop);
562 if (!stop) return E_POINTER;
564 *stop = taskset->stop_if_going_on_batteries ? VARIANT_TRUE : VARIANT_FALSE;
566 return S_OK;
569 static HRESULT WINAPI TaskSettings_put_StopIfGoingOnBatteries(ITaskSettings *iface, VARIANT_BOOL stop)
571 FIXME("%p,%d: stub\n", iface, stop);
572 return E_NOTIMPL;
575 static HRESULT WINAPI TaskSettings_get_DisallowStartIfOnBatteries(ITaskSettings *iface, VARIANT_BOOL *disallow)
577 TaskSettings *taskset = impl_from_ITaskSettings(iface);
579 TRACE("%p,%p\n", iface, disallow);
581 if (!disallow) return E_POINTER;
583 *disallow = taskset->disallow_start_if_on_batteries ? VARIANT_TRUE : VARIANT_FALSE;
585 return S_OK;
588 static HRESULT WINAPI TaskSettings_put_DisallowStartIfOnBatteries(ITaskSettings *iface, VARIANT_BOOL disallow)
590 FIXME("%p,%d: stub\n", iface, disallow);
591 return E_NOTIMPL;
594 static HRESULT WINAPI TaskSettings_get_AllowHardTerminate(ITaskSettings *iface, VARIANT_BOOL *allow)
596 TaskSettings *taskset = impl_from_ITaskSettings(iface);
598 TRACE("%p,%p\n", iface, allow);
600 if (!allow) return E_POINTER;
602 *allow = taskset->allow_hard_terminate ? VARIANT_TRUE : VARIANT_FALSE;
604 return S_OK;
607 static HRESULT WINAPI TaskSettings_put_AllowHardTerminate(ITaskSettings *iface, VARIANT_BOOL allow)
609 FIXME("%p,%d: stub\n", iface, allow);
610 return E_NOTIMPL;
613 static HRESULT WINAPI TaskSettings_get_StartWhenAvailable(ITaskSettings *iface, VARIANT_BOOL *start)
615 TaskSettings *taskset = impl_from_ITaskSettings(iface);
617 TRACE("%p,%p\n", iface, start);
619 if (!start) return E_POINTER;
621 *start = taskset->start_when_available ? VARIANT_TRUE : VARIANT_FALSE;
623 return S_OK;
626 static HRESULT WINAPI TaskSettings_put_StartWhenAvailable(ITaskSettings *iface, VARIANT_BOOL start)
628 FIXME("%p,%d: stub\n", iface, start);
629 return E_NOTIMPL;
632 static HRESULT WINAPI TaskSettings_get_XmlText(ITaskSettings *iface, BSTR *xml)
634 FIXME("%p,%p: stub\n", iface, xml);
635 return E_NOTIMPL;
638 static HRESULT WINAPI TaskSettings_put_XmlText(ITaskSettings *iface, BSTR xml)
640 FIXME("%p,%s: stub\n", iface, debugstr_w(xml));
641 return E_NOTIMPL;
644 static HRESULT WINAPI TaskSettings_get_RunOnlyIfNetworkAvailable(ITaskSettings *iface, VARIANT_BOOL *run)
646 TaskSettings *taskset = impl_from_ITaskSettings(iface);
648 TRACE("%p,%p\n", iface, run);
650 if (!run) return E_POINTER;
652 *run = taskset->run_only_if_network_available ? VARIANT_TRUE : VARIANT_FALSE;
654 return S_OK;
657 static HRESULT WINAPI TaskSettings_put_RunOnlyIfNetworkAvailable(ITaskSettings *iface, VARIANT_BOOL run)
659 FIXME("%p,%d: stub\n", iface, run);
660 return E_NOTIMPL;
663 static HRESULT WINAPI TaskSettings_get_ExecutionTimeLimit(ITaskSettings *iface, BSTR *limit)
665 TaskSettings *taskset = impl_from_ITaskSettings(iface);
667 TRACE("%p,%p\n", iface, limit);
669 if (!limit) return E_POINTER;
671 if (!taskset->execution_time_limit)
673 *limit = NULL;
674 return S_OK;
677 *limit = SysAllocString(taskset->execution_time_limit);
678 if (!*limit) return E_OUTOFMEMORY;
680 return S_OK;
683 static HRESULT WINAPI TaskSettings_put_ExecutionTimeLimit(ITaskSettings *iface, BSTR limit)
685 TRACE("%p,%s\n", iface, debugstr_w(limit));
686 return E_NOTIMPL;
689 static HRESULT WINAPI TaskSettings_get_Enabled(ITaskSettings *iface, VARIANT_BOOL *enabled)
691 TaskSettings *taskset = impl_from_ITaskSettings(iface);
693 TRACE("%p,%p\n", iface, enabled);
695 if (!enabled) return E_POINTER;
697 *enabled = taskset->enabled ? VARIANT_TRUE : VARIANT_FALSE;
699 return S_OK;
702 static HRESULT WINAPI TaskSettings_put_Enabled(ITaskSettings *iface, VARIANT_BOOL enabled)
704 FIXME("%p,%d: stub\n", iface, enabled);
705 return E_NOTIMPL;
708 static HRESULT WINAPI TaskSettings_get_DeleteExpiredTaskAfter(ITaskSettings *iface, BSTR *delay)
710 TaskSettings *taskset = impl_from_ITaskSettings(iface);
712 TRACE("%p,%p\n", iface, delay);
714 if (!delay) return E_POINTER;
716 if (!taskset->delete_expired_task_after)
718 *delay = NULL;
719 return S_OK;
722 *delay = SysAllocString(taskset->delete_expired_task_after);
723 if (!*delay) return E_OUTOFMEMORY;
725 return S_OK;
728 static HRESULT WINAPI TaskSettings_put_DeleteExpiredTaskAfter(ITaskSettings *iface, BSTR delay)
730 TRACE("%p,%s\n", iface, debugstr_w(delay));
731 return E_NOTIMPL;
734 static HRESULT WINAPI TaskSettings_get_Priority(ITaskSettings *iface, INT *priority)
736 TaskSettings *taskset = impl_from_ITaskSettings(iface);
738 TRACE("%p,%p\n", iface, priority);
740 if (!priority) return E_POINTER;
742 *priority = taskset->priority;
744 return S_OK;
747 static HRESULT WINAPI TaskSettings_put_Priority(ITaskSettings *iface, INT priority)
749 FIXME("%p,%d: stub\n", iface, priority);
750 return E_NOTIMPL;
753 static HRESULT WINAPI TaskSettings_get_Compatibility(ITaskSettings *iface, TASK_COMPATIBILITY *level)
755 TaskSettings *taskset = impl_from_ITaskSettings(iface);
757 TRACE("%p,%p\n", iface, level);
759 if (!level) return E_POINTER;
761 *level = taskset->compatibility;
763 return S_OK;
766 static HRESULT WINAPI TaskSettings_put_Compatibility(ITaskSettings *iface, TASK_COMPATIBILITY level)
768 FIXME("%p,%d: stub\n", iface, level);
769 return E_NOTIMPL;
772 static HRESULT WINAPI TaskSettings_get_Hidden(ITaskSettings *iface, VARIANT_BOOL *hidden)
774 TaskSettings *taskset = impl_from_ITaskSettings(iface);
776 TRACE("%p,%p\n", iface, hidden);
778 if (!hidden) return E_POINTER;
780 *hidden = taskset->hidden ? VARIANT_TRUE : VARIANT_FALSE;
782 return S_OK;
785 static HRESULT WINAPI TaskSettings_put_Hidden(ITaskSettings *iface, VARIANT_BOOL hidden)
787 FIXME("%p,%d: stub\n", iface, hidden);
788 return E_NOTIMPL;
791 static HRESULT WINAPI TaskSettings_get_IdleSettings(ITaskSettings *iface, IIdleSettings **settings)
793 FIXME("%p,%p: stub\n", iface, settings);
794 return E_NOTIMPL;
797 static HRESULT WINAPI TaskSettings_put_IdleSettings(ITaskSettings *iface, IIdleSettings *settings)
799 FIXME("%p,%p: stub\n", iface, settings);
800 return E_NOTIMPL;
803 static HRESULT WINAPI TaskSettings_get_RunOnlyIfIdle(ITaskSettings *iface, VARIANT_BOOL *run)
805 TaskSettings *taskset = impl_from_ITaskSettings(iface);
807 TRACE("%p,%p\n", iface, run);
809 if (!run) return E_POINTER;
811 *run = taskset->run_only_if_idle ? VARIANT_TRUE : VARIANT_FALSE;
813 return S_OK;
816 static HRESULT WINAPI TaskSettings_put_RunOnlyIfIdle(ITaskSettings *iface, VARIANT_BOOL run)
818 FIXME("%p,%d: stub\n", iface, run);
819 return E_NOTIMPL;
822 static HRESULT WINAPI TaskSettings_get_WakeToRun(ITaskSettings *iface, VARIANT_BOOL *wake)
824 TaskSettings *taskset = impl_from_ITaskSettings(iface);
826 TRACE("%p,%p\n", iface, wake);
828 if (!wake) return E_POINTER;
830 *wake = taskset->wake_to_run ? VARIANT_TRUE : VARIANT_FALSE;
832 return S_OK;
835 static HRESULT WINAPI TaskSettings_put_WakeToRun(ITaskSettings *iface, VARIANT_BOOL wake)
837 FIXME("%p,%d: stub\n", iface, wake);
838 return E_NOTIMPL;
841 static HRESULT WINAPI TaskSettings_get_NetworkSettings(ITaskSettings *iface, INetworkSettings **settings)
843 FIXME("%p,%p: stub\n", iface, settings);
844 return E_NOTIMPL;
847 static HRESULT WINAPI TaskSettings_put_NetworkSettings(ITaskSettings *iface, INetworkSettings *settings)
849 FIXME("%p,%p: stub\n", iface, settings);
850 return E_NOTIMPL;
853 static const ITaskSettingsVtbl TaskSettings_vtbl =
855 TaskSettings_QueryInterface,
856 TaskSettings_AddRef,
857 TaskSettings_Release,
858 TaskSettings_GetTypeInfoCount,
859 TaskSettings_GetTypeInfo,
860 TaskSettings_GetIDsOfNames,
861 TaskSettings_Invoke,
862 TaskSettings_get_AllowDemandStart,
863 TaskSettings_put_AllowDemandStart,
864 TaskSettings_get_RestartInterval,
865 TaskSettings_put_RestartInterval,
866 TaskSettings_get_RestartCount,
867 TaskSettings_put_RestartCount,
868 TaskSettings_get_MultipleInstances,
869 TaskSettings_put_MultipleInstances,
870 TaskSettings_get_StopIfGoingOnBatteries,
871 TaskSettings_put_StopIfGoingOnBatteries,
872 TaskSettings_get_DisallowStartIfOnBatteries,
873 TaskSettings_put_DisallowStartIfOnBatteries,
874 TaskSettings_get_AllowHardTerminate,
875 TaskSettings_put_AllowHardTerminate,
876 TaskSettings_get_StartWhenAvailable,
877 TaskSettings_put_StartWhenAvailable,
878 TaskSettings_get_XmlText,
879 TaskSettings_put_XmlText,
880 TaskSettings_get_RunOnlyIfNetworkAvailable,
881 TaskSettings_put_RunOnlyIfNetworkAvailable,
882 TaskSettings_get_ExecutionTimeLimit,
883 TaskSettings_put_ExecutionTimeLimit,
884 TaskSettings_get_Enabled,
885 TaskSettings_put_Enabled,
886 TaskSettings_get_DeleteExpiredTaskAfter,
887 TaskSettings_put_DeleteExpiredTaskAfter,
888 TaskSettings_get_Priority,
889 TaskSettings_put_Priority,
890 TaskSettings_get_Compatibility,
891 TaskSettings_put_Compatibility,
892 TaskSettings_get_Hidden,
893 TaskSettings_put_Hidden,
894 TaskSettings_get_IdleSettings,
895 TaskSettings_put_IdleSettings,
896 TaskSettings_get_RunOnlyIfIdle,
897 TaskSettings_put_RunOnlyIfIdle,
898 TaskSettings_get_WakeToRun,
899 TaskSettings_put_WakeToRun,
900 TaskSettings_get_NetworkSettings,
901 TaskSettings_put_NetworkSettings
904 static HRESULT TaskSettings_create(ITaskSettings **obj)
906 static const WCHAR exec_time_limit[] = { 'P','T','7','2','H',0 };
907 TaskSettings *taskset;
909 taskset = heap_alloc(sizeof(*taskset));
910 if (!taskset) return E_OUTOFMEMORY;
912 taskset->ITaskSettings_iface.lpVtbl = &TaskSettings_vtbl;
913 taskset->ref = 1;
914 /* set the defaults */
915 taskset->restart_interval = NULL;
916 taskset->execution_time_limit = heap_strdupW(exec_time_limit);
917 taskset->delete_expired_task_after = NULL;
918 taskset->restart_count = 0;
919 taskset->priority = 7;
920 taskset->policy = TASK_INSTANCES_IGNORE_NEW;
921 taskset->compatibility = TASK_COMPATIBILITY_V2;
922 taskset->allow_on_demand_start = TRUE;
923 taskset->stop_if_going_on_batteries = TRUE;
924 taskset->disallow_start_if_on_batteries = TRUE;
925 taskset->allow_hard_terminate = TRUE;
926 taskset->start_when_available = FALSE;
927 taskset->run_only_if_network_available = FALSE;
928 taskset->enabled = TRUE;
929 taskset->hidden = FALSE;
930 taskset->run_only_if_idle = FALSE;
931 taskset->wake_to_run = FALSE;
933 *obj = &taskset->ITaskSettings_iface;
935 TRACE("created %p\n", *obj);
937 return S_OK;
940 typedef struct
942 ITaskDefinition ITaskDefinition_iface;
943 LONG ref;
944 IRegistrationInfo *reginfo;
945 ITaskSettings *taskset;
946 ITriggerCollection *triggers;
947 IPrincipal *principal;
948 IActionCollection *actions;
949 } TaskDefinition;
951 static inline TaskDefinition *impl_from_ITaskDefinition(ITaskDefinition *iface)
953 return CONTAINING_RECORD(iface, TaskDefinition, ITaskDefinition_iface);
956 static ULONG WINAPI TaskDefinition_AddRef(ITaskDefinition *iface)
958 TaskDefinition *taskdef = impl_from_ITaskDefinition(iface);
959 return InterlockedIncrement(&taskdef->ref);
962 static ULONG WINAPI TaskDefinition_Release(ITaskDefinition *iface)
964 TaskDefinition *taskdef = impl_from_ITaskDefinition(iface);
965 LONG ref = InterlockedDecrement(&taskdef->ref);
967 if (!ref)
969 TRACE("destroying %p\n", iface);
971 if (taskdef->reginfo)
972 IRegistrationInfo_Release(taskdef->reginfo);
973 if (taskdef->taskset)
974 ITaskSettings_Release(taskdef->taskset);
975 if (taskdef->triggers)
976 ITriggerCollection_Release(taskdef->triggers);
977 if (taskdef->principal)
978 IPrincipal_Release(taskdef->principal);
979 if (taskdef->actions)
980 IActionCollection_Release(taskdef->actions);
982 heap_free(taskdef);
985 return ref;
988 static HRESULT WINAPI TaskDefinition_QueryInterface(ITaskDefinition *iface, REFIID riid, void **obj)
990 if (!riid || !obj) return E_INVALIDARG;
992 TRACE("%p,%s,%p\n", iface, debugstr_guid(riid), obj);
994 if (IsEqualGUID(riid, &IID_ITaskDefinition) ||
995 IsEqualGUID(riid, &IID_IDispatch) ||
996 IsEqualGUID(riid, &IID_IUnknown))
998 ITaskDefinition_AddRef(iface);
999 *obj = iface;
1000 return S_OK;
1003 FIXME("interface %s is not implemented\n", debugstr_guid(riid));
1004 *obj = NULL;
1005 return E_NOINTERFACE;
1008 static HRESULT WINAPI TaskDefinition_GetTypeInfoCount(ITaskDefinition *iface, UINT *count)
1010 FIXME("%p,%p: stub\n", iface, count);
1011 return E_NOTIMPL;
1014 static HRESULT WINAPI TaskDefinition_GetTypeInfo(ITaskDefinition *iface, UINT index, LCID lcid, ITypeInfo **info)
1016 FIXME("%p,%u,%u,%p: stub\n", iface, index, lcid, info);
1017 return E_NOTIMPL;
1020 static HRESULT WINAPI TaskDefinition_GetIDsOfNames(ITaskDefinition *iface, REFIID riid, LPOLESTR *names,
1021 UINT count, LCID lcid, DISPID *dispid)
1023 FIXME("%p,%s,%p,%u,%u,%p: stub\n", iface, debugstr_guid(riid), names, count, lcid, dispid);
1024 return E_NOTIMPL;
1027 static HRESULT WINAPI TaskDefinition_Invoke(ITaskDefinition *iface, DISPID dispid, REFIID riid, LCID lcid, WORD flags,
1028 DISPPARAMS *params, VARIANT *result, EXCEPINFO *excepinfo, UINT *argerr)
1030 FIXME("%p,%d,%s,%04x,%04x,%p,%p,%p,%p: stub\n", iface, dispid, debugstr_guid(riid), lcid, flags,
1031 params, result, excepinfo, argerr);
1032 return E_NOTIMPL;
1035 static HRESULT WINAPI TaskDefinition_get_RegistrationInfo(ITaskDefinition *iface, IRegistrationInfo **info)
1037 TaskDefinition *taskdef = impl_from_ITaskDefinition(iface);
1038 HRESULT hr;
1040 TRACE("%p,%p\n", iface, info);
1042 if (!info) return E_POINTER;
1044 if (!taskdef->reginfo)
1046 hr = RegistrationInfo_create(&taskdef->reginfo);
1047 if (hr != S_OK) return hr;
1050 IRegistrationInfo_AddRef(taskdef->reginfo);
1051 *info = taskdef->reginfo;
1053 return S_OK;
1056 static HRESULT WINAPI TaskDefinition_put_RegistrationInfo(ITaskDefinition *iface, IRegistrationInfo *info)
1058 TaskDefinition *taskdef = impl_from_ITaskDefinition(iface);
1060 TRACE("%p,%p\n", iface, info);
1062 if (!info) return E_POINTER;
1064 if (taskdef->reginfo)
1065 IRegistrationInfo_Release(taskdef->reginfo);
1067 IRegistrationInfo_AddRef(info);
1068 taskdef->reginfo = info;
1070 return S_OK;
1073 static HRESULT WINAPI TaskDefinition_get_Triggers(ITaskDefinition *iface, ITriggerCollection **triggers)
1075 FIXME("%p,%p: stub\n", iface, triggers);
1076 return E_NOTIMPL;
1079 static HRESULT WINAPI TaskDefinition_put_Triggers(ITaskDefinition *iface, ITriggerCollection *triggers)
1081 FIXME("%p,%p: stub\n", iface, triggers);
1082 return E_NOTIMPL;
1085 static HRESULT WINAPI TaskDefinition_get_Settings(ITaskDefinition *iface, ITaskSettings **settings)
1087 TaskDefinition *taskdef = impl_from_ITaskDefinition(iface);
1088 HRESULT hr;
1090 TRACE("%p,%p\n", iface, settings);
1092 if (!settings) return E_POINTER;
1094 if (!taskdef->taskset)
1096 hr = TaskSettings_create(&taskdef->taskset);
1097 if (hr != S_OK) return hr;
1100 ITaskSettings_AddRef(taskdef->taskset);
1101 *settings = taskdef->taskset;
1103 return S_OK;
1106 static HRESULT WINAPI TaskDefinition_put_Settings(ITaskDefinition *iface, ITaskSettings *settings)
1108 TaskDefinition *taskdef = impl_from_ITaskDefinition(iface);
1110 TRACE("%p,%p\n", iface, settings);
1112 if (!settings) return E_POINTER;
1114 if (taskdef->taskset)
1115 ITaskSettings_Release(taskdef->taskset);
1117 ITaskSettings_AddRef(settings);
1118 taskdef->taskset = settings;
1120 return S_OK;
1123 static HRESULT WINAPI TaskDefinition_get_Data(ITaskDefinition *iface, BSTR *data)
1125 FIXME("%p,%p: stub\n", iface, data);
1126 return E_NOTIMPL;
1129 static HRESULT WINAPI TaskDefinition_put_Data(ITaskDefinition *iface, BSTR data)
1131 FIXME("%p,%p: stub\n", iface, data);
1132 return E_NOTIMPL;
1135 static HRESULT WINAPI TaskDefinition_get_Principal(ITaskDefinition *iface, IPrincipal **principal)
1137 FIXME("%p,%p: stub\n", iface, principal);
1138 return E_NOTIMPL;
1141 static HRESULT WINAPI TaskDefinition_put_Principal(ITaskDefinition *iface, IPrincipal *principal)
1143 FIXME("%p,%p: stub\n", iface, principal);
1144 return E_NOTIMPL;
1147 static HRESULT WINAPI TaskDefinition_get_Actions(ITaskDefinition *iface, IActionCollection **actions)
1149 FIXME("%p,%p: stub\n", iface, actions);
1150 return E_NOTIMPL;
1153 static HRESULT WINAPI TaskDefinition_put_Actions(ITaskDefinition *iface, IActionCollection *actions)
1155 FIXME("%p,%p: stub\n", iface, actions);
1156 return E_NOTIMPL;
1159 static const WCHAR Task[] = {'T','a','s','k',0};
1160 static const WCHAR version[] = {'v','e','r','s','i','o','n',0};
1161 static const WCHAR v1_0[] = {'1','.','0',0};
1162 static const WCHAR v1_1[] = {'1','.','1',0};
1163 static const WCHAR v1_2[] = {'1','.','2',0};
1164 static const WCHAR v1_3[] = {'1','.','3',0};
1165 static const WCHAR xmlns[] = {'x','m','l','n','s',0};
1166 static const WCHAR task_ns[] = {'h','t','t','p',':','/','/','s','c','h','e','m','a','s','.','m','i','c','r','o','s','o','f','t','.','c','o','m','/','w','i','n','d','o','w','s','/','2','0','0','4','/','0','2','/','m','i','t','/','t','a','s','k',0};
1167 static const WCHAR RegistrationInfo[] = {'R','e','g','i','s','t','r','a','t','i','o','n','I','n','f','o',0};
1168 static const WCHAR Author[] = {'A','u','t','h','o','r',0};
1169 static const WCHAR Description[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
1170 static const WCHAR Source[] = {'S','o','u','r','c','e',0};
1171 static const WCHAR Date[] = {'D','a','t','e',0};
1172 static const WCHAR Version[] = {'V','e','r','s','i','o','n',0};
1173 static const WCHAR Documentation[] = {'D','o','c','u','m','e','n','t','a','t','i','o','n',0};
1174 static const WCHAR URI[] = {'U','R','I',0};
1175 static const WCHAR SecurityDescriptor[] = {'S','e','c','u','r','i','t','y','D','e','s','c','r','i','p','t','o','r',0};
1176 static const WCHAR Settings[] = {'S','e','t','t','i','n','g','s',0};
1177 static const WCHAR Triggers[] = {'T','r','i','g','g','e','r','s',0};
1178 static const WCHAR Principals[] = {'P','r','i','n','c','i','p','a','l','s',0};
1179 static const WCHAR Principal[] = {'P','r','i','n','c','i','p','a','l',0};
1180 static const WCHAR id[] = {'i','d',0};
1181 static const WCHAR UserId[] = {'U','s','e','r','I','d',0};
1182 static const WCHAR LogonType[] = {'L','o','g','o','n','T','y','p','e',0};
1183 static const WCHAR GroupId[] = {'G','r','o','u','p','I','d',0};
1184 static const WCHAR DisplayName[] = {'D','i','s','p','l','a','y','N','a','m','e',0};
1185 static const WCHAR HighestAvailable[] = {'H','i','g','h','e','s','t','A','v','a','i','l','a','b','l','e',0};
1186 static const WCHAR Password[] = {'P','a','s','s','w','o','r','d',0};
1187 static const WCHAR S4U[] = {'S','4','U',0};
1188 static const WCHAR InteractiveToken[] = {'I','n','t','e','r','a','c','t','i','v','e','T','o','k','e','n',0};
1189 static const WCHAR RunLevel[] = {'R','u','n','L','e','v','e','l',0};
1190 static const WCHAR LeastPrivilege[] = {'L','e','a','s','t','P','r','i','v','i','l','e','g','e',0};
1191 static const WCHAR Actions[] = {'A','c','t','i','o','n','s',0};
1192 static const WCHAR Exec[] = {'E','x','e','c',0};
1193 static const WCHAR MultipleInstancesPolicy[] = {'M','u','l','t','i','p','l','e','I','n','s','t','a','n','c','e','s','P','o','l','i','c','y',0};
1194 static const WCHAR IgnoreNew[] = {'I','g','n','o','r','e','N','e','w',0};
1195 static const WCHAR DisallowStartIfOnBatteries[] = {'D','i','s','a','l','l','o','w','S','t','a','r','t','I','f','O','n','B','a','t','t','e','r','i','e','s',0};
1196 static const WCHAR AllowStartOnDemand[] = {'A','l','l','o','w','S','t','a','r','t','O','n','D','e','m','a','n','d',0};
1197 static const WCHAR StopIfGoingOnBatteries[] = {'S','t','o','p','I','f','G','o','i','n','g','O','n','B','a','t','t','e','r','i','e','s',0};
1198 static const WCHAR AllowHardTerminate[] = {'A','l','l','o','w','H','a','r','d','T','e','r','m','i','n','a','t','e',0};
1199 static const WCHAR StartWhenAvailable[] = {'S','t','a','r','t','W','h','e','n','A','v','a','i','l','a','b','l','e',0};
1200 static const WCHAR RunOnlyIfNetworkAvailable[] = {'R','u','n','O','n','l','y','I','f','N','e','t','w','o','r','k','A','v','a','i','l','a','b','l','e',0};
1201 static const WCHAR Enabled[] = {'E','n','a','b','l','e','d',0};
1202 static const WCHAR Hidden[] = {'H','i','d','d','e','n',0};
1203 static const WCHAR RunOnlyIfIdle[] = {'R','u','n','O','n','l','y','I','f','I','d','l','e',0};
1204 static const WCHAR WakeToRun[] = {'W','a','k','e','T','o','R','u','n',0};
1205 static const WCHAR ExecutionTimeLimit[] = {'E','x','e','c','u','t','i','o','n','T','i','m','e','L','i','m','i','t',0};
1206 static const WCHAR Priority[] = {'P','r','i','o','r','i','t','y',0};
1207 static const WCHAR IdleSettings[] = {'I','d','l','e','S','e','t','t','i','n','g','s',0};
1209 static int xml_indent;
1211 static inline void push_indent(void)
1213 xml_indent += 2;
1216 static inline void pop_indent(void)
1218 xml_indent -= 2;
1221 static inline HRESULT write_stringW(IStream *stream, const WCHAR *str)
1223 return IStream_Write(stream, str, lstrlenW(str) * sizeof(WCHAR), NULL);
1226 static void write_indent(IStream *stream)
1228 static const WCHAR spacesW[] = {' ',' ',0};
1229 int i;
1230 for (i = 0; i < xml_indent; i += 2)
1231 write_stringW(stream, spacesW);
1234 static const WCHAR start_element[] = {'<',0};
1235 static const WCHAR start_end_element[] = {'<','/',0};
1236 static const WCHAR close_element[] = {'>',0};
1237 static const WCHAR end_empty_element[] = {'/','>',0};
1238 static const WCHAR eol[] = {'\n',0};
1239 static const WCHAR spaceW[] = {' ',0};
1240 static const WCHAR equalW[] = {'=',0};
1241 static const WCHAR quoteW[] = {'"',0};
1243 static inline HRESULT write_empty_element(IStream *stream, const WCHAR *name)
1245 write_indent(stream);
1246 write_stringW(stream, start_element);
1247 write_stringW(stream, name);
1248 write_stringW(stream, end_empty_element);
1249 return write_stringW(stream, eol);
1252 static inline HRESULT write_element(IStream *stream, const WCHAR *name)
1254 write_indent(stream);
1255 write_stringW(stream, start_element);
1256 write_stringW(stream, name);
1257 write_stringW(stream, close_element);
1258 return write_stringW(stream, eol);
1261 static inline HRESULT write_element_end(IStream *stream, const WCHAR *name)
1263 write_indent(stream);
1264 write_stringW(stream, start_end_element);
1265 write_stringW(stream, name);
1266 write_stringW(stream, close_element);
1267 return write_stringW(stream, eol);
1270 static inline HRESULT write_text_value(IStream *stream, const WCHAR *name, const WCHAR *value)
1272 write_indent(stream);
1273 write_stringW(stream, start_element);
1274 write_stringW(stream, name);
1275 write_stringW(stream, close_element);
1276 write_stringW(stream, value);
1277 write_stringW(stream, start_end_element);
1278 write_stringW(stream, name);
1279 write_stringW(stream, close_element);
1280 return write_stringW(stream, eol);
1283 static HRESULT write_task_attributes(IStream *stream, ITaskDefinition *taskdef)
1285 HRESULT hr;
1286 ITaskSettings *taskset;
1287 TASK_COMPATIBILITY level;
1288 const WCHAR *compatibility;
1290 hr = ITaskDefinition_get_Settings(taskdef, &taskset);
1291 if (hr != S_OK) return hr;
1293 hr = ITaskSettings_get_Compatibility(taskset, &level);
1294 if (hr != S_OK) level = TASK_COMPATIBILITY_V2_1;
1296 ITaskSettings_Release(taskset);
1298 switch (level)
1300 case TASK_COMPATIBILITY_AT:
1301 compatibility = v1_0;
1302 break;
1303 case TASK_COMPATIBILITY_V1:
1304 compatibility = v1_1;
1305 break;
1306 case TASK_COMPATIBILITY_V2:
1307 compatibility = v1_2;
1308 break;
1309 default:
1310 compatibility = v1_3;
1311 break;
1314 write_stringW(stream, start_element);
1315 write_stringW(stream, Task);
1316 write_stringW(stream, spaceW);
1317 write_stringW(stream, version);
1318 write_stringW(stream, equalW);
1319 write_stringW(stream, quoteW);
1320 write_stringW(stream, compatibility);
1321 write_stringW(stream, quoteW);
1322 write_stringW(stream, spaceW);
1323 write_stringW(stream, xmlns);
1324 write_stringW(stream, equalW);
1325 write_stringW(stream, quoteW);
1326 write_stringW(stream, task_ns);
1327 write_stringW(stream, quoteW);
1328 write_stringW(stream, close_element);
1329 return write_stringW(stream, eol);
1332 static HRESULT write_registration_info(IStream *stream, IRegistrationInfo *reginfo)
1334 HRESULT hr;
1335 BSTR bstr;
1336 VARIANT var;
1338 if (!reginfo)
1339 return write_empty_element(stream, RegistrationInfo);
1341 hr = write_element(stream, RegistrationInfo);
1342 if (hr != S_OK) return hr;
1344 push_indent();
1346 hr = IRegistrationInfo_get_Source(reginfo, &bstr);
1347 if (hr == S_OK && bstr)
1349 hr = write_text_value(stream, Source, bstr);
1350 SysFreeString(bstr);
1351 if (hr != S_OK) return hr;
1353 hr = IRegistrationInfo_get_Date(reginfo, &bstr);
1354 if (hr == S_OK && bstr)
1356 hr = write_text_value(stream, Date, bstr);
1357 SysFreeString(bstr);
1358 if (hr != S_OK) return hr;
1360 hr = IRegistrationInfo_get_Author(reginfo, &bstr);
1361 if (hr == S_OK && bstr)
1363 hr = write_text_value(stream, Author, bstr);
1364 SysFreeString(bstr);
1365 if (hr != S_OK) return hr;
1367 hr = IRegistrationInfo_get_Version(reginfo, &bstr);
1368 if (hr == S_OK && bstr)
1370 hr = write_text_value(stream, Version, bstr);
1371 SysFreeString(bstr);
1372 if (hr != S_OK) return hr;
1374 hr = IRegistrationInfo_get_Description(reginfo, &bstr);
1375 if (hr == S_OK && bstr)
1377 hr = write_text_value(stream, Description, bstr);
1378 SysFreeString(bstr);
1379 if (hr != S_OK) return hr;
1381 hr = IRegistrationInfo_get_Documentation(reginfo, &bstr);
1382 if (hr == S_OK && bstr)
1384 hr = write_text_value(stream, Documentation, bstr);
1385 SysFreeString(bstr);
1386 if (hr != S_OK) return hr;
1388 hr = IRegistrationInfo_get_URI(reginfo, &bstr);
1389 if (hr == S_OK && bstr)
1391 hr = write_text_value(stream, URI, bstr);
1392 SysFreeString(bstr);
1393 if (hr != S_OK) return hr;
1395 hr = IRegistrationInfo_get_SecurityDescriptor(reginfo, &var);
1396 if (hr == S_OK)
1398 if (V_VT(&var) == VT_BSTR)
1400 hr = write_text_value(stream, SecurityDescriptor, V_BSTR(&var));
1401 VariantClear(&var);
1402 if (hr != S_OK) return hr;
1404 else
1405 FIXME("SecurityInfo variant type %d is not supported\n", V_VT(&var));
1408 pop_indent();
1410 return write_element_end(stream, RegistrationInfo);
1413 static HRESULT write_principal(IStream *stream, IPrincipal *principal)
1415 HRESULT hr;
1416 BSTR bstr;
1417 TASK_LOGON_TYPE logon;
1418 TASK_RUNLEVEL_TYPE level;
1420 if (!principal)
1421 return write_empty_element(stream, Principals);
1423 hr = write_element(stream, Principals);
1424 if (hr != S_OK) return hr;
1426 push_indent();
1428 hr = IPrincipal_get_Id(principal, &bstr);
1429 if (hr == S_OK)
1431 write_indent(stream);
1432 write_stringW(stream, start_element);
1433 write_stringW(stream, Principal);
1434 write_stringW(stream, spaceW);
1435 write_stringW(stream, id);
1436 write_stringW(stream, equalW);
1437 write_stringW(stream, quoteW);
1438 write_stringW(stream, bstr);
1439 write_stringW(stream, quoteW);
1440 write_stringW(stream, close_element);
1441 write_stringW(stream, eol);
1442 SysFreeString(bstr);
1444 else
1445 write_element(stream, Principal);
1447 push_indent();
1449 hr = IPrincipal_get_GroupId(principal, &bstr);
1450 if (hr == S_OK)
1452 hr = write_text_value(stream, GroupId, bstr);
1453 SysFreeString(bstr);
1454 if (hr != S_OK) return hr;
1456 hr = IPrincipal_get_DisplayName(principal, &bstr);
1457 if (hr == S_OK)
1459 hr = write_text_value(stream, DisplayName, bstr);
1460 SysFreeString(bstr);
1461 if (hr != S_OK) return hr;
1463 hr = IPrincipal_get_UserId(principal, &bstr);
1464 if (hr == S_OK && lstrlenW(bstr))
1466 hr = write_text_value(stream, UserId, bstr);
1467 SysFreeString(bstr);
1468 if (hr != S_OK) return hr;
1470 hr = IPrincipal_get_RunLevel(principal, &level);
1471 if (hr == S_OK)
1473 const WCHAR *level_str = NULL;
1475 switch (level)
1477 case TASK_RUNLEVEL_HIGHEST:
1478 level_str = HighestAvailable;
1479 break;
1480 case TASK_RUNLEVEL_LUA:
1481 level_str = LeastPrivilege;
1482 break;
1483 default:
1484 FIXME("Principal run level %d\n", level);
1485 break;
1488 if (level_str)
1490 hr = write_text_value(stream, RunLevel, level_str);
1491 if (hr != S_OK) return hr;
1494 hr = IPrincipal_get_LogonType(principal, &logon);
1495 if (hr == S_OK)
1497 const WCHAR *logon_str = NULL;
1499 switch (logon)
1501 case TASK_LOGON_PASSWORD:
1502 logon_str = Password;
1503 break;
1504 case TASK_LOGON_S4U:
1505 logon_str = S4U;
1506 break;
1507 case TASK_LOGON_INTERACTIVE_TOKEN:
1508 logon_str = InteractiveToken;
1509 break;
1510 default:
1511 FIXME("Principal logon type %d\n", logon);
1512 break;
1515 if (logon_str)
1517 hr = write_text_value(stream, LogonType, logon_str);
1518 if (hr != S_OK) return hr;
1522 pop_indent();
1523 write_element_end(stream, Principal);
1525 pop_indent();
1526 return write_element_end(stream, Principals);
1529 static HRESULT write_settings(IStream *stream, ITaskSettings *settings)
1531 if (!settings)
1532 return write_empty_element(stream, Settings);
1534 FIXME("stub\n");
1535 return S_OK;
1538 static HRESULT write_triggers(IStream *stream, ITriggerCollection *triggers)
1540 if (!triggers)
1541 return write_empty_element(stream, Triggers);
1543 FIXME("stub\n");
1544 return S_OK;
1547 static HRESULT write_actions(IStream *stream, IActionCollection *actions)
1549 if (!actions)
1551 write_element(stream, Actions);
1552 push_indent();
1553 write_empty_element(stream, Exec);
1554 pop_indent();
1555 return write_element_end(stream, Actions);
1558 FIXME("stub\n");
1559 return S_OK;
1562 static HRESULT WINAPI TaskDefinition_get_XmlText(ITaskDefinition *iface, BSTR *xml)
1564 TaskDefinition *taskdef = impl_from_ITaskDefinition(iface);
1565 HRESULT hr;
1566 IStream *stream;
1567 HGLOBAL hmem;
1568 void *p;
1570 TRACE("%p,%p\n", iface, xml);
1572 hmem = GlobalAlloc(GMEM_MOVEABLE | GMEM_NODISCARD, 16);
1573 if (!hmem) return E_OUTOFMEMORY;
1575 hr = CreateStreamOnHGlobal(hmem, TRUE, &stream);
1576 if (hr != S_OK)
1578 GlobalFree(hmem);
1579 return hr;
1582 hr = write_task_attributes(stream, &taskdef->ITaskDefinition_iface);
1583 if (hr != S_OK) goto failed;
1585 push_indent();
1587 hr = write_registration_info(stream, taskdef->reginfo);
1588 if (hr != S_OK) goto failed;
1590 hr = write_triggers(stream, taskdef->triggers);
1591 if (hr != S_OK) goto failed;
1593 hr = write_principal(stream, taskdef->principal);
1594 if (hr != S_OK) goto failed;
1596 hr = write_settings(stream, taskdef->taskset);
1597 if (hr != S_OK) goto failed;
1599 hr = write_actions(stream, taskdef->actions);
1600 if (hr != S_OK) goto failed;
1602 pop_indent();
1604 write_element_end(stream, Task);
1605 IStream_Write(stream, "\0\0", 2, NULL);
1607 p = GlobalLock(hmem);
1608 *xml = SysAllocString(p);
1609 GlobalUnlock(hmem);
1611 IStream_Release(stream);
1613 return *xml ? S_OK : E_OUTOFMEMORY;
1615 failed:
1616 IStream_Release(stream);
1617 return hr;
1620 static HRESULT read_text_value(IXmlReader *reader, WCHAR **value)
1622 HRESULT hr;
1623 XmlNodeType type;
1625 while (IXmlReader_Read(reader, &type) == S_OK)
1627 switch (type)
1629 case XmlNodeType_Text:
1630 hr = IXmlReader_GetValue(reader, (const WCHAR **)value, NULL);
1631 if (hr != S_OK) return hr;
1632 TRACE("%s\n", debugstr_w(*value));
1633 return S_OK;
1635 case XmlNodeType_Whitespace:
1636 case XmlNodeType_Comment:
1637 break;
1639 default:
1640 FIXME("unexpected node type %d\n", type);
1641 return E_FAIL;
1645 return E_FAIL;
1648 static HRESULT read_variantbool_value(IXmlReader *reader, VARIANT_BOOL *vbool)
1650 static const WCHAR trueW[] = {'t','r','u','e',0};
1651 static const WCHAR falseW[] = {'f','a','l','s','e',0};
1652 HRESULT hr;
1653 WCHAR *value;
1655 hr = read_text_value(reader, &value);
1656 if (hr != S_OK) return hr;
1658 if (!lstrcmpW(value, trueW))
1659 *vbool = VARIANT_TRUE;
1660 else if (!lstrcmpW(value, falseW))
1661 *vbool = VARIANT_FALSE;
1662 else
1664 WARN("unexpected bool value %s\n", debugstr_w(value));
1665 return SCHED_E_INVALIDVALUE;
1668 return S_OK;
1671 static HRESULT read_int_value(IXmlReader *reader, int *int_val)
1673 HRESULT hr;
1674 WCHAR *value;
1676 hr = read_text_value(reader, &value);
1677 if (hr != S_OK) return hr;
1679 *int_val = strtolW(value, NULL, 10);
1681 return S_OK;
1684 static HRESULT read_triggers(IXmlReader *reader, ITaskDefinition *taskdef)
1686 FIXME("stub\n");
1687 return S_OK;
1690 static HRESULT read_principal_attributes(IXmlReader *reader, IPrincipal *principal)
1692 HRESULT hr;
1693 const WCHAR *name;
1694 const WCHAR *value;
1696 hr = IXmlReader_MoveToFirstAttribute(reader);
1698 while (hr == S_OK)
1700 hr = IXmlReader_GetLocalName(reader, &name, NULL);
1701 if (hr != S_OK) break;
1703 hr = IXmlReader_GetValue(reader, &value, NULL);
1704 if (hr != S_OK) break;
1706 TRACE("%s=%s\n", debugstr_w(name), debugstr_w(value));
1708 if (!lstrcmpW(name, id))
1709 IPrincipal_put_Id(principal, (BSTR)value);
1710 else
1711 FIXME("unhandled Principal attribute %s\n", debugstr_w(name));
1713 hr = IXmlReader_MoveToNextAttribute(reader);
1716 return S_OK;
1719 static HRESULT read_principal(IXmlReader *reader, IPrincipal *principal)
1721 HRESULT hr;
1722 XmlNodeType type;
1723 const WCHAR *name;
1724 WCHAR *value;
1726 if (IXmlReader_IsEmptyElement(reader))
1728 TRACE("Principal is empty\n");
1729 return S_OK;
1732 read_principal_attributes(reader, principal);
1734 while (IXmlReader_Read(reader, &type) == S_OK)
1736 switch (type)
1738 case XmlNodeType_EndElement:
1739 hr = IXmlReader_GetLocalName(reader, &name, NULL);
1740 if (hr != S_OK) return hr;
1742 TRACE("/%s\n", debugstr_w(name));
1744 if (!lstrcmpW(name, Principal))
1745 return S_OK;
1747 break;
1749 case XmlNodeType_Element:
1750 hr = IXmlReader_GetLocalName(reader, &name, NULL);
1751 if (hr != S_OK) return hr;
1753 TRACE("Element: %s\n", debugstr_w(name));
1755 if (!lstrcmpW(name, UserId))
1757 hr = read_text_value(reader, &value);
1758 if (hr == S_OK)
1759 IPrincipal_put_UserId(principal, value);
1761 else if (!lstrcmpW(name, LogonType))
1763 hr = read_text_value(reader, &value);
1764 if (hr == S_OK)
1766 TASK_LOGON_TYPE logon = TASK_LOGON_NONE;
1768 if (!lstrcmpW(value, InteractiveToken))
1769 logon = TASK_LOGON_INTERACTIVE_TOKEN;
1770 else
1771 FIXME("unhandled LogonType %s\n", debugstr_w(value));
1773 IPrincipal_put_LogonType(principal, logon);
1776 else if (!lstrcmpW(name, RunLevel))
1778 hr = read_text_value(reader, &value);
1779 if (hr == S_OK)
1781 TASK_RUNLEVEL_TYPE level = TASK_RUNLEVEL_LUA;
1783 if (!lstrcmpW(value, LeastPrivilege))
1784 level = TASK_RUNLEVEL_LUA;
1785 else
1786 FIXME("unhandled RunLevel %s\n", debugstr_w(value));
1788 IPrincipal_put_RunLevel(principal, level);
1791 else
1792 FIXME("unhandled Principal element %s\n", debugstr_w(name));
1794 break;
1796 case XmlNodeType_Whitespace:
1797 case XmlNodeType_Comment:
1798 break;
1800 default:
1801 FIXME("unhandled Principal node type %d\n", type);
1802 break;
1806 WARN("Principal was not terminated\n");
1807 return E_FAIL;
1810 static HRESULT read_principals(IXmlReader *reader, ITaskDefinition *taskdef)
1812 HRESULT hr;
1813 XmlNodeType type;
1814 const WCHAR *name;
1816 if (IXmlReader_IsEmptyElement(reader))
1818 TRACE("Principals is empty\n");
1819 return S_OK;
1822 while (IXmlReader_Read(reader, &type) == S_OK)
1824 switch (type)
1826 case XmlNodeType_EndElement:
1827 hr = IXmlReader_GetLocalName(reader, &name, NULL);
1828 if (hr != S_OK) return hr;
1830 TRACE("/%s\n", debugstr_w(name));
1832 if (!lstrcmpW(name, Principals))
1833 return S_OK;
1835 break;
1837 case XmlNodeType_Element:
1838 hr = IXmlReader_GetLocalName(reader, &name, NULL);
1839 if (hr != S_OK) return hr;
1841 TRACE("Element: %s\n", debugstr_w(name));
1843 if (!lstrcmpW(name, Principal))
1845 IPrincipal *principal;
1847 hr = ITaskDefinition_get_Principal(taskdef, &principal);
1848 if (hr != S_OK) return hr;
1849 hr = read_principal(reader, principal);
1850 IPrincipal_Release(principal);
1852 else
1853 FIXME("unhandled Principals element %s\n", debugstr_w(name));
1855 break;
1857 case XmlNodeType_Whitespace:
1858 case XmlNodeType_Comment:
1859 break;
1861 default:
1862 FIXME("unhandled Principals node type %d\n", type);
1863 break;
1867 WARN("Principals was not terminated\n");
1868 return E_FAIL;
1871 static HRESULT read_actions(IXmlReader *reader, ITaskDefinition *taskdef)
1873 FIXME("stub\n");
1874 return S_OK;
1877 static HRESULT read_idle_settings(IXmlReader *reader, ITaskSettings *taskset)
1879 FIXME("stub\n");
1880 return S_OK;
1883 static HRESULT read_settings(IXmlReader *reader, ITaskSettings *taskset)
1885 HRESULT hr;
1886 XmlNodeType type;
1887 const WCHAR *name;
1888 WCHAR *value;
1889 VARIANT_BOOL bool_val;
1890 int int_val;
1892 if (IXmlReader_IsEmptyElement(reader))
1894 TRACE("Settings is empty\n");
1895 return S_OK;
1898 while (IXmlReader_Read(reader, &type) == S_OK)
1900 switch (type)
1902 case XmlNodeType_EndElement:
1903 hr = IXmlReader_GetLocalName(reader, &name, NULL);
1904 if (hr != S_OK) return hr;
1906 TRACE("/%s\n", debugstr_w(name));
1908 if (!lstrcmpW(name, Settings))
1909 return S_OK;
1911 break;
1913 case XmlNodeType_Element:
1914 hr = IXmlReader_GetLocalName(reader, &name, NULL);
1915 if (hr != S_OK) return hr;
1917 TRACE("Element: %s\n", debugstr_w(name));
1919 if (!lstrcmpW(name, MultipleInstancesPolicy))
1921 hr = read_text_value(reader, &value);
1922 if (hr == S_OK)
1924 int_val = TASK_INSTANCES_IGNORE_NEW;
1926 if (!lstrcmpW(value, IgnoreNew))
1927 int_val = TASK_INSTANCES_IGNORE_NEW;
1928 else
1929 FIXME("unhandled MultipleInstancesPolicy %s\n", debugstr_w(value));
1931 ITaskSettings_put_MultipleInstances(taskset, int_val);
1934 else if (!lstrcmpW(name, DisallowStartIfOnBatteries))
1936 hr = read_variantbool_value(reader, &bool_val);
1937 if (hr != S_OK) return hr;
1938 ITaskSettings_put_DisallowStartIfOnBatteries(taskset, bool_val);
1940 else if (!lstrcmpW(name, AllowStartOnDemand))
1942 hr = read_variantbool_value(reader, &bool_val);
1943 if (hr != S_OK) return hr;
1944 ITaskSettings_put_AllowDemandStart(taskset, bool_val);
1946 else if (!lstrcmpW(name, StopIfGoingOnBatteries))
1948 hr = read_variantbool_value(reader, &bool_val);
1949 if (hr != S_OK) return hr;
1950 ITaskSettings_put_StopIfGoingOnBatteries(taskset, bool_val);
1952 else if (!lstrcmpW(name, AllowHardTerminate))
1954 hr = read_variantbool_value(reader, &bool_val);
1955 if (hr != S_OK) return hr;
1956 ITaskSettings_put_AllowHardTerminate(taskset, bool_val);
1958 else if (!lstrcmpW(name, StartWhenAvailable))
1960 hr = read_variantbool_value(reader, &bool_val);
1961 if (hr != S_OK) return hr;
1962 ITaskSettings_put_StartWhenAvailable(taskset, bool_val);
1964 else if (!lstrcmpW(name, RunOnlyIfNetworkAvailable))
1966 hr = read_variantbool_value(reader, &bool_val);
1967 if (hr != S_OK) return hr;
1968 ITaskSettings_put_RunOnlyIfNetworkAvailable(taskset, bool_val);
1970 else if (!lstrcmpW(name, Enabled))
1972 hr = read_variantbool_value(reader, &bool_val);
1973 if (hr != S_OK) return hr;
1974 ITaskSettings_put_Enabled(taskset, bool_val);
1976 else if (!lstrcmpW(name, Hidden))
1978 hr = read_variantbool_value(reader, &bool_val);
1979 if (hr != S_OK) return hr;
1980 ITaskSettings_put_Hidden(taskset, bool_val);
1982 else if (!lstrcmpW(name, RunOnlyIfIdle))
1984 hr = read_variantbool_value(reader, &bool_val);
1985 if (hr != S_OK) return hr;
1986 ITaskSettings_put_RunOnlyIfIdle(taskset, bool_val);
1988 else if (!lstrcmpW(name, WakeToRun))
1990 hr = read_variantbool_value(reader, &bool_val);
1991 if (hr != S_OK) return hr;
1992 ITaskSettings_put_WakeToRun(taskset, bool_val);
1994 else if (!lstrcmpW(name, ExecutionTimeLimit))
1996 hr = read_text_value(reader, &value);
1997 if (hr == S_OK)
1998 ITaskSettings_put_ExecutionTimeLimit(taskset, value);
2000 else if (!lstrcmpW(name, Priority))
2002 hr = read_int_value(reader, &int_val);
2003 if (hr == S_OK)
2004 ITaskSettings_put_Priority(taskset, int_val);
2006 else if (!lstrcmpW(name, IdleSettings))
2008 hr = read_idle_settings(reader, taskset);
2009 if (hr != S_OK) return hr;
2011 else
2012 FIXME("unhandled Settings element %s\n", debugstr_w(name));
2014 break;
2016 case XmlNodeType_Whitespace:
2017 case XmlNodeType_Comment:
2018 break;
2020 default:
2021 FIXME("unhandled Settings node type %d\n", type);
2022 break;
2026 WARN("Settings was not terminated\n");
2027 return SCHED_E_MALFORMEDXML;
2030 static HRESULT read_registration_info(IXmlReader *reader, IRegistrationInfo *info)
2032 HRESULT hr;
2033 XmlNodeType type;
2034 const WCHAR *name;
2035 WCHAR *value;
2037 if (IXmlReader_IsEmptyElement(reader))
2039 TRACE("RegistrationInfo is empty\n");
2040 return S_OK;
2043 while (IXmlReader_Read(reader, &type) == S_OK)
2045 switch (type)
2047 case XmlNodeType_EndElement:
2048 hr = IXmlReader_GetLocalName(reader, &name, NULL);
2049 if (hr != S_OK) return hr;
2051 TRACE("/%s\n", debugstr_w(name));
2053 if (!lstrcmpW(name, RegistrationInfo))
2054 return S_OK;
2056 break;
2058 case XmlNodeType_Element:
2059 hr = IXmlReader_GetLocalName(reader, &name, NULL);
2060 if (hr != S_OK) return hr;
2062 TRACE("Element: %s\n", debugstr_w(name));
2064 if (!lstrcmpW(name, Author))
2066 hr = read_text_value(reader, &value);
2067 if (hr == S_OK)
2068 IRegistrationInfo_put_Author(info, value);
2070 else if (!lstrcmpW(name, Description))
2072 hr = read_text_value(reader, &value);
2073 if (hr == S_OK)
2074 IRegistrationInfo_put_Description(info, value);
2076 else
2077 FIXME("unhandled RegistrationInfo element %s\n", debugstr_w(name));
2079 break;
2081 case XmlNodeType_Whitespace:
2082 case XmlNodeType_Comment:
2083 break;
2085 default:
2086 FIXME("unhandled RegistrationInfo node type %d\n", type);
2087 break;
2091 WARN("RegistrationInfo was not terminated\n");
2092 return SCHED_E_MALFORMEDXML;
2095 static HRESULT read_task_attributes(IXmlReader *reader, ITaskDefinition *taskdef)
2097 HRESULT hr;
2098 ITaskSettings *taskset;
2099 const WCHAR *name;
2100 const WCHAR *value;
2101 BOOL xmlns_ok = FALSE;
2103 TRACE("\n");
2105 hr = ITaskDefinition_get_Settings(taskdef, &taskset);
2106 if (hr != S_OK) return hr;
2108 hr = IXmlReader_MoveToFirstAttribute(reader);
2110 while (hr == S_OK)
2112 hr = IXmlReader_GetLocalName(reader, &name, NULL);
2113 if (hr != S_OK) break;
2115 hr = IXmlReader_GetValue(reader, &value, NULL);
2116 if (hr != S_OK) break;
2118 TRACE("%s=%s\n", debugstr_w(name), debugstr_w(value));
2120 if (!lstrcmpW(name, version))
2122 TASK_COMPATIBILITY compatibility = TASK_COMPATIBILITY_V2;
2124 if (!lstrcmpW(value, v1_0))
2125 compatibility = TASK_COMPATIBILITY_AT;
2126 else if (!lstrcmpW(value, v1_1))
2127 compatibility = TASK_COMPATIBILITY_V1;
2128 else if (!lstrcmpW(value, v1_2))
2129 compatibility = TASK_COMPATIBILITY_V2;
2130 else if (!lstrcmpW(value, v1_3))
2131 compatibility = TASK_COMPATIBILITY_V2_1;
2132 else
2133 FIXME("unknown version %s\n", debugstr_w(value));
2135 ITaskSettings_put_Compatibility(taskset, compatibility);
2137 else if (!lstrcmpW(name, xmlns))
2139 if (lstrcmpW(value, task_ns))
2141 FIXME("unknown namespace %s\n", debugstr_w(value));
2142 break;
2144 xmlns_ok = TRUE;
2146 else
2147 FIXME("unhandled Task attribute %s\n", debugstr_w(name));
2149 hr = IXmlReader_MoveToNextAttribute(reader);
2152 ITaskSettings_Release(taskset);
2153 return xmlns_ok ? S_OK : SCHED_E_NAMESPACE;
2156 static HRESULT read_task(IXmlReader *reader, ITaskDefinition *taskdef)
2158 HRESULT hr;
2159 XmlNodeType type;
2160 const WCHAR *name;
2162 if (IXmlReader_IsEmptyElement(reader))
2164 TRACE("Task is empty\n");
2165 return S_OK;
2168 while (IXmlReader_Read(reader, &type) == S_OK)
2170 switch (type)
2172 case XmlNodeType_EndElement:
2173 hr = IXmlReader_GetLocalName(reader, &name, NULL);
2174 if (hr != S_OK) return hr;
2176 TRACE("/%s\n", debugstr_w(name));
2178 if (!lstrcmpW(name, Task))
2179 return S_OK;
2181 break;
2183 case XmlNodeType_Element:
2184 hr = IXmlReader_GetLocalName(reader, &name, NULL);
2185 if (hr != S_OK) return hr;
2187 TRACE("Element: %s\n", debugstr_w(name));
2189 if (!lstrcmpW(name, RegistrationInfo))
2191 IRegistrationInfo *info;
2193 hr = ITaskDefinition_get_RegistrationInfo(taskdef, &info);
2194 if (hr != S_OK) return hr;
2195 hr = read_registration_info(reader, info);
2196 IRegistrationInfo_Release(info);
2198 else if (!lstrcmpW(name, Settings))
2200 ITaskSettings *taskset;
2202 hr = ITaskDefinition_get_Settings(taskdef, &taskset);
2203 if (hr != S_OK) return hr;
2204 hr = read_settings(reader, taskset);
2205 ITaskSettings_Release(taskset);
2207 else if (!lstrcmpW(name, Triggers))
2208 hr = read_triggers(reader, taskdef);
2209 else if (!lstrcmpW(name, Principals))
2210 hr = read_principals(reader, taskdef);
2211 else if (!lstrcmpW(name, Actions))
2212 hr = read_actions(reader, taskdef);
2213 else
2214 FIXME("unhandled Task element %s\n", debugstr_w(name));
2216 if (hr != S_OK) return hr;
2217 break;
2219 case XmlNodeType_Comment:
2220 case XmlNodeType_Whitespace:
2221 break;
2223 default:
2224 FIXME("unhandled Task node type %d\n", type);
2225 break;
2229 WARN("Task was not terminated\n");
2230 return SCHED_E_MALFORMEDXML;
2233 static HRESULT read_xml(IXmlReader *reader, ITaskDefinition *taskdef)
2235 HRESULT hr;
2236 XmlNodeType type;
2237 const WCHAR *name;
2239 while (IXmlReader_Read(reader, &type) == S_OK)
2241 switch (type)
2243 case XmlNodeType_XmlDeclaration:
2244 TRACE("XmlDeclaration\n");
2245 break;
2247 case XmlNodeType_Element:
2248 hr = IXmlReader_GetLocalName(reader, &name, NULL);
2249 if (hr != S_OK) return hr;
2251 TRACE("Element: %s\n", debugstr_w(name));
2253 if (!lstrcmpW(name, Task))
2255 hr = read_task_attributes(reader, taskdef);
2256 if (hr != S_OK) return hr;
2258 return read_task(reader, taskdef);
2260 else
2261 FIXME("unhandled XML element %s\n", debugstr_w(name));
2263 break;
2265 case XmlNodeType_Comment:
2266 case XmlNodeType_Whitespace:
2267 break;
2269 default:
2270 FIXME("unhandled XML node type %d\n", type);
2271 break;
2275 WARN("Task definition was not found\n");
2276 return SCHED_E_MALFORMEDXML;
2279 static HRESULT WINAPI TaskDefinition_put_XmlText(ITaskDefinition *iface, BSTR xml)
2281 TaskDefinition *taskdef = impl_from_ITaskDefinition(iface);
2282 HRESULT hr;
2283 IStream *stream;
2284 IXmlReader *reader;
2285 HGLOBAL hmem;
2286 void *buf;
2288 TRACE("%p,%s\n", iface, debugstr_w(xml));
2290 if (!xml) return E_INVALIDARG;
2292 hmem = GlobalAlloc(0, lstrlenW(xml) * sizeof(WCHAR));
2293 if (!hmem) return E_OUTOFMEMORY;
2295 buf = GlobalLock(hmem);
2296 memcpy(buf, xml, lstrlenW(xml) * sizeof(WCHAR));
2297 GlobalUnlock(hmem);
2299 hr = CreateStreamOnHGlobal(hmem, TRUE, &stream);
2300 if (hr != S_OK)
2302 GlobalFree(hmem);
2303 return hr;
2306 hr = CreateXmlReader(&IID_IXmlReader, (void **)&reader, NULL);
2307 if (hr != S_OK)
2309 IStream_Release(stream);
2310 return hr;
2313 hr = IXmlReader_SetInput(reader, (IUnknown *)stream);
2314 if (hr == S_OK)
2316 if (taskdef->reginfo)
2318 IRegistrationInfo_Release(taskdef->reginfo);
2319 taskdef->reginfo = NULL;
2321 if (taskdef->taskset)
2323 ITaskSettings_Release(taskdef->taskset);
2324 taskdef->taskset = NULL;
2326 if (taskdef->triggers)
2328 ITriggerCollection_Release(taskdef->triggers);
2329 taskdef->triggers = NULL;
2331 if (taskdef->principal)
2333 IPrincipal_Release(taskdef->principal);
2334 taskdef->principal = NULL;
2336 if (taskdef->actions)
2338 IActionCollection_Release(taskdef->actions);
2339 taskdef->actions = NULL;
2342 hr = read_xml(reader, iface);
2345 IXmlReader_Release(reader);
2346 IStream_Release(stream);
2348 return hr;
2351 static const ITaskDefinitionVtbl TaskDefinition_vtbl =
2353 TaskDefinition_QueryInterface,
2354 TaskDefinition_AddRef,
2355 TaskDefinition_Release,
2356 TaskDefinition_GetTypeInfoCount,
2357 TaskDefinition_GetTypeInfo,
2358 TaskDefinition_GetIDsOfNames,
2359 TaskDefinition_Invoke,
2360 TaskDefinition_get_RegistrationInfo,
2361 TaskDefinition_put_RegistrationInfo,
2362 TaskDefinition_get_Triggers,
2363 TaskDefinition_put_Triggers,
2364 TaskDefinition_get_Settings,
2365 TaskDefinition_put_Settings,
2366 TaskDefinition_get_Data,
2367 TaskDefinition_put_Data,
2368 TaskDefinition_get_Principal,
2369 TaskDefinition_put_Principal,
2370 TaskDefinition_get_Actions,
2371 TaskDefinition_put_Actions,
2372 TaskDefinition_get_XmlText,
2373 TaskDefinition_put_XmlText
2376 HRESULT TaskDefinition_create(ITaskDefinition **obj)
2378 TaskDefinition *taskdef;
2380 taskdef = heap_alloc_zero(sizeof(*taskdef));
2381 if (!taskdef) return E_OUTOFMEMORY;
2383 taskdef->ITaskDefinition_iface.lpVtbl = &TaskDefinition_vtbl;
2384 taskdef->ref = 1;
2385 *obj = &taskdef->ITaskDefinition_iface;
2387 TRACE("created %p\n", *obj);
2389 return S_OK;
2392 typedef struct
2394 ITaskService ITaskService_iface;
2395 LONG ref;
2396 BOOL connected;
2397 DWORD version;
2398 WCHAR comp_name[MAX_COMPUTERNAME_LENGTH + 1];
2399 } TaskService;
2401 static inline TaskService *impl_from_ITaskService(ITaskService *iface)
2403 return CONTAINING_RECORD(iface, TaskService, ITaskService_iface);
2406 static ULONG WINAPI TaskService_AddRef(ITaskService *iface)
2408 TaskService *task_svc = impl_from_ITaskService(iface);
2409 return InterlockedIncrement(&task_svc->ref);
2412 static ULONG WINAPI TaskService_Release(ITaskService *iface)
2414 TaskService *task_svc = impl_from_ITaskService(iface);
2415 LONG ref = InterlockedDecrement(&task_svc->ref);
2417 if (!ref)
2419 TRACE("destroying %p\n", iface);
2420 heap_free(task_svc);
2423 return ref;
2426 static HRESULT WINAPI TaskService_QueryInterface(ITaskService *iface, REFIID riid, void **obj)
2428 if (!riid || !obj) return E_INVALIDARG;
2430 TRACE("%p,%s,%p\n", iface, debugstr_guid(riid), obj);
2432 if (IsEqualGUID(riid, &IID_ITaskService) ||
2433 IsEqualGUID(riid, &IID_IDispatch) ||
2434 IsEqualGUID(riid, &IID_IUnknown))
2436 ITaskService_AddRef(iface);
2437 *obj = iface;
2438 return S_OK;
2441 FIXME("interface %s is not implemented\n", debugstr_guid(riid));
2442 *obj = NULL;
2443 return E_NOINTERFACE;
2446 static HRESULT WINAPI TaskService_GetTypeInfoCount(ITaskService *iface, UINT *count)
2448 FIXME("%p,%p: stub\n", iface, count);
2449 return E_NOTIMPL;
2452 static HRESULT WINAPI TaskService_GetTypeInfo(ITaskService *iface, UINT index, LCID lcid, ITypeInfo **info)
2454 FIXME("%p,%u,%u,%p: stub\n", iface, index, lcid, info);
2455 return E_NOTIMPL;
2458 static HRESULT WINAPI TaskService_GetIDsOfNames(ITaskService *iface, REFIID riid, LPOLESTR *names,
2459 UINT count, LCID lcid, DISPID *dispid)
2461 FIXME("%p,%s,%p,%u,%u,%p: stub\n", iface, debugstr_guid(riid), names, count, lcid, dispid);
2462 return E_NOTIMPL;
2465 static HRESULT WINAPI TaskService_Invoke(ITaskService *iface, DISPID dispid, REFIID riid, LCID lcid, WORD flags,
2466 DISPPARAMS *params, VARIANT *result, EXCEPINFO *excepinfo, UINT *argerr)
2468 FIXME("%p,%d,%s,%04x,%04x,%p,%p,%p,%p: stub\n", iface, dispid, debugstr_guid(riid), lcid, flags,
2469 params, result, excepinfo, argerr);
2470 return E_NOTIMPL;
2473 static HRESULT WINAPI TaskService_GetFolder(ITaskService *iface, BSTR path, ITaskFolder **folder)
2475 TaskService *task_svc = impl_from_ITaskService(iface);
2477 TRACE("%p,%s,%p\n", iface, debugstr_w(path), folder);
2479 if (!folder) return E_POINTER;
2481 if (!task_svc->connected)
2482 return HRESULT_FROM_WIN32(ERROR_ONLY_IF_CONNECTED);
2484 return TaskFolder_create(path, NULL, folder, FALSE);
2487 static HRESULT WINAPI TaskService_GetRunningTasks(ITaskService *iface, LONG flags, IRunningTaskCollection **tasks)
2489 FIXME("%p,%x,%p: stub\n", iface, flags, tasks);
2490 return E_NOTIMPL;
2493 static HRESULT WINAPI TaskService_NewTask(ITaskService *iface, DWORD flags, ITaskDefinition **definition)
2495 TRACE("%p,%x,%p\n", iface, flags, definition);
2497 if (!definition) return E_POINTER;
2499 if (flags)
2500 FIXME("unsupported flags %x\n", flags);
2502 return TaskDefinition_create(definition);
2505 static inline BOOL is_variant_null(const VARIANT *var)
2507 return V_VT(var) == VT_EMPTY || V_VT(var) == VT_NULL ||
2508 (V_VT(var) == VT_BSTR && (V_BSTR(var) == NULL || !*V_BSTR(var)));
2511 static HRESULT start_schedsvc(void)
2513 static const WCHAR scheduleW[] = { 'S','c','h','e','d','u','l','e',0 };
2514 SC_HANDLE scm, service;
2515 SERVICE_STATUS_PROCESS status;
2516 ULONGLONG start_time;
2517 HRESULT hr = SCHED_E_SERVICE_NOT_RUNNING;
2519 TRACE("Trying to start %s service\n", debugstr_w(scheduleW));
2521 scm = OpenSCManagerW(NULL, NULL, 0);
2522 if (!scm) return SCHED_E_SERVICE_NOT_INSTALLED;
2524 service = OpenServiceW(scm, scheduleW, SERVICE_START | SERVICE_QUERY_STATUS);
2525 if (service)
2527 if (StartServiceW(service, 0, NULL) || GetLastError() == ERROR_SERVICE_ALREADY_RUNNING)
2529 start_time = GetTickCount64();
2532 DWORD dummy;
2534 if (!QueryServiceStatusEx(service, SC_STATUS_PROCESS_INFO, (BYTE *)&status, sizeof(status), &dummy))
2536 WARN("failed to query scheduler status (%u)\n", GetLastError());
2537 break;
2540 if (status.dwCurrentState == SERVICE_RUNNING)
2542 hr = S_OK;
2543 break;
2546 if (GetTickCount64() - start_time > 30000) break;
2547 Sleep(1000);
2549 } while (status.dwCurrentState == SERVICE_START_PENDING);
2551 if (status.dwCurrentState != SERVICE_RUNNING)
2552 WARN("scheduler failed to start %u\n", status.dwCurrentState);
2554 else
2555 WARN("failed to start scheduler service (%u)\n", GetLastError());
2557 CloseServiceHandle(service);
2559 else
2560 WARN("failed to open scheduler service (%u)\n", GetLastError());
2562 CloseServiceHandle(scm);
2563 return hr;
2566 static HRESULT WINAPI TaskService_Connect(ITaskService *iface, VARIANT server, VARIANT user, VARIANT domain, VARIANT password)
2568 static WCHAR ncalrpc[] = { 'n','c','a','l','r','p','c',0 };
2569 TaskService *task_svc = impl_from_ITaskService(iface);
2570 WCHAR comp_name[MAX_COMPUTERNAME_LENGTH + 1];
2571 DWORD len;
2572 HRESULT hr;
2573 RPC_WSTR binding_str;
2574 extern handle_t rpc_handle;
2576 TRACE("%p,%s,%s,%s,%s\n", iface, debugstr_variant(&server), debugstr_variant(&user),
2577 debugstr_variant(&domain), debugstr_variant(&password));
2579 if (!is_variant_null(&user) || !is_variant_null(&domain) || !is_variant_null(&password))
2580 FIXME("user/domain/password are ignored\n");
2582 len = sizeof(comp_name)/sizeof(comp_name[0]);
2583 if (!GetComputerNameW(comp_name, &len))
2584 return HRESULT_FROM_WIN32(GetLastError());
2586 if (!is_variant_null(&server))
2588 const WCHAR *server_name;
2590 if (V_VT(&server) != VT_BSTR)
2592 FIXME("server variant type %d is not supported\n", V_VT(&server));
2593 return HRESULT_FROM_WIN32(ERROR_BAD_NETPATH);
2596 /* skip UNC prefix if any */
2597 server_name = V_BSTR(&server);
2598 if (server_name[0] == '\\' && server_name[1] == '\\')
2599 server_name += 2;
2601 if (strcmpiW(server_name, comp_name))
2603 FIXME("connection to remote server %s is not supported\n", debugstr_w(V_BSTR(&server)));
2604 return HRESULT_FROM_WIN32(ERROR_BAD_NETPATH);
2608 hr = start_schedsvc();
2609 if (hr != S_OK) return hr;
2611 hr = RpcStringBindingComposeW(NULL, ncalrpc, NULL, NULL, NULL, &binding_str);
2612 if (hr != RPC_S_OK) return hr;
2613 hr = RpcBindingFromStringBindingW(binding_str, &rpc_handle);
2614 if (hr != RPC_S_OK) return hr;
2615 RpcStringFreeW(&binding_str);
2617 /* Make sure that the connection works */
2618 hr = SchRpcHighestVersion(&task_svc->version);
2619 if (hr != S_OK) return hr;
2621 TRACE("server version %#x\n", task_svc->version);
2623 strcpyW(task_svc->comp_name, comp_name);
2624 task_svc->connected = TRUE;
2626 return S_OK;
2629 static HRESULT WINAPI TaskService_get_Connected(ITaskService *iface, VARIANT_BOOL *connected)
2631 TaskService *task_svc = impl_from_ITaskService(iface);
2633 TRACE("%p,%p\n", iface, connected);
2635 if (!connected) return E_POINTER;
2637 *connected = task_svc->connected ? VARIANT_TRUE : VARIANT_FALSE;
2639 return S_OK;
2642 static HRESULT WINAPI TaskService_get_TargetServer(ITaskService *iface, BSTR *server)
2644 TaskService *task_svc = impl_from_ITaskService(iface);
2646 TRACE("%p,%p\n", iface, server);
2648 if (!server) return E_POINTER;
2650 if (!task_svc->connected)
2651 return HRESULT_FROM_WIN32(ERROR_ONLY_IF_CONNECTED);
2653 *server = SysAllocString(task_svc->comp_name);
2654 if (!*server) return E_OUTOFMEMORY;
2656 return S_OK;
2659 static HRESULT WINAPI TaskService_get_ConnectedUser(ITaskService *iface, BSTR *user)
2661 FIXME("%p,%p: stub\n", iface, user);
2662 return E_NOTIMPL;
2665 static HRESULT WINAPI TaskService_get_ConnectedDomain(ITaskService *iface, BSTR *domain)
2667 FIXME("%p,%p: stub\n", iface, domain);
2668 return E_NOTIMPL;
2671 static HRESULT WINAPI TaskService_get_HighestVersion(ITaskService *iface, DWORD *version)
2673 TaskService *task_svc = impl_from_ITaskService(iface);
2675 TRACE("%p,%p\n", iface, version);
2677 if (!version) return E_POINTER;
2679 if (!task_svc->connected)
2680 return HRESULT_FROM_WIN32(ERROR_ONLY_IF_CONNECTED);
2682 *version = task_svc->version;
2684 return S_OK;
2687 static const ITaskServiceVtbl TaskService_vtbl =
2689 TaskService_QueryInterface,
2690 TaskService_AddRef,
2691 TaskService_Release,
2692 TaskService_GetTypeInfoCount,
2693 TaskService_GetTypeInfo,
2694 TaskService_GetIDsOfNames,
2695 TaskService_Invoke,
2696 TaskService_GetFolder,
2697 TaskService_GetRunningTasks,
2698 TaskService_NewTask,
2699 TaskService_Connect,
2700 TaskService_get_Connected,
2701 TaskService_get_TargetServer,
2702 TaskService_get_ConnectedUser,
2703 TaskService_get_ConnectedDomain,
2704 TaskService_get_HighestVersion
2707 HRESULT TaskService_create(void **obj)
2709 TaskService *task_svc;
2711 task_svc = heap_alloc(sizeof(*task_svc));
2712 if (!task_svc) return E_OUTOFMEMORY;
2714 task_svc->ITaskService_iface.lpVtbl = &TaskService_vtbl;
2715 task_svc->ref = 1;
2716 task_svc->connected = FALSE;
2717 *obj = &task_svc->ITaskService_iface;
2719 TRACE("created %p\n", *obj);
2721 return S_OK;
2724 void __RPC_FAR *__RPC_USER MIDL_user_allocate(SIZE_T n)
2726 return HeapAlloc(GetProcessHeap(), 0, n);
2729 void __RPC_USER MIDL_user_free(void __RPC_FAR *p)
2731 HeapFree(GetProcessHeap(), 0, p);