taskschd: Implement ITaskSettings_put_Priority.
[wine.git] / dlls / taskschd / task.c
blob33ec2b45d18f535fc9374be16e8646f00c7dca2f
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 {
39 IDailyTrigger IDailyTrigger_iface;
40 LONG ref;
41 short interval;
42 } DailyTrigger;
44 static inline DailyTrigger *impl_from_IDailyTrigger(IDailyTrigger *iface)
46 return CONTAINING_RECORD(iface, DailyTrigger, IDailyTrigger_iface);
49 static HRESULT WINAPI DailyTrigger_QueryInterface(IDailyTrigger *iface, REFIID riid, void **ppv)
51 DailyTrigger *This = impl_from_IDailyTrigger(iface);
53 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
55 if(IsEqualGUID(&IID_IUnknown, riid) ||
56 IsEqualGUID(&IID_IDispatch, riid) ||
57 IsEqualGUID(&IID_ITrigger, riid) ||
58 IsEqualGUID(&IID_IDailyTrigger, riid))
60 *ppv = &This->IDailyTrigger_iface;
62 else
64 FIXME("unsupported riid %s\n", debugstr_guid(riid));
65 *ppv = NULL;
66 return E_NOINTERFACE;
69 IUnknown_AddRef((IUnknown*)*ppv);
70 return S_OK;
73 static ULONG WINAPI DailyTrigger_AddRef(IDailyTrigger *iface)
75 DailyTrigger *This = impl_from_IDailyTrigger(iface);
76 LONG ref = InterlockedIncrement(&This->ref);
78 TRACE("(%p) ref=%d\n", This, ref);
80 return ref;
83 static ULONG WINAPI DailyTrigger_Release(IDailyTrigger *iface)
85 DailyTrigger *This = impl_from_IDailyTrigger(iface);
86 LONG ref = InterlockedDecrement(&This->ref);
88 TRACE("(%p) ref=%d\n", This, ref);
90 if(!ref)
91 heap_free(This);
93 return ref;
96 static HRESULT WINAPI DailyTrigger_GetTypeInfoCount(IDailyTrigger *iface, UINT *count)
98 DailyTrigger *This = impl_from_IDailyTrigger(iface);
99 FIXME("(%p)->(%p)\n", This, count);
100 return E_NOTIMPL;
103 static HRESULT WINAPI DailyTrigger_GetTypeInfo(IDailyTrigger *iface, UINT index, LCID lcid, ITypeInfo **info)
105 DailyTrigger *This = impl_from_IDailyTrigger(iface);
106 FIXME("(%p)->(%u %u %p)\n", This, index, lcid, info);
107 return E_NOTIMPL;
110 static HRESULT WINAPI DailyTrigger_GetIDsOfNames(IDailyTrigger *iface, REFIID riid, LPOLESTR *names,
111 UINT count, LCID lcid, DISPID *dispid)
113 DailyTrigger *This = impl_from_IDailyTrigger(iface);
114 FIXME("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), names, count, lcid, dispid);
115 return E_NOTIMPL;
118 static HRESULT WINAPI DailyTrigger_Invoke(IDailyTrigger *iface, DISPID dispid, REFIID riid, LCID lcid, WORD flags,
119 DISPPARAMS *params, VARIANT *result, EXCEPINFO *excepinfo, UINT *argerr)
121 DailyTrigger *This = impl_from_IDailyTrigger(iface);
122 FIXME("(%p)->(%d %s %x %x %p %p %p %p)\n", This, dispid, debugstr_guid(riid), lcid, flags,
123 params, result, excepinfo, argerr);
124 return E_NOTIMPL;
127 static HRESULT WINAPI DailyTrigger_get_Type(IDailyTrigger *iface, TASK_TRIGGER_TYPE2 *type)
129 DailyTrigger *This = impl_from_IDailyTrigger(iface);
130 FIXME("(%p)->(%p)\n", This, type);
131 return E_NOTIMPL;
134 static HRESULT WINAPI DailyTrigger_get_Id(IDailyTrigger *iface, BSTR *id)
136 DailyTrigger *This = impl_from_IDailyTrigger(iface);
137 FIXME("(%p)->(%p)\n", This, id);
138 return E_NOTIMPL;
141 static HRESULT WINAPI DailyTrigger_put_Id(IDailyTrigger *iface, BSTR id)
143 DailyTrigger *This = impl_from_IDailyTrigger(iface);
144 FIXME("(%p)->(%s)\n", This, debugstr_w(id));
145 return E_NOTIMPL;
148 static HRESULT WINAPI DailyTrigger_get_Repetition(IDailyTrigger *iface, IRepetitionPattern **repeat)
150 DailyTrigger *This = impl_from_IDailyTrigger(iface);
151 FIXME("(%p)->(%p)\n", This, repeat);
152 return E_NOTIMPL;
155 static HRESULT WINAPI DailyTrigger_put_Repetition(IDailyTrigger *iface, IRepetitionPattern *repeat)
157 DailyTrigger *This = impl_from_IDailyTrigger(iface);
158 FIXME("(%p)->(%p)\n", This, repeat);
159 return E_NOTIMPL;
162 static HRESULT WINAPI DailyTrigger_get_ExecutionTimeLimit(IDailyTrigger *iface, BSTR *limit)
164 DailyTrigger *This = impl_from_IDailyTrigger(iface);
165 FIXME("(%p)->(%p)\n", This, limit);
166 return E_NOTIMPL;
169 static HRESULT WINAPI DailyTrigger_put_ExecutionTimeLimit(IDailyTrigger *iface, BSTR limit)
171 DailyTrigger *This = impl_from_IDailyTrigger(iface);
172 FIXME("(%p)->(%s)\n", This, debugstr_w(limit));
173 return E_NOTIMPL;
176 static HRESULT WINAPI DailyTrigger_get_StartBoundary(IDailyTrigger *iface, BSTR *start)
178 DailyTrigger *This = impl_from_IDailyTrigger(iface);
179 FIXME("(%p)->(%p)\n", This, start);
180 return E_NOTIMPL;
183 static HRESULT WINAPI DailyTrigger_put_StartBoundary(IDailyTrigger *iface, BSTR start)
185 DailyTrigger *This = impl_from_IDailyTrigger(iface);
186 FIXME("(%p)->(%s)\n", This, debugstr_w(start));
187 return S_OK;
190 static HRESULT WINAPI DailyTrigger_get_EndBoundary(IDailyTrigger *iface, BSTR *end)
192 DailyTrigger *This = impl_from_IDailyTrigger(iface);
193 FIXME("(%p)->(%p)\n", This, end);
194 return E_NOTIMPL;
197 static HRESULT WINAPI DailyTrigger_put_EndBoundary(IDailyTrigger *iface, BSTR end)
199 DailyTrigger *This = impl_from_IDailyTrigger(iface);
200 FIXME("(%p)->(%s)\n", This, debugstr_w(end));
201 return E_NOTIMPL;
204 static HRESULT WINAPI DailyTrigger_get_Enabled(IDailyTrigger *iface, VARIANT_BOOL *enabled)
206 DailyTrigger *This = impl_from_IDailyTrigger(iface);
207 FIXME("(%p)->(%p)\n", This, enabled);
208 return E_NOTIMPL;
211 static HRESULT WINAPI DailyTrigger_put_Enabled(IDailyTrigger *iface, VARIANT_BOOL enabled)
213 DailyTrigger *This = impl_from_IDailyTrigger(iface);
214 FIXME("(%p)->(%x)\n", This, enabled);
215 return S_OK;
218 static HRESULT WINAPI DailyTrigger_get_DaysInterval(IDailyTrigger *iface, short *days)
220 DailyTrigger *This = impl_from_IDailyTrigger(iface);
222 TRACE("(%p)->(%p)\n", This, days);
224 *days = This->interval;
225 return S_OK;
228 static HRESULT WINAPI DailyTrigger_put_DaysInterval(IDailyTrigger *iface, short days)
230 DailyTrigger *This = impl_from_IDailyTrigger(iface);
232 TRACE("(%p)->(%d)\n", This, days);
234 if(days <= 0)
235 return E_INVALIDARG;
237 This->interval = days;
238 return S_OK;
241 static HRESULT WINAPI DailyTrigger_get_RandomDelay(IDailyTrigger *iface, BSTR *pRandomDelay)
243 DailyTrigger *This = impl_from_IDailyTrigger(iface);
244 FIXME("(%p)->(%p)\n", This, pRandomDelay);
245 return E_NOTIMPL;
248 static HRESULT WINAPI DailyTrigger_put_RandomDelay(IDailyTrigger *iface, BSTR randomDelay)
250 DailyTrigger *This = impl_from_IDailyTrigger(iface);
251 FIXME("(%p)->(%s)\n", This, debugstr_w(randomDelay));
252 return E_NOTIMPL;
255 static const IDailyTriggerVtbl DailyTrigger_vtbl = {
256 DailyTrigger_QueryInterface,
257 DailyTrigger_AddRef,
258 DailyTrigger_Release,
259 DailyTrigger_GetTypeInfoCount,
260 DailyTrigger_GetTypeInfo,
261 DailyTrigger_GetIDsOfNames,
262 DailyTrigger_Invoke,
263 DailyTrigger_get_Type,
264 DailyTrigger_get_Id,
265 DailyTrigger_put_Id,
266 DailyTrigger_get_Repetition,
267 DailyTrigger_put_Repetition,
268 DailyTrigger_get_ExecutionTimeLimit,
269 DailyTrigger_put_ExecutionTimeLimit,
270 DailyTrigger_get_StartBoundary,
271 DailyTrigger_put_StartBoundary,
272 DailyTrigger_get_EndBoundary,
273 DailyTrigger_put_EndBoundary,
274 DailyTrigger_get_Enabled,
275 DailyTrigger_put_Enabled,
276 DailyTrigger_get_DaysInterval,
277 DailyTrigger_put_DaysInterval,
278 DailyTrigger_get_RandomDelay,
279 DailyTrigger_put_RandomDelay
282 static HRESULT DailyTrigger_create(ITrigger **trigger)
284 DailyTrigger *daily_trigger;
286 daily_trigger = heap_alloc(sizeof(*daily_trigger));
287 if (!daily_trigger)
288 return E_OUTOFMEMORY;
290 daily_trigger->IDailyTrigger_iface.lpVtbl = &DailyTrigger_vtbl;
291 daily_trigger->ref = 1;
292 daily_trigger->interval = 1;
294 *trigger = (ITrigger*)&daily_trigger->IDailyTrigger_iface;
295 return S_OK;
298 typedef struct
300 ITriggerCollection ITriggerCollection_iface;
301 LONG ref;
302 } trigger_collection;
304 static inline trigger_collection *impl_from_ITriggerCollection(ITriggerCollection *iface)
306 return CONTAINING_RECORD(iface, trigger_collection, ITriggerCollection_iface);
309 static HRESULT WINAPI TriggerCollection_QueryInterface(ITriggerCollection *iface, REFIID riid, void **ppv)
311 trigger_collection *This = impl_from_ITriggerCollection(iface);
313 TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv);
315 if(IsEqualGUID(&IID_IUnknown, riid) ||
316 IsEqualGUID(&IID_IDispatch, riid) ||
317 IsEqualGUID(&IID_ITriggerCollection, riid)) {
318 *ppv = &This->ITriggerCollection_iface;
319 }else {
320 FIXME("unimplemented interface %s\n", debugstr_guid(riid));
321 *ppv = NULL;
322 return E_NOINTERFACE;
325 IUnknown_AddRef((IUnknown*)*ppv);
326 return S_OK;
329 static ULONG WINAPI TriggerCollection_AddRef(ITriggerCollection *iface)
331 trigger_collection *This = impl_from_ITriggerCollection(iface);
332 LONG ref = InterlockedIncrement(&This->ref);
334 TRACE("(%p) ref=%d\n", This, ref);
336 return ref;
339 static ULONG WINAPI TriggerCollection_Release(ITriggerCollection *iface)
341 trigger_collection *This = impl_from_ITriggerCollection(iface);
342 LONG ref = InterlockedDecrement(&This->ref);
344 TRACE("(%p) ref=%d\n", This, ref);
346 if(!ref)
347 heap_free(This);
349 return ref;
352 static HRESULT WINAPI TriggerCollection_GetTypeInfoCount(ITriggerCollection *iface, UINT *count)
354 trigger_collection *This = impl_from_ITriggerCollection(iface);
355 FIXME("(%p)->(%p)\n", This, count);
356 return E_NOTIMPL;
359 static HRESULT WINAPI TriggerCollection_GetTypeInfo(ITriggerCollection *iface, UINT index, LCID lcid, ITypeInfo **info)
361 trigger_collection *This = impl_from_ITriggerCollection(iface);
362 FIXME("(%p)->(%u %u %p)\n", This, index, lcid, info);
363 return E_NOTIMPL;
366 static HRESULT WINAPI TriggerCollection_GetIDsOfNames(ITriggerCollection *iface, REFIID riid, LPOLESTR *names,
367 UINT count, LCID lcid, DISPID *dispid)
369 trigger_collection *This = impl_from_ITriggerCollection(iface);
370 FIXME("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), names, count, lcid, dispid);
371 return E_NOTIMPL;
374 static HRESULT WINAPI TriggerCollection_Invoke(ITriggerCollection *iface, DISPID dispid, REFIID riid, LCID lcid, WORD flags,
375 DISPPARAMS *params, VARIANT *result, EXCEPINFO *excepinfo, UINT *argerr)
377 trigger_collection *This = impl_from_ITriggerCollection(iface);
378 FIXME("(%p)->(%d %s %x %x %p %p %p %p)\n", This, dispid, debugstr_guid(riid), lcid, flags,
379 params, result, excepinfo, argerr);
380 return E_NOTIMPL;
383 static HRESULT WINAPI TriggerCollection_get_Count(ITriggerCollection *iface, LONG *count)
385 trigger_collection *This = impl_from_ITriggerCollection(iface);
386 FIXME("(%p)->(%p)\n", This, count);
387 return E_NOTIMPL;
390 static HRESULT WINAPI TriggerCollection_get_Item(ITriggerCollection *iface, LONG index, ITrigger **trigger)
392 trigger_collection *This = impl_from_ITriggerCollection(iface);
393 FIXME("(%p)->(%d %p)\n", This, index, trigger);
394 return E_NOTIMPL;
397 static HRESULT WINAPI TriggerCollection_get__NewEnum(ITriggerCollection *iface, IUnknown **penum)
399 trigger_collection *This = impl_from_ITriggerCollection(iface);
400 FIXME("(%p)->(%p)\n", This, penum);
401 return E_NOTIMPL;
404 static HRESULT WINAPI TriggerCollection_Create(ITriggerCollection *iface, TASK_TRIGGER_TYPE2 type, ITrigger **trigger)
406 trigger_collection *This = impl_from_ITriggerCollection(iface);
408 TRACE("(%p)->(%d %p)\n", This, type, trigger);
410 switch(type) {
411 case TASK_TRIGGER_DAILY:
412 return DailyTrigger_create(trigger);
413 default:
414 FIXME("Unimplemented type %d\n", type);
415 return E_NOTIMPL;
418 return S_OK;
421 static HRESULT WINAPI TriggerCollection_Remove(ITriggerCollection *iface, VARIANT index)
423 trigger_collection *This = impl_from_ITriggerCollection(iface);
424 FIXME("(%p)->(%s)\n", This, debugstr_variant(&index));
425 return E_NOTIMPL;
428 static HRESULT WINAPI TriggerCollection_Clear(ITriggerCollection *iface)
430 trigger_collection *This = impl_from_ITriggerCollection(iface);
431 FIXME("(%p)\n", This);
432 return E_NOTIMPL;
435 static const ITriggerCollectionVtbl TriggerCollection_vtbl = {
436 TriggerCollection_QueryInterface,
437 TriggerCollection_AddRef,
438 TriggerCollection_Release,
439 TriggerCollection_GetTypeInfoCount,
440 TriggerCollection_GetTypeInfo,
441 TriggerCollection_GetIDsOfNames,
442 TriggerCollection_Invoke,
443 TriggerCollection_get_Count,
444 TriggerCollection_get_Item,
445 TriggerCollection_get__NewEnum,
446 TriggerCollection_Create,
447 TriggerCollection_Remove,
448 TriggerCollection_Clear
451 typedef struct
453 IRegistrationInfo IRegistrationInfo_iface;
454 LONG ref;
455 WCHAR *description, *author, *version, *date, *documentation, *uri, *source;
456 } registration_info;
458 static inline registration_info *impl_from_IRegistrationInfo(IRegistrationInfo *iface)
460 return CONTAINING_RECORD(iface, registration_info, IRegistrationInfo_iface);
463 static ULONG WINAPI RegistrationInfo_AddRef(IRegistrationInfo *iface)
465 registration_info *reginfo = impl_from_IRegistrationInfo(iface);
466 return InterlockedIncrement(&reginfo->ref);
469 static ULONG WINAPI RegistrationInfo_Release(IRegistrationInfo *iface)
471 registration_info *reginfo = impl_from_IRegistrationInfo(iface);
472 LONG ref = InterlockedDecrement(&reginfo->ref);
474 if (!ref)
476 TRACE("destroying %p\n", iface);
477 heap_free(reginfo->description);
478 heap_free(reginfo->author);
479 heap_free(reginfo->version);
480 heap_free(reginfo->date);
481 heap_free(reginfo->documentation);
482 heap_free(reginfo->uri);
483 heap_free(reginfo->source);
484 heap_free(reginfo);
487 return ref;
490 static HRESULT WINAPI RegistrationInfo_QueryInterface(IRegistrationInfo *iface, REFIID riid, void **obj)
492 if (!riid || !obj) return E_INVALIDARG;
494 TRACE("%p,%s,%p\n", iface, debugstr_guid(riid), obj);
496 if (IsEqualGUID(riid, &IID_IRegistrationInfo) ||
497 IsEqualGUID(riid, &IID_IDispatch) ||
498 IsEqualGUID(riid, &IID_IUnknown))
500 IRegistrationInfo_AddRef(iface);
501 *obj = iface;
502 return S_OK;
505 FIXME("interface %s is not implemented\n", debugstr_guid(riid));
506 *obj = NULL;
507 return E_NOINTERFACE;
510 static HRESULT WINAPI RegistrationInfo_GetTypeInfoCount(IRegistrationInfo *iface, UINT *count)
512 FIXME("%p,%p: stub\n", iface, count);
513 return E_NOTIMPL;
516 static HRESULT WINAPI RegistrationInfo_GetTypeInfo(IRegistrationInfo *iface, UINT index, LCID lcid, ITypeInfo **info)
518 FIXME("%p,%u,%u,%p: stub\n", iface, index, lcid, info);
519 return E_NOTIMPL;
522 static HRESULT WINAPI RegistrationInfo_GetIDsOfNames(IRegistrationInfo *iface, REFIID riid, LPOLESTR *names,
523 UINT count, LCID lcid, DISPID *dispid)
525 FIXME("%p,%s,%p,%u,%u,%p: stub\n", iface, debugstr_guid(riid), names, count, lcid, dispid);
526 return E_NOTIMPL;
529 static HRESULT WINAPI RegistrationInfo_Invoke(IRegistrationInfo *iface, DISPID dispid, REFIID riid, LCID lcid, WORD flags,
530 DISPPARAMS *params, VARIANT *result, EXCEPINFO *excepinfo, UINT *argerr)
532 FIXME("%p,%d,%s,%04x,%04x,%p,%p,%p,%p: stub\n", iface, dispid, debugstr_guid(riid), lcid, flags,
533 params, result, excepinfo, argerr);
534 return E_NOTIMPL;
537 static HRESULT WINAPI RegistrationInfo_get_Description(IRegistrationInfo *iface, BSTR *description)
539 registration_info *reginfo = impl_from_IRegistrationInfo(iface);
541 TRACE("%p,%p\n", iface, description);
543 if (!description) return E_POINTER;
545 *description = SysAllocString(reginfo->description);
546 return S_OK;
549 static HRESULT WINAPI RegistrationInfo_put_Description(IRegistrationInfo *iface, BSTR description)
551 registration_info *reginfo = impl_from_IRegistrationInfo(iface);
553 TRACE("%p,%s\n", iface, debugstr_w(description));
555 if (!description) return E_INVALIDARG;
557 heap_free(reginfo->description);
558 reginfo->description = heap_strdupW(description);
559 /* FIXME: update XML on the server side */
560 return reginfo->description ? S_OK : E_OUTOFMEMORY;
563 static HRESULT WINAPI RegistrationInfo_get_Author(IRegistrationInfo *iface, BSTR *author)
565 registration_info *reginfo = impl_from_IRegistrationInfo(iface);
567 TRACE("%p,%p\n", iface, author);
569 if (!author) return E_POINTER;
571 *author = SysAllocString(reginfo->author);
572 return S_OK;
575 static HRESULT WINAPI RegistrationInfo_put_Author(IRegistrationInfo *iface, BSTR author)
577 registration_info *reginfo = impl_from_IRegistrationInfo(iface);
579 TRACE("%p,%s\n", iface, debugstr_w(author));
581 if (!author) return E_INVALIDARG;
583 heap_free(reginfo->author);
584 reginfo->author = heap_strdupW(author);
585 /* FIXME: update XML on the server side */
586 return reginfo->author ? S_OK : E_OUTOFMEMORY;
589 static HRESULT WINAPI RegistrationInfo_get_Version(IRegistrationInfo *iface, BSTR *version)
591 registration_info *reginfo = impl_from_IRegistrationInfo(iface);
593 TRACE("%p,%p\n", iface, version);
595 if (!version) return E_POINTER;
597 *version = SysAllocString(reginfo->version);
598 return S_OK;
601 static HRESULT WINAPI RegistrationInfo_put_Version(IRegistrationInfo *iface, BSTR version)
603 registration_info *reginfo = impl_from_IRegistrationInfo(iface);
605 TRACE("%p,%s\n", iface, debugstr_w(version));
607 if (!version) return E_INVALIDARG;
609 heap_free(reginfo->version);
610 reginfo->version = heap_strdupW(version);
611 /* FIXME: update XML on the server side */
612 return reginfo->version ? S_OK : E_OUTOFMEMORY;
615 static HRESULT WINAPI RegistrationInfo_get_Date(IRegistrationInfo *iface, BSTR *date)
617 registration_info *reginfo = impl_from_IRegistrationInfo(iface);
619 TRACE("%p,%p\n", iface, date);
621 if (!date) return E_POINTER;
623 *date = SysAllocString(reginfo->date);
624 return S_OK;
627 static HRESULT WINAPI RegistrationInfo_put_Date(IRegistrationInfo *iface, BSTR date)
629 registration_info *reginfo = impl_from_IRegistrationInfo(iface);
631 TRACE("%p,%s\n", iface, debugstr_w(date));
633 if (!date) return E_INVALIDARG;
635 heap_free(reginfo->date);
636 reginfo->date = heap_strdupW(date);
637 /* FIXME: update XML on the server side */
638 return reginfo->date ? S_OK : E_OUTOFMEMORY;
641 static HRESULT WINAPI RegistrationInfo_get_Documentation(IRegistrationInfo *iface, BSTR *doc)
643 registration_info *reginfo = impl_from_IRegistrationInfo(iface);
645 TRACE("%p,%p\n", iface, doc);
647 if (!doc) return E_POINTER;
649 *doc = SysAllocString(reginfo->documentation);
650 return S_OK;
653 static HRESULT WINAPI RegistrationInfo_put_Documentation(IRegistrationInfo *iface, BSTR doc)
655 registration_info *reginfo = impl_from_IRegistrationInfo(iface);
657 TRACE("%p,%s\n", iface, debugstr_w(doc));
659 if (!doc) return E_INVALIDARG;
661 heap_free(reginfo->documentation);
662 reginfo->documentation = heap_strdupW(doc);
663 /* FIXME: update XML on the server side */
664 return reginfo->documentation ? S_OK : E_OUTOFMEMORY;
667 static HRESULT WINAPI RegistrationInfo_get_XmlText(IRegistrationInfo *iface, BSTR *xml)
669 FIXME("%p,%p: stub\n", iface, xml);
670 return E_NOTIMPL;
673 static HRESULT WINAPI RegistrationInfo_put_XmlText(IRegistrationInfo *iface, BSTR xml)
675 FIXME("%p,%s: stub\n", iface, debugstr_w(xml));
676 return E_NOTIMPL;
679 static HRESULT WINAPI RegistrationInfo_get_URI(IRegistrationInfo *iface, BSTR *uri)
681 registration_info *reginfo = impl_from_IRegistrationInfo(iface);
683 TRACE("%p,%p\n", iface, uri);
685 if (!uri) return E_POINTER;
687 *uri = SysAllocString(reginfo->uri);
688 return S_OK;
691 static HRESULT WINAPI RegistrationInfo_put_URI(IRegistrationInfo *iface, BSTR uri)
693 registration_info *reginfo = impl_from_IRegistrationInfo(iface);
695 TRACE("%p,%s\n", iface, debugstr_w(uri));
697 if (!uri) return E_INVALIDARG;
699 heap_free(reginfo->uri);
700 reginfo->uri = heap_strdupW(uri);
701 /* FIXME: update XML on the server side */
702 return reginfo->uri ? S_OK : E_OUTOFMEMORY;
705 static HRESULT WINAPI RegistrationInfo_get_SecurityDescriptor(IRegistrationInfo *iface, VARIANT *sddl)
707 FIXME("%p,%p: stub\n", iface, sddl);
708 return E_NOTIMPL;
711 static HRESULT WINAPI RegistrationInfo_put_SecurityDescriptor(IRegistrationInfo *iface, VARIANT sddl)
713 FIXME("%p,%s: stub\n", iface, debugstr_variant(&sddl));
714 return S_OK;
717 static HRESULT WINAPI RegistrationInfo_get_Source(IRegistrationInfo *iface, BSTR *source)
719 registration_info *reginfo = impl_from_IRegistrationInfo(iface);
721 TRACE("%p,%p\n", iface, source);
723 if (!source) return E_POINTER;
725 *source = SysAllocString(reginfo->source);
726 return S_OK;
729 static HRESULT WINAPI RegistrationInfo_put_Source(IRegistrationInfo *iface, BSTR source)
731 registration_info *reginfo = impl_from_IRegistrationInfo(iface);
733 TRACE("%p,%s\n", iface, debugstr_w(source));
735 if (!source) return E_INVALIDARG;
737 heap_free(reginfo->source);
738 reginfo->source = heap_strdupW(source);
739 /* FIXME: update XML on the server side */
740 return reginfo->source ? S_OK : E_OUTOFMEMORY;
743 static const IRegistrationInfoVtbl RegistrationInfo_vtbl =
745 RegistrationInfo_QueryInterface,
746 RegistrationInfo_AddRef,
747 RegistrationInfo_Release,
748 RegistrationInfo_GetTypeInfoCount,
749 RegistrationInfo_GetTypeInfo,
750 RegistrationInfo_GetIDsOfNames,
751 RegistrationInfo_Invoke,
752 RegistrationInfo_get_Description,
753 RegistrationInfo_put_Description,
754 RegistrationInfo_get_Author,
755 RegistrationInfo_put_Author,
756 RegistrationInfo_get_Version,
757 RegistrationInfo_put_Version,
758 RegistrationInfo_get_Date,
759 RegistrationInfo_put_Date,
760 RegistrationInfo_get_Documentation,
761 RegistrationInfo_put_Documentation,
762 RegistrationInfo_get_XmlText,
763 RegistrationInfo_put_XmlText,
764 RegistrationInfo_get_URI,
765 RegistrationInfo_put_URI,
766 RegistrationInfo_get_SecurityDescriptor,
767 RegistrationInfo_put_SecurityDescriptor,
768 RegistrationInfo_get_Source,
769 RegistrationInfo_put_Source
772 static HRESULT RegistrationInfo_create(IRegistrationInfo **obj)
774 registration_info *reginfo;
776 reginfo = heap_alloc_zero(sizeof(*reginfo));
777 if (!reginfo) return E_OUTOFMEMORY;
779 reginfo->IRegistrationInfo_iface.lpVtbl = &RegistrationInfo_vtbl;
780 reginfo->ref = 1;
781 *obj = &reginfo->IRegistrationInfo_iface;
783 TRACE("created %p\n", *obj);
785 return S_OK;
788 typedef struct
790 ITaskSettings ITaskSettings_iface;
791 LONG ref;
792 WCHAR *restart_interval;
793 WCHAR *execution_time_limit;
794 WCHAR *delete_expired_task_after;
795 int restart_count;
796 int priority;
797 TASK_INSTANCES_POLICY policy;
798 TASK_COMPATIBILITY compatibility;
799 BOOL allow_on_demand_start;
800 BOOL stop_if_going_on_batteries;
801 BOOL disallow_start_if_on_batteries;
802 BOOL allow_hard_terminate;
803 BOOL start_when_available;
804 BOOL run_only_if_network_available;
805 BOOL enabled;
806 BOOL hidden;
807 BOOL run_only_if_idle;
808 BOOL wake_to_run;
809 } TaskSettings;
811 static inline TaskSettings *impl_from_ITaskSettings(ITaskSettings *iface)
813 return CONTAINING_RECORD(iface, TaskSettings, ITaskSettings_iface);
816 static ULONG WINAPI TaskSettings_AddRef(ITaskSettings *iface)
818 TaskSettings *taskset = impl_from_ITaskSettings(iface);
819 return InterlockedIncrement(&taskset->ref);
822 static ULONG WINAPI TaskSettings_Release(ITaskSettings *iface)
824 TaskSettings *taskset = impl_from_ITaskSettings(iface);
825 LONG ref = InterlockedDecrement(&taskset->ref);
827 if (!ref)
829 TRACE("destroying %p\n", iface);
830 heap_free(taskset->restart_interval);
831 heap_free(taskset->execution_time_limit);
832 heap_free(taskset->delete_expired_task_after);
833 heap_free(taskset);
836 return ref;
839 static HRESULT WINAPI TaskSettings_QueryInterface(ITaskSettings *iface, REFIID riid, void **obj)
841 if (!riid || !obj) return E_INVALIDARG;
843 TRACE("%p,%s,%p\n", iface, debugstr_guid(riid), obj);
845 if (IsEqualGUID(riid, &IID_ITaskSettings) ||
846 IsEqualGUID(riid, &IID_IDispatch) ||
847 IsEqualGUID(riid, &IID_IUnknown))
849 ITaskSettings_AddRef(iface);
850 *obj = iface;
851 return S_OK;
854 FIXME("interface %s is not implemented\n", debugstr_guid(riid));
855 *obj = NULL;
856 return E_NOINTERFACE;
859 static HRESULT WINAPI TaskSettings_GetTypeInfoCount(ITaskSettings *iface, UINT *count)
861 FIXME("%p,%p: stub\n", iface, count);
862 return E_NOTIMPL;
865 static HRESULT WINAPI TaskSettings_GetTypeInfo(ITaskSettings *iface, UINT index, LCID lcid, ITypeInfo **info)
867 FIXME("%p,%u,%u,%p: stub\n", iface, index, lcid, info);
868 return E_NOTIMPL;
871 static HRESULT WINAPI TaskSettings_GetIDsOfNames(ITaskSettings *iface, REFIID riid, LPOLESTR *names,
872 UINT count, LCID lcid, DISPID *dispid)
874 FIXME("%p,%s,%p,%u,%u,%p: stub\n", iface, debugstr_guid(riid), names, count, lcid, dispid);
875 return E_NOTIMPL;
878 static HRESULT WINAPI TaskSettings_Invoke(ITaskSettings *iface, DISPID dispid, REFIID riid, LCID lcid, WORD flags,
879 DISPPARAMS *params, VARIANT *result, EXCEPINFO *excepinfo, UINT *argerr)
881 FIXME("%p,%d,%s,%04x,%04x,%p,%p,%p,%p: stub\n", iface, dispid, debugstr_guid(riid), lcid, flags,
882 params, result, excepinfo, argerr);
883 return E_NOTIMPL;
886 static HRESULT WINAPI TaskSettings_get_AllowDemandStart(ITaskSettings *iface, VARIANT_BOOL *allow)
888 TaskSettings *taskset = impl_from_ITaskSettings(iface);
890 TRACE("%p,%p\n", iface, allow);
892 if (!allow) return E_POINTER;
894 *allow = taskset->allow_on_demand_start ? VARIANT_TRUE : VARIANT_FALSE;
896 return S_OK;
899 static HRESULT WINAPI TaskSettings_put_AllowDemandStart(ITaskSettings *iface, VARIANT_BOOL allow)
901 FIXME("%p,%d: stub\n", iface, allow);
902 return E_NOTIMPL;
905 static HRESULT WINAPI TaskSettings_get_RestartInterval(ITaskSettings *iface, BSTR *interval)
907 TaskSettings *taskset = impl_from_ITaskSettings(iface);
909 TRACE("%p,%p\n", iface, interval);
911 if (!interval) return E_POINTER;
913 if (!taskset->restart_interval)
915 *interval = NULL;
916 return S_OK;
919 *interval = SysAllocString(taskset->restart_interval);
920 if (!*interval) return E_OUTOFMEMORY;
922 return S_OK;
925 static HRESULT WINAPI TaskSettings_put_RestartInterval(ITaskSettings *iface, BSTR interval)
927 TaskSettings *taskset = impl_from_ITaskSettings(iface);
928 WCHAR *str = NULL;
930 TRACE("%p,%s\n", iface, debugstr_w(interval));
932 if (interval && !(str = heap_strdupW(interval))) return E_OUTOFMEMORY;
933 heap_free(taskset->restart_interval);
934 taskset->restart_interval = str;
936 return S_OK;
939 static HRESULT WINAPI TaskSettings_get_RestartCount(ITaskSettings *iface, INT *count)
941 TaskSettings *taskset = impl_from_ITaskSettings(iface);
943 TRACE("%p,%p\n", iface, count);
945 if (!count) return E_POINTER;
947 *count = taskset->restart_count;
949 return S_OK;
952 static HRESULT WINAPI TaskSettings_put_RestartCount(ITaskSettings *iface, INT count)
954 TaskSettings *taskset = impl_from_ITaskSettings(iface);
956 TRACE("%p,%d\n", iface, count);
958 taskset->restart_count = count;
960 return S_OK;
963 static HRESULT WINAPI TaskSettings_get_MultipleInstances(ITaskSettings *iface, TASK_INSTANCES_POLICY *policy)
965 TaskSettings *taskset = impl_from_ITaskSettings(iface);
967 TRACE("%p,%p\n", iface, policy);
969 if (!policy) return E_POINTER;
971 *policy = taskset->policy;
973 return S_OK;
976 static HRESULT WINAPI TaskSettings_put_MultipleInstances(ITaskSettings *iface, TASK_INSTANCES_POLICY policy)
978 TaskSettings *taskset = impl_from_ITaskSettings(iface);
980 TRACE("%p,%d\n", iface, policy);
982 taskset->policy = policy;
984 return S_OK;
987 static HRESULT WINAPI TaskSettings_get_StopIfGoingOnBatteries(ITaskSettings *iface, VARIANT_BOOL *stop)
989 TaskSettings *taskset = impl_from_ITaskSettings(iface);
991 TRACE("%p,%p\n", iface, stop);
993 if (!stop) return E_POINTER;
995 *stop = taskset->stop_if_going_on_batteries ? VARIANT_TRUE : VARIANT_FALSE;
997 return S_OK;
1000 static HRESULT WINAPI TaskSettings_put_StopIfGoingOnBatteries(ITaskSettings *iface, VARIANT_BOOL stop)
1002 TaskSettings *taskset = impl_from_ITaskSettings(iface);
1004 TRACE("%p,%d\n", iface, stop);
1006 taskset->stop_if_going_on_batteries = stop ? TRUE : FALSE;
1008 return S_OK;
1011 static HRESULT WINAPI TaskSettings_get_DisallowStartIfOnBatteries(ITaskSettings *iface, VARIANT_BOOL *disallow)
1013 TaskSettings *taskset = impl_from_ITaskSettings(iface);
1015 TRACE("%p,%p\n", iface, disallow);
1017 if (!disallow) return E_POINTER;
1019 *disallow = taskset->disallow_start_if_on_batteries ? VARIANT_TRUE : VARIANT_FALSE;
1021 return S_OK;
1024 static HRESULT WINAPI TaskSettings_put_DisallowStartIfOnBatteries(ITaskSettings *iface, VARIANT_BOOL disallow)
1026 TaskSettings *taskset = impl_from_ITaskSettings(iface);
1028 TRACE("%p,%d\n", iface, disallow);
1030 taskset->disallow_start_if_on_batteries = disallow ? TRUE : FALSE;
1032 return S_OK;
1035 static HRESULT WINAPI TaskSettings_get_AllowHardTerminate(ITaskSettings *iface, VARIANT_BOOL *allow)
1037 TaskSettings *taskset = impl_from_ITaskSettings(iface);
1039 TRACE("%p,%p\n", iface, allow);
1041 if (!allow) return E_POINTER;
1043 *allow = taskset->allow_hard_terminate ? VARIANT_TRUE : VARIANT_FALSE;
1045 return S_OK;
1048 static HRESULT WINAPI TaskSettings_put_AllowHardTerminate(ITaskSettings *iface, VARIANT_BOOL allow)
1050 TaskSettings *taskset = impl_from_ITaskSettings(iface);
1052 TRACE("%p,%d\n", iface, allow);
1054 taskset->allow_hard_terminate = allow ? TRUE : FALSE;
1056 return S_OK;
1059 static HRESULT WINAPI TaskSettings_get_StartWhenAvailable(ITaskSettings *iface, VARIANT_BOOL *start)
1061 TaskSettings *taskset = impl_from_ITaskSettings(iface);
1063 TRACE("%p,%p\n", iface, start);
1065 if (!start) return E_POINTER;
1067 *start = taskset->start_when_available ? VARIANT_TRUE : VARIANT_FALSE;
1069 return S_OK;
1072 static HRESULT WINAPI TaskSettings_put_StartWhenAvailable(ITaskSettings *iface, VARIANT_BOOL start)
1074 TaskSettings *taskset = impl_from_ITaskSettings(iface);
1076 TRACE("%p,%d\n", iface, start);
1078 taskset->start_when_available = start ? TRUE : FALSE;
1080 return S_OK;
1083 static HRESULT WINAPI TaskSettings_get_XmlText(ITaskSettings *iface, BSTR *xml)
1085 FIXME("%p,%p: stub\n", iface, xml);
1086 return E_NOTIMPL;
1089 static HRESULT WINAPI TaskSettings_put_XmlText(ITaskSettings *iface, BSTR xml)
1091 FIXME("%p,%s: stub\n", iface, debugstr_w(xml));
1092 return E_NOTIMPL;
1095 static HRESULT WINAPI TaskSettings_get_RunOnlyIfNetworkAvailable(ITaskSettings *iface, VARIANT_BOOL *run)
1097 TaskSettings *taskset = impl_from_ITaskSettings(iface);
1099 TRACE("%p,%p\n", iface, run);
1101 if (!run) return E_POINTER;
1103 *run = taskset->run_only_if_network_available ? VARIANT_TRUE : VARIANT_FALSE;
1105 return S_OK;
1108 static HRESULT WINAPI TaskSettings_put_RunOnlyIfNetworkAvailable(ITaskSettings *iface, VARIANT_BOOL run)
1110 TaskSettings *taskset = impl_from_ITaskSettings(iface);
1112 TRACE("%p,%d\n", iface, run);
1114 taskset->run_only_if_network_available = run ? TRUE : FALSE;
1116 return S_OK;
1119 static HRESULT WINAPI TaskSettings_get_ExecutionTimeLimit(ITaskSettings *iface, BSTR *limit)
1121 TaskSettings *taskset = impl_from_ITaskSettings(iface);
1123 TRACE("%p,%p\n", iface, limit);
1125 if (!limit) return E_POINTER;
1127 if (!taskset->execution_time_limit)
1129 *limit = NULL;
1130 return S_OK;
1133 *limit = SysAllocString(taskset->execution_time_limit);
1134 if (!*limit) return E_OUTOFMEMORY;
1136 return S_OK;
1139 static HRESULT WINAPI TaskSettings_put_ExecutionTimeLimit(ITaskSettings *iface, BSTR limit)
1141 TaskSettings *taskset = impl_from_ITaskSettings(iface);
1142 WCHAR *str = NULL;
1144 TRACE("%p,%s\n", iface, debugstr_w(limit));
1146 if (limit && !(str = heap_strdupW(limit))) return E_OUTOFMEMORY;
1147 heap_free(taskset->execution_time_limit);
1148 taskset->execution_time_limit = str;
1150 return S_OK;
1153 static HRESULT WINAPI TaskSettings_get_Enabled(ITaskSettings *iface, VARIANT_BOOL *enabled)
1155 TaskSettings *taskset = impl_from_ITaskSettings(iface);
1157 TRACE("%p,%p\n", iface, enabled);
1159 if (!enabled) return E_POINTER;
1161 *enabled = taskset->enabled ? VARIANT_TRUE : VARIANT_FALSE;
1163 return S_OK;
1166 static HRESULT WINAPI TaskSettings_put_Enabled(ITaskSettings *iface, VARIANT_BOOL enabled)
1168 TaskSettings *taskset = impl_from_ITaskSettings(iface);
1170 TRACE("%p,%d\n", iface, enabled);
1172 taskset->enabled = enabled ? TRUE : FALSE;
1174 return S_OK;
1177 static HRESULT WINAPI TaskSettings_get_DeleteExpiredTaskAfter(ITaskSettings *iface, BSTR *delay)
1179 TaskSettings *taskset = impl_from_ITaskSettings(iface);
1181 TRACE("%p,%p\n", iface, delay);
1183 if (!delay) return E_POINTER;
1185 if (!taskset->delete_expired_task_after)
1187 *delay = NULL;
1188 return S_OK;
1191 *delay = SysAllocString(taskset->delete_expired_task_after);
1192 if (!*delay) return E_OUTOFMEMORY;
1194 return S_OK;
1197 static HRESULT WINAPI TaskSettings_put_DeleteExpiredTaskAfter(ITaskSettings *iface, BSTR delay)
1199 TaskSettings *taskset = impl_from_ITaskSettings(iface);
1200 WCHAR *str = NULL;
1202 TRACE("%p,%s\n", iface, debugstr_w(delay));
1204 if (delay && !(str = heap_strdupW(delay))) return E_OUTOFMEMORY;
1205 heap_free(taskset->delete_expired_task_after);
1206 taskset->delete_expired_task_after = str;
1208 return S_OK;
1211 static HRESULT WINAPI TaskSettings_get_Priority(ITaskSettings *iface, INT *priority)
1213 TaskSettings *taskset = impl_from_ITaskSettings(iface);
1215 TRACE("%p,%p\n", iface, priority);
1217 if (!priority) return E_POINTER;
1219 *priority = taskset->priority;
1221 return S_OK;
1224 static HRESULT WINAPI TaskSettings_put_Priority(ITaskSettings *iface, INT priority)
1226 TaskSettings *taskset = impl_from_ITaskSettings(iface);
1228 TRACE("%p,%d\n", iface, priority);
1230 taskset->priority = priority;
1232 return S_OK;
1235 static HRESULT WINAPI TaskSettings_get_Compatibility(ITaskSettings *iface, TASK_COMPATIBILITY *level)
1237 TaskSettings *taskset = impl_from_ITaskSettings(iface);
1239 TRACE("%p,%p\n", iface, level);
1241 if (!level) return E_POINTER;
1243 *level = taskset->compatibility;
1245 return S_OK;
1248 static HRESULT WINAPI TaskSettings_put_Compatibility(ITaskSettings *iface, TASK_COMPATIBILITY level)
1250 FIXME("%p,%d: stub\n", iface, level);
1251 return E_NOTIMPL;
1254 static HRESULT WINAPI TaskSettings_get_Hidden(ITaskSettings *iface, VARIANT_BOOL *hidden)
1256 TaskSettings *taskset = impl_from_ITaskSettings(iface);
1258 TRACE("%p,%p\n", iface, hidden);
1260 if (!hidden) return E_POINTER;
1262 *hidden = taskset->hidden ? VARIANT_TRUE : VARIANT_FALSE;
1264 return S_OK;
1267 static HRESULT WINAPI TaskSettings_put_Hidden(ITaskSettings *iface, VARIANT_BOOL hidden)
1269 FIXME("%p,%d: stub\n", iface, hidden);
1270 return E_NOTIMPL;
1273 static HRESULT WINAPI TaskSettings_get_IdleSettings(ITaskSettings *iface, IIdleSettings **settings)
1275 FIXME("%p,%p: stub\n", iface, settings);
1276 return E_NOTIMPL;
1279 static HRESULT WINAPI TaskSettings_put_IdleSettings(ITaskSettings *iface, IIdleSettings *settings)
1281 FIXME("%p,%p: stub\n", iface, settings);
1282 return E_NOTIMPL;
1285 static HRESULT WINAPI TaskSettings_get_RunOnlyIfIdle(ITaskSettings *iface, VARIANT_BOOL *run)
1287 TaskSettings *taskset = impl_from_ITaskSettings(iface);
1289 TRACE("%p,%p\n", iface, run);
1291 if (!run) return E_POINTER;
1293 *run = taskset->run_only_if_idle ? VARIANT_TRUE : VARIANT_FALSE;
1295 return S_OK;
1298 static HRESULT WINAPI TaskSettings_put_RunOnlyIfIdle(ITaskSettings *iface, VARIANT_BOOL run)
1300 FIXME("%p,%d: stub\n", iface, run);
1301 return E_NOTIMPL;
1304 static HRESULT WINAPI TaskSettings_get_WakeToRun(ITaskSettings *iface, VARIANT_BOOL *wake)
1306 TaskSettings *taskset = impl_from_ITaskSettings(iface);
1308 TRACE("%p,%p\n", iface, wake);
1310 if (!wake) return E_POINTER;
1312 *wake = taskset->wake_to_run ? VARIANT_TRUE : VARIANT_FALSE;
1314 return S_OK;
1317 static HRESULT WINAPI TaskSettings_put_WakeToRun(ITaskSettings *iface, VARIANT_BOOL wake)
1319 FIXME("%p,%d: stub\n", iface, wake);
1320 return E_NOTIMPL;
1323 static HRESULT WINAPI TaskSettings_get_NetworkSettings(ITaskSettings *iface, INetworkSettings **settings)
1325 FIXME("%p,%p: stub\n", iface, settings);
1326 return E_NOTIMPL;
1329 static HRESULT WINAPI TaskSettings_put_NetworkSettings(ITaskSettings *iface, INetworkSettings *settings)
1331 FIXME("%p,%p: stub\n", iface, settings);
1332 return E_NOTIMPL;
1335 static const ITaskSettingsVtbl TaskSettings_vtbl =
1337 TaskSettings_QueryInterface,
1338 TaskSettings_AddRef,
1339 TaskSettings_Release,
1340 TaskSettings_GetTypeInfoCount,
1341 TaskSettings_GetTypeInfo,
1342 TaskSettings_GetIDsOfNames,
1343 TaskSettings_Invoke,
1344 TaskSettings_get_AllowDemandStart,
1345 TaskSettings_put_AllowDemandStart,
1346 TaskSettings_get_RestartInterval,
1347 TaskSettings_put_RestartInterval,
1348 TaskSettings_get_RestartCount,
1349 TaskSettings_put_RestartCount,
1350 TaskSettings_get_MultipleInstances,
1351 TaskSettings_put_MultipleInstances,
1352 TaskSettings_get_StopIfGoingOnBatteries,
1353 TaskSettings_put_StopIfGoingOnBatteries,
1354 TaskSettings_get_DisallowStartIfOnBatteries,
1355 TaskSettings_put_DisallowStartIfOnBatteries,
1356 TaskSettings_get_AllowHardTerminate,
1357 TaskSettings_put_AllowHardTerminate,
1358 TaskSettings_get_StartWhenAvailable,
1359 TaskSettings_put_StartWhenAvailable,
1360 TaskSettings_get_XmlText,
1361 TaskSettings_put_XmlText,
1362 TaskSettings_get_RunOnlyIfNetworkAvailable,
1363 TaskSettings_put_RunOnlyIfNetworkAvailable,
1364 TaskSettings_get_ExecutionTimeLimit,
1365 TaskSettings_put_ExecutionTimeLimit,
1366 TaskSettings_get_Enabled,
1367 TaskSettings_put_Enabled,
1368 TaskSettings_get_DeleteExpiredTaskAfter,
1369 TaskSettings_put_DeleteExpiredTaskAfter,
1370 TaskSettings_get_Priority,
1371 TaskSettings_put_Priority,
1372 TaskSettings_get_Compatibility,
1373 TaskSettings_put_Compatibility,
1374 TaskSettings_get_Hidden,
1375 TaskSettings_put_Hidden,
1376 TaskSettings_get_IdleSettings,
1377 TaskSettings_put_IdleSettings,
1378 TaskSettings_get_RunOnlyIfIdle,
1379 TaskSettings_put_RunOnlyIfIdle,
1380 TaskSettings_get_WakeToRun,
1381 TaskSettings_put_WakeToRun,
1382 TaskSettings_get_NetworkSettings,
1383 TaskSettings_put_NetworkSettings
1386 static HRESULT TaskSettings_create(ITaskSettings **obj)
1388 static const WCHAR exec_time_limit[] = { 'P','T','7','2','H',0 };
1389 TaskSettings *taskset;
1391 taskset = heap_alloc(sizeof(*taskset));
1392 if (!taskset) return E_OUTOFMEMORY;
1394 taskset->ITaskSettings_iface.lpVtbl = &TaskSettings_vtbl;
1395 taskset->ref = 1;
1396 /* set the defaults */
1397 taskset->restart_interval = NULL;
1398 taskset->execution_time_limit = heap_strdupW(exec_time_limit);
1399 taskset->delete_expired_task_after = NULL;
1400 taskset->restart_count = 0;
1401 taskset->priority = 7;
1402 taskset->policy = TASK_INSTANCES_IGNORE_NEW;
1403 taskset->compatibility = TASK_COMPATIBILITY_V2;
1404 taskset->allow_on_demand_start = TRUE;
1405 taskset->stop_if_going_on_batteries = TRUE;
1406 taskset->disallow_start_if_on_batteries = TRUE;
1407 taskset->allow_hard_terminate = TRUE;
1408 taskset->start_when_available = FALSE;
1409 taskset->run_only_if_network_available = FALSE;
1410 taskset->enabled = TRUE;
1411 taskset->hidden = FALSE;
1412 taskset->run_only_if_idle = FALSE;
1413 taskset->wake_to_run = FALSE;
1415 *obj = &taskset->ITaskSettings_iface;
1417 TRACE("created %p\n", *obj);
1419 return S_OK;
1422 typedef struct
1424 ITaskDefinition ITaskDefinition_iface;
1425 LONG ref;
1426 IRegistrationInfo *reginfo;
1427 ITaskSettings *taskset;
1428 ITriggerCollection *triggers;
1429 IPrincipal *principal;
1430 IActionCollection *actions;
1431 } TaskDefinition;
1433 static inline TaskDefinition *impl_from_ITaskDefinition(ITaskDefinition *iface)
1435 return CONTAINING_RECORD(iface, TaskDefinition, ITaskDefinition_iface);
1438 static ULONG WINAPI TaskDefinition_AddRef(ITaskDefinition *iface)
1440 TaskDefinition *taskdef = impl_from_ITaskDefinition(iface);
1441 return InterlockedIncrement(&taskdef->ref);
1444 static ULONG WINAPI TaskDefinition_Release(ITaskDefinition *iface)
1446 TaskDefinition *taskdef = impl_from_ITaskDefinition(iface);
1447 LONG ref = InterlockedDecrement(&taskdef->ref);
1449 if (!ref)
1451 TRACE("destroying %p\n", iface);
1453 if (taskdef->reginfo)
1454 IRegistrationInfo_Release(taskdef->reginfo);
1455 if (taskdef->taskset)
1456 ITaskSettings_Release(taskdef->taskset);
1457 if (taskdef->triggers)
1458 ITriggerCollection_Release(taskdef->triggers);
1459 if (taskdef->principal)
1460 IPrincipal_Release(taskdef->principal);
1461 if (taskdef->actions)
1462 IActionCollection_Release(taskdef->actions);
1464 heap_free(taskdef);
1467 return ref;
1470 static HRESULT WINAPI TaskDefinition_QueryInterface(ITaskDefinition *iface, REFIID riid, void **obj)
1472 if (!riid || !obj) return E_INVALIDARG;
1474 TRACE("%p,%s,%p\n", iface, debugstr_guid(riid), obj);
1476 if (IsEqualGUID(riid, &IID_ITaskDefinition) ||
1477 IsEqualGUID(riid, &IID_IDispatch) ||
1478 IsEqualGUID(riid, &IID_IUnknown))
1480 ITaskDefinition_AddRef(iface);
1481 *obj = iface;
1482 return S_OK;
1485 FIXME("interface %s is not implemented\n", debugstr_guid(riid));
1486 *obj = NULL;
1487 return E_NOINTERFACE;
1490 static HRESULT WINAPI TaskDefinition_GetTypeInfoCount(ITaskDefinition *iface, UINT *count)
1492 FIXME("%p,%p: stub\n", iface, count);
1493 return E_NOTIMPL;
1496 static HRESULT WINAPI TaskDefinition_GetTypeInfo(ITaskDefinition *iface, UINT index, LCID lcid, ITypeInfo **info)
1498 FIXME("%p,%u,%u,%p: stub\n", iface, index, lcid, info);
1499 return E_NOTIMPL;
1502 static HRESULT WINAPI TaskDefinition_GetIDsOfNames(ITaskDefinition *iface, REFIID riid, LPOLESTR *names,
1503 UINT count, LCID lcid, DISPID *dispid)
1505 FIXME("%p,%s,%p,%u,%u,%p: stub\n", iface, debugstr_guid(riid), names, count, lcid, dispid);
1506 return E_NOTIMPL;
1509 static HRESULT WINAPI TaskDefinition_Invoke(ITaskDefinition *iface, DISPID dispid, REFIID riid, LCID lcid, WORD flags,
1510 DISPPARAMS *params, VARIANT *result, EXCEPINFO *excepinfo, UINT *argerr)
1512 FIXME("%p,%d,%s,%04x,%04x,%p,%p,%p,%p: stub\n", iface, dispid, debugstr_guid(riid), lcid, flags,
1513 params, result, excepinfo, argerr);
1514 return E_NOTIMPL;
1517 static HRESULT WINAPI TaskDefinition_get_RegistrationInfo(ITaskDefinition *iface, IRegistrationInfo **info)
1519 TaskDefinition *taskdef = impl_from_ITaskDefinition(iface);
1520 HRESULT hr;
1522 TRACE("%p,%p\n", iface, info);
1524 if (!info) return E_POINTER;
1526 if (!taskdef->reginfo)
1528 hr = RegistrationInfo_create(&taskdef->reginfo);
1529 if (hr != S_OK) return hr;
1532 IRegistrationInfo_AddRef(taskdef->reginfo);
1533 *info = taskdef->reginfo;
1535 return S_OK;
1538 static HRESULT WINAPI TaskDefinition_put_RegistrationInfo(ITaskDefinition *iface, IRegistrationInfo *info)
1540 TaskDefinition *taskdef = impl_from_ITaskDefinition(iface);
1542 TRACE("%p,%p\n", iface, info);
1544 if (!info) return E_POINTER;
1546 if (taskdef->reginfo)
1547 IRegistrationInfo_Release(taskdef->reginfo);
1549 IRegistrationInfo_AddRef(info);
1550 taskdef->reginfo = info;
1552 return S_OK;
1555 static HRESULT WINAPI TaskDefinition_get_Triggers(ITaskDefinition *iface, ITriggerCollection **triggers)
1557 TaskDefinition *This = impl_from_ITaskDefinition(iface);
1559 TRACE("%p,%p\n", This, triggers);
1561 if (!This->triggers)
1563 trigger_collection *collection;
1565 collection = heap_alloc(sizeof(*collection));
1566 if (!collection) return E_OUTOFMEMORY;
1568 collection->ITriggerCollection_iface.lpVtbl = &TriggerCollection_vtbl;
1569 collection->ref = 1;
1570 This->triggers = &collection->ITriggerCollection_iface;
1573 ITriggerCollection_AddRef(*triggers = This->triggers);
1574 return S_OK;
1577 static HRESULT WINAPI TaskDefinition_put_Triggers(ITaskDefinition *iface, ITriggerCollection *triggers)
1579 FIXME("%p,%p: stub\n", iface, triggers);
1580 return E_NOTIMPL;
1583 static HRESULT WINAPI TaskDefinition_get_Settings(ITaskDefinition *iface, ITaskSettings **settings)
1585 TaskDefinition *taskdef = impl_from_ITaskDefinition(iface);
1586 HRESULT hr;
1588 TRACE("%p,%p\n", iface, settings);
1590 if (!settings) return E_POINTER;
1592 if (!taskdef->taskset)
1594 hr = TaskSettings_create(&taskdef->taskset);
1595 if (hr != S_OK) return hr;
1598 ITaskSettings_AddRef(taskdef->taskset);
1599 *settings = taskdef->taskset;
1601 return S_OK;
1604 static HRESULT WINAPI TaskDefinition_put_Settings(ITaskDefinition *iface, ITaskSettings *settings)
1606 TaskDefinition *taskdef = impl_from_ITaskDefinition(iface);
1608 TRACE("%p,%p\n", iface, settings);
1610 if (!settings) return E_POINTER;
1612 if (taskdef->taskset)
1613 ITaskSettings_Release(taskdef->taskset);
1615 ITaskSettings_AddRef(settings);
1616 taskdef->taskset = settings;
1618 return S_OK;
1621 static HRESULT WINAPI TaskDefinition_get_Data(ITaskDefinition *iface, BSTR *data)
1623 FIXME("%p,%p: stub\n", iface, data);
1624 return E_NOTIMPL;
1627 static HRESULT WINAPI TaskDefinition_put_Data(ITaskDefinition *iface, BSTR data)
1629 FIXME("%p,%p: stub\n", iface, data);
1630 return E_NOTIMPL;
1633 static HRESULT WINAPI TaskDefinition_get_Principal(ITaskDefinition *iface, IPrincipal **principal)
1635 FIXME("%p,%p: stub\n", iface, principal);
1636 return E_NOTIMPL;
1639 static HRESULT WINAPI TaskDefinition_put_Principal(ITaskDefinition *iface, IPrincipal *principal)
1641 FIXME("%p,%p: stub\n", iface, principal);
1642 return E_NOTIMPL;
1645 static HRESULT WINAPI TaskDefinition_get_Actions(ITaskDefinition *iface, IActionCollection **actions)
1647 FIXME("%p,%p: stub\n", iface, actions);
1648 return E_NOTIMPL;
1651 static HRESULT WINAPI TaskDefinition_put_Actions(ITaskDefinition *iface, IActionCollection *actions)
1653 FIXME("%p,%p: stub\n", iface, actions);
1654 return E_NOTIMPL;
1657 static const WCHAR Task[] = {'T','a','s','k',0};
1658 static const WCHAR version[] = {'v','e','r','s','i','o','n',0};
1659 static const WCHAR v1_0[] = {'1','.','0',0};
1660 static const WCHAR v1_1[] = {'1','.','1',0};
1661 static const WCHAR v1_2[] = {'1','.','2',0};
1662 static const WCHAR v1_3[] = {'1','.','3',0};
1663 static const WCHAR xmlns[] = {'x','m','l','n','s',0};
1664 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};
1665 static const WCHAR RegistrationInfo[] = {'R','e','g','i','s','t','r','a','t','i','o','n','I','n','f','o',0};
1666 static const WCHAR Author[] = {'A','u','t','h','o','r',0};
1667 static const WCHAR Description[] = {'D','e','s','c','r','i','p','t','i','o','n',0};
1668 static const WCHAR Source[] = {'S','o','u','r','c','e',0};
1669 static const WCHAR Date[] = {'D','a','t','e',0};
1670 static const WCHAR Version[] = {'V','e','r','s','i','o','n',0};
1671 static const WCHAR Documentation[] = {'D','o','c','u','m','e','n','t','a','t','i','o','n',0};
1672 static const WCHAR URI[] = {'U','R','I',0};
1673 static const WCHAR SecurityDescriptor[] = {'S','e','c','u','r','i','t','y','D','e','s','c','r','i','p','t','o','r',0};
1674 static const WCHAR Settings[] = {'S','e','t','t','i','n','g','s',0};
1675 static const WCHAR Triggers[] = {'T','r','i','g','g','e','r','s',0};
1676 static const WCHAR Principals[] = {'P','r','i','n','c','i','p','a','l','s',0};
1677 static const WCHAR Principal[] = {'P','r','i','n','c','i','p','a','l',0};
1678 static const WCHAR id[] = {'i','d',0};
1679 static const WCHAR UserId[] = {'U','s','e','r','I','d',0};
1680 static const WCHAR LogonType[] = {'L','o','g','o','n','T','y','p','e',0};
1681 static const WCHAR GroupId[] = {'G','r','o','u','p','I','d',0};
1682 static const WCHAR DisplayName[] = {'D','i','s','p','l','a','y','N','a','m','e',0};
1683 static const WCHAR HighestAvailable[] = {'H','i','g','h','e','s','t','A','v','a','i','l','a','b','l','e',0};
1684 static const WCHAR Password[] = {'P','a','s','s','w','o','r','d',0};
1685 static const WCHAR S4U[] = {'S','4','U',0};
1686 static const WCHAR InteractiveToken[] = {'I','n','t','e','r','a','c','t','i','v','e','T','o','k','e','n',0};
1687 static const WCHAR RunLevel[] = {'R','u','n','L','e','v','e','l',0};
1688 static const WCHAR LeastPrivilege[] = {'L','e','a','s','t','P','r','i','v','i','l','e','g','e',0};
1689 static const WCHAR Actions[] = {'A','c','t','i','o','n','s',0};
1690 static const WCHAR Exec[] = {'E','x','e','c',0};
1691 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};
1692 static const WCHAR IgnoreNew[] = {'I','g','n','o','r','e','N','e','w',0};
1693 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};
1694 static const WCHAR AllowStartOnDemand[] = {'A','l','l','o','w','S','t','a','r','t','O','n','D','e','m','a','n','d',0};
1695 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};
1696 static const WCHAR AllowHardTerminate[] = {'A','l','l','o','w','H','a','r','d','T','e','r','m','i','n','a','t','e',0};
1697 static const WCHAR StartWhenAvailable[] = {'S','t','a','r','t','W','h','e','n','A','v','a','i','l','a','b','l','e',0};
1698 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};
1699 static const WCHAR Enabled[] = {'E','n','a','b','l','e','d',0};
1700 static const WCHAR Hidden[] = {'H','i','d','d','e','n',0};
1701 static const WCHAR RunOnlyIfIdle[] = {'R','u','n','O','n','l','y','I','f','I','d','l','e',0};
1702 static const WCHAR WakeToRun[] = {'W','a','k','e','T','o','R','u','n',0};
1703 static const WCHAR ExecutionTimeLimit[] = {'E','x','e','c','u','t','i','o','n','T','i','m','e','L','i','m','i','t',0};
1704 static const WCHAR Priority[] = {'P','r','i','o','r','i','t','y',0};
1705 static const WCHAR IdleSettings[] = {'I','d','l','e','S','e','t','t','i','n','g','s',0};
1707 static int xml_indent;
1709 static inline void push_indent(void)
1711 xml_indent += 2;
1714 static inline void pop_indent(void)
1716 xml_indent -= 2;
1719 static inline HRESULT write_stringW(IStream *stream, const WCHAR *str)
1721 return IStream_Write(stream, str, lstrlenW(str) * sizeof(WCHAR), NULL);
1724 static void write_indent(IStream *stream)
1726 static const WCHAR spacesW[] = {' ',' ',0};
1727 int i;
1728 for (i = 0; i < xml_indent; i += 2)
1729 write_stringW(stream, spacesW);
1732 static const WCHAR start_element[] = {'<',0};
1733 static const WCHAR start_end_element[] = {'<','/',0};
1734 static const WCHAR close_element[] = {'>',0};
1735 static const WCHAR end_empty_element[] = {'/','>',0};
1736 static const WCHAR eol[] = {'\n',0};
1737 static const WCHAR spaceW[] = {' ',0};
1738 static const WCHAR equalW[] = {'=',0};
1739 static const WCHAR quoteW[] = {'"',0};
1741 static inline HRESULT write_empty_element(IStream *stream, const WCHAR *name)
1743 write_indent(stream);
1744 write_stringW(stream, start_element);
1745 write_stringW(stream, name);
1746 write_stringW(stream, end_empty_element);
1747 return write_stringW(stream, eol);
1750 static inline HRESULT write_element(IStream *stream, const WCHAR *name)
1752 write_indent(stream);
1753 write_stringW(stream, start_element);
1754 write_stringW(stream, name);
1755 write_stringW(stream, close_element);
1756 return write_stringW(stream, eol);
1759 static inline HRESULT write_element_end(IStream *stream, const WCHAR *name)
1761 write_indent(stream);
1762 write_stringW(stream, start_end_element);
1763 write_stringW(stream, name);
1764 write_stringW(stream, close_element);
1765 return write_stringW(stream, eol);
1768 static inline HRESULT write_text_value(IStream *stream, const WCHAR *name, const WCHAR *value)
1770 write_indent(stream);
1771 write_stringW(stream, start_element);
1772 write_stringW(stream, name);
1773 write_stringW(stream, close_element);
1774 write_stringW(stream, value);
1775 write_stringW(stream, start_end_element);
1776 write_stringW(stream, name);
1777 write_stringW(stream, close_element);
1778 return write_stringW(stream, eol);
1781 static HRESULT write_task_attributes(IStream *stream, ITaskDefinition *taskdef)
1783 HRESULT hr;
1784 ITaskSettings *taskset;
1785 TASK_COMPATIBILITY level;
1786 const WCHAR *compatibility;
1788 hr = ITaskDefinition_get_Settings(taskdef, &taskset);
1789 if (hr != S_OK) return hr;
1791 hr = ITaskSettings_get_Compatibility(taskset, &level);
1792 if (hr != S_OK) level = TASK_COMPATIBILITY_V2_1;
1794 ITaskSettings_Release(taskset);
1796 switch (level)
1798 case TASK_COMPATIBILITY_AT:
1799 compatibility = v1_0;
1800 break;
1801 case TASK_COMPATIBILITY_V1:
1802 compatibility = v1_1;
1803 break;
1804 case TASK_COMPATIBILITY_V2:
1805 compatibility = v1_2;
1806 break;
1807 default:
1808 compatibility = v1_3;
1809 break;
1812 write_stringW(stream, start_element);
1813 write_stringW(stream, Task);
1814 write_stringW(stream, spaceW);
1815 write_stringW(stream, version);
1816 write_stringW(stream, equalW);
1817 write_stringW(stream, quoteW);
1818 write_stringW(stream, compatibility);
1819 write_stringW(stream, quoteW);
1820 write_stringW(stream, spaceW);
1821 write_stringW(stream, xmlns);
1822 write_stringW(stream, equalW);
1823 write_stringW(stream, quoteW);
1824 write_stringW(stream, task_ns);
1825 write_stringW(stream, quoteW);
1826 write_stringW(stream, close_element);
1827 return write_stringW(stream, eol);
1830 static HRESULT write_registration_info(IStream *stream, IRegistrationInfo *reginfo)
1832 HRESULT hr;
1833 BSTR bstr;
1834 VARIANT var;
1836 if (!reginfo)
1837 return write_empty_element(stream, RegistrationInfo);
1839 hr = write_element(stream, RegistrationInfo);
1840 if (hr != S_OK) return hr;
1842 push_indent();
1844 hr = IRegistrationInfo_get_Source(reginfo, &bstr);
1845 if (hr == S_OK && bstr)
1847 hr = write_text_value(stream, Source, bstr);
1848 SysFreeString(bstr);
1849 if (hr != S_OK) return hr;
1851 hr = IRegistrationInfo_get_Date(reginfo, &bstr);
1852 if (hr == S_OK && bstr)
1854 hr = write_text_value(stream, Date, bstr);
1855 SysFreeString(bstr);
1856 if (hr != S_OK) return hr;
1858 hr = IRegistrationInfo_get_Author(reginfo, &bstr);
1859 if (hr == S_OK && bstr)
1861 hr = write_text_value(stream, Author, bstr);
1862 SysFreeString(bstr);
1863 if (hr != S_OK) return hr;
1865 hr = IRegistrationInfo_get_Version(reginfo, &bstr);
1866 if (hr == S_OK && bstr)
1868 hr = write_text_value(stream, Version, bstr);
1869 SysFreeString(bstr);
1870 if (hr != S_OK) return hr;
1872 hr = IRegistrationInfo_get_Description(reginfo, &bstr);
1873 if (hr == S_OK && bstr)
1875 hr = write_text_value(stream, Description, bstr);
1876 SysFreeString(bstr);
1877 if (hr != S_OK) return hr;
1879 hr = IRegistrationInfo_get_Documentation(reginfo, &bstr);
1880 if (hr == S_OK && bstr)
1882 hr = write_text_value(stream, Documentation, bstr);
1883 SysFreeString(bstr);
1884 if (hr != S_OK) return hr;
1886 hr = IRegistrationInfo_get_URI(reginfo, &bstr);
1887 if (hr == S_OK && bstr)
1889 hr = write_text_value(stream, URI, bstr);
1890 SysFreeString(bstr);
1891 if (hr != S_OK) return hr;
1893 hr = IRegistrationInfo_get_SecurityDescriptor(reginfo, &var);
1894 if (hr == S_OK)
1896 if (V_VT(&var) == VT_BSTR)
1898 hr = write_text_value(stream, SecurityDescriptor, V_BSTR(&var));
1899 VariantClear(&var);
1900 if (hr != S_OK) return hr;
1902 else
1903 FIXME("SecurityInfo variant type %d is not supported\n", V_VT(&var));
1906 pop_indent();
1908 return write_element_end(stream, RegistrationInfo);
1911 static HRESULT write_principal(IStream *stream, IPrincipal *principal)
1913 HRESULT hr;
1914 BSTR bstr;
1915 TASK_LOGON_TYPE logon;
1916 TASK_RUNLEVEL_TYPE level;
1918 if (!principal)
1919 return write_empty_element(stream, Principals);
1921 hr = write_element(stream, Principals);
1922 if (hr != S_OK) return hr;
1924 push_indent();
1926 hr = IPrincipal_get_Id(principal, &bstr);
1927 if (hr == S_OK)
1929 write_indent(stream);
1930 write_stringW(stream, start_element);
1931 write_stringW(stream, Principal);
1932 write_stringW(stream, spaceW);
1933 write_stringW(stream, id);
1934 write_stringW(stream, equalW);
1935 write_stringW(stream, quoteW);
1936 write_stringW(stream, bstr);
1937 write_stringW(stream, quoteW);
1938 write_stringW(stream, close_element);
1939 write_stringW(stream, eol);
1940 SysFreeString(bstr);
1942 else
1943 write_element(stream, Principal);
1945 push_indent();
1947 hr = IPrincipal_get_GroupId(principal, &bstr);
1948 if (hr == S_OK)
1950 hr = write_text_value(stream, GroupId, bstr);
1951 SysFreeString(bstr);
1952 if (hr != S_OK) return hr;
1954 hr = IPrincipal_get_DisplayName(principal, &bstr);
1955 if (hr == S_OK)
1957 hr = write_text_value(stream, DisplayName, bstr);
1958 SysFreeString(bstr);
1959 if (hr != S_OK) return hr;
1961 hr = IPrincipal_get_UserId(principal, &bstr);
1962 if (hr == S_OK && lstrlenW(bstr))
1964 hr = write_text_value(stream, UserId, bstr);
1965 SysFreeString(bstr);
1966 if (hr != S_OK) return hr;
1968 hr = IPrincipal_get_RunLevel(principal, &level);
1969 if (hr == S_OK)
1971 const WCHAR *level_str = NULL;
1973 switch (level)
1975 case TASK_RUNLEVEL_HIGHEST:
1976 level_str = HighestAvailable;
1977 break;
1978 case TASK_RUNLEVEL_LUA:
1979 level_str = LeastPrivilege;
1980 break;
1981 default:
1982 FIXME("Principal run level %d\n", level);
1983 break;
1986 if (level_str)
1988 hr = write_text_value(stream, RunLevel, level_str);
1989 if (hr != S_OK) return hr;
1992 hr = IPrincipal_get_LogonType(principal, &logon);
1993 if (hr == S_OK)
1995 const WCHAR *logon_str = NULL;
1997 switch (logon)
1999 case TASK_LOGON_PASSWORD:
2000 logon_str = Password;
2001 break;
2002 case TASK_LOGON_S4U:
2003 logon_str = S4U;
2004 break;
2005 case TASK_LOGON_INTERACTIVE_TOKEN:
2006 logon_str = InteractiveToken;
2007 break;
2008 default:
2009 FIXME("Principal logon type %d\n", logon);
2010 break;
2013 if (logon_str)
2015 hr = write_text_value(stream, LogonType, logon_str);
2016 if (hr != S_OK) return hr;
2020 pop_indent();
2021 write_element_end(stream, Principal);
2023 pop_indent();
2024 return write_element_end(stream, Principals);
2027 static HRESULT write_settings(IStream *stream, ITaskSettings *settings)
2029 if (!settings)
2030 return write_empty_element(stream, Settings);
2032 FIXME("stub\n");
2033 return S_OK;
2036 static HRESULT write_triggers(IStream *stream, ITriggerCollection *triggers)
2038 if (!triggers)
2039 return write_empty_element(stream, Triggers);
2041 FIXME("stub\n");
2042 return S_OK;
2045 static HRESULT write_actions(IStream *stream, IActionCollection *actions)
2047 if (!actions)
2049 write_element(stream, Actions);
2050 push_indent();
2051 write_empty_element(stream, Exec);
2052 pop_indent();
2053 return write_element_end(stream, Actions);
2056 FIXME("stub\n");
2057 return S_OK;
2060 static HRESULT WINAPI TaskDefinition_get_XmlText(ITaskDefinition *iface, BSTR *xml)
2062 TaskDefinition *taskdef = impl_from_ITaskDefinition(iface);
2063 HRESULT hr;
2064 IStream *stream;
2065 HGLOBAL hmem;
2066 void *p;
2068 TRACE("%p,%p\n", iface, xml);
2070 hmem = GlobalAlloc(GMEM_MOVEABLE | GMEM_NODISCARD, 16);
2071 if (!hmem) return E_OUTOFMEMORY;
2073 hr = CreateStreamOnHGlobal(hmem, TRUE, &stream);
2074 if (hr != S_OK)
2076 GlobalFree(hmem);
2077 return hr;
2080 hr = write_task_attributes(stream, &taskdef->ITaskDefinition_iface);
2081 if (hr != S_OK) goto failed;
2083 push_indent();
2085 hr = write_registration_info(stream, taskdef->reginfo);
2086 if (hr != S_OK) goto failed;
2088 hr = write_triggers(stream, taskdef->triggers);
2089 if (hr != S_OK) goto failed;
2091 hr = write_principal(stream, taskdef->principal);
2092 if (hr != S_OK) goto failed;
2094 hr = write_settings(stream, taskdef->taskset);
2095 if (hr != S_OK) goto failed;
2097 hr = write_actions(stream, taskdef->actions);
2098 if (hr != S_OK) goto failed;
2100 pop_indent();
2102 write_element_end(stream, Task);
2103 IStream_Write(stream, "\0\0", 2, NULL);
2105 p = GlobalLock(hmem);
2106 *xml = SysAllocString(p);
2107 GlobalUnlock(hmem);
2109 IStream_Release(stream);
2111 return *xml ? S_OK : E_OUTOFMEMORY;
2113 failed:
2114 IStream_Release(stream);
2115 return hr;
2118 static HRESULT read_text_value(IXmlReader *reader, WCHAR **value)
2120 HRESULT hr;
2121 XmlNodeType type;
2123 while (IXmlReader_Read(reader, &type) == S_OK)
2125 switch (type)
2127 case XmlNodeType_Text:
2128 hr = IXmlReader_GetValue(reader, (const WCHAR **)value, NULL);
2129 if (hr != S_OK) return hr;
2130 TRACE("%s\n", debugstr_w(*value));
2131 return S_OK;
2133 case XmlNodeType_Whitespace:
2134 case XmlNodeType_Comment:
2135 break;
2137 default:
2138 FIXME("unexpected node type %d\n", type);
2139 return E_FAIL;
2143 return E_FAIL;
2146 static HRESULT read_variantbool_value(IXmlReader *reader, VARIANT_BOOL *vbool)
2148 static const WCHAR trueW[] = {'t','r','u','e',0};
2149 static const WCHAR falseW[] = {'f','a','l','s','e',0};
2150 HRESULT hr;
2151 WCHAR *value;
2153 hr = read_text_value(reader, &value);
2154 if (hr != S_OK) return hr;
2156 if (!lstrcmpW(value, trueW))
2157 *vbool = VARIANT_TRUE;
2158 else if (!lstrcmpW(value, falseW))
2159 *vbool = VARIANT_FALSE;
2160 else
2162 WARN("unexpected bool value %s\n", debugstr_w(value));
2163 return SCHED_E_INVALIDVALUE;
2166 return S_OK;
2169 static HRESULT read_int_value(IXmlReader *reader, int *int_val)
2171 HRESULT hr;
2172 WCHAR *value;
2174 hr = read_text_value(reader, &value);
2175 if (hr != S_OK) return hr;
2177 *int_val = strtolW(value, NULL, 10);
2179 return S_OK;
2182 static HRESULT read_triggers(IXmlReader *reader, ITaskDefinition *taskdef)
2184 FIXME("stub\n");
2185 return S_OK;
2188 static HRESULT read_principal_attributes(IXmlReader *reader, IPrincipal *principal)
2190 HRESULT hr;
2191 const WCHAR *name;
2192 const WCHAR *value;
2194 hr = IXmlReader_MoveToFirstAttribute(reader);
2196 while (hr == S_OK)
2198 hr = IXmlReader_GetLocalName(reader, &name, NULL);
2199 if (hr != S_OK) break;
2201 hr = IXmlReader_GetValue(reader, &value, NULL);
2202 if (hr != S_OK) break;
2204 TRACE("%s=%s\n", debugstr_w(name), debugstr_w(value));
2206 if (!lstrcmpW(name, id))
2207 IPrincipal_put_Id(principal, (BSTR)value);
2208 else
2209 FIXME("unhandled Principal attribute %s\n", debugstr_w(name));
2211 hr = IXmlReader_MoveToNextAttribute(reader);
2214 return S_OK;
2217 static HRESULT read_principal(IXmlReader *reader, IPrincipal *principal)
2219 HRESULT hr;
2220 XmlNodeType type;
2221 const WCHAR *name;
2222 WCHAR *value;
2224 if (IXmlReader_IsEmptyElement(reader))
2226 TRACE("Principal is empty\n");
2227 return S_OK;
2230 read_principal_attributes(reader, principal);
2232 while (IXmlReader_Read(reader, &type) == S_OK)
2234 switch (type)
2236 case XmlNodeType_EndElement:
2237 hr = IXmlReader_GetLocalName(reader, &name, NULL);
2238 if (hr != S_OK) return hr;
2240 TRACE("/%s\n", debugstr_w(name));
2242 if (!lstrcmpW(name, Principal))
2243 return S_OK;
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, UserId))
2255 hr = read_text_value(reader, &value);
2256 if (hr == S_OK)
2257 IPrincipal_put_UserId(principal, value);
2259 else if (!lstrcmpW(name, LogonType))
2261 hr = read_text_value(reader, &value);
2262 if (hr == S_OK)
2264 TASK_LOGON_TYPE logon = TASK_LOGON_NONE;
2266 if (!lstrcmpW(value, InteractiveToken))
2267 logon = TASK_LOGON_INTERACTIVE_TOKEN;
2268 else
2269 FIXME("unhandled LogonType %s\n", debugstr_w(value));
2271 IPrincipal_put_LogonType(principal, logon);
2274 else if (!lstrcmpW(name, RunLevel))
2276 hr = read_text_value(reader, &value);
2277 if (hr == S_OK)
2279 TASK_RUNLEVEL_TYPE level = TASK_RUNLEVEL_LUA;
2281 if (!lstrcmpW(value, LeastPrivilege))
2282 level = TASK_RUNLEVEL_LUA;
2283 else
2284 FIXME("unhandled RunLevel %s\n", debugstr_w(value));
2286 IPrincipal_put_RunLevel(principal, level);
2289 else
2290 FIXME("unhandled Principal element %s\n", debugstr_w(name));
2292 break;
2294 case XmlNodeType_Whitespace:
2295 case XmlNodeType_Comment:
2296 break;
2298 default:
2299 FIXME("unhandled Principal node type %d\n", type);
2300 break;
2304 WARN("Principal was not terminated\n");
2305 return E_FAIL;
2308 static HRESULT read_principals(IXmlReader *reader, ITaskDefinition *taskdef)
2310 HRESULT hr;
2311 XmlNodeType type;
2312 const WCHAR *name;
2314 if (IXmlReader_IsEmptyElement(reader))
2316 TRACE("Principals is empty\n");
2317 return S_OK;
2320 while (IXmlReader_Read(reader, &type) == S_OK)
2322 switch (type)
2324 case XmlNodeType_EndElement:
2325 hr = IXmlReader_GetLocalName(reader, &name, NULL);
2326 if (hr != S_OK) return hr;
2328 TRACE("/%s\n", debugstr_w(name));
2330 if (!lstrcmpW(name, Principals))
2331 return S_OK;
2333 break;
2335 case XmlNodeType_Element:
2336 hr = IXmlReader_GetLocalName(reader, &name, NULL);
2337 if (hr != S_OK) return hr;
2339 TRACE("Element: %s\n", debugstr_w(name));
2341 if (!lstrcmpW(name, Principal))
2343 IPrincipal *principal;
2345 hr = ITaskDefinition_get_Principal(taskdef, &principal);
2346 if (hr != S_OK) return hr;
2347 hr = read_principal(reader, principal);
2348 IPrincipal_Release(principal);
2350 else
2351 FIXME("unhandled Principals element %s\n", debugstr_w(name));
2353 break;
2355 case XmlNodeType_Whitespace:
2356 case XmlNodeType_Comment:
2357 break;
2359 default:
2360 FIXME("unhandled Principals node type %d\n", type);
2361 break;
2365 WARN("Principals was not terminated\n");
2366 return E_FAIL;
2369 static HRESULT read_actions(IXmlReader *reader, ITaskDefinition *taskdef)
2371 FIXME("stub\n");
2372 return S_OK;
2375 static HRESULT read_idle_settings(IXmlReader *reader, ITaskSettings *taskset)
2377 FIXME("stub\n");
2378 return S_OK;
2381 static HRESULT read_settings(IXmlReader *reader, ITaskSettings *taskset)
2383 HRESULT hr;
2384 XmlNodeType type;
2385 const WCHAR *name;
2386 WCHAR *value;
2387 VARIANT_BOOL bool_val;
2388 int int_val;
2390 if (IXmlReader_IsEmptyElement(reader))
2392 TRACE("Settings is empty\n");
2393 return S_OK;
2396 while (IXmlReader_Read(reader, &type) == S_OK)
2398 switch (type)
2400 case XmlNodeType_EndElement:
2401 hr = IXmlReader_GetLocalName(reader, &name, NULL);
2402 if (hr != S_OK) return hr;
2404 TRACE("/%s\n", debugstr_w(name));
2406 if (!lstrcmpW(name, Settings))
2407 return S_OK;
2409 break;
2411 case XmlNodeType_Element:
2412 hr = IXmlReader_GetLocalName(reader, &name, NULL);
2413 if (hr != S_OK) return hr;
2415 TRACE("Element: %s\n", debugstr_w(name));
2417 if (!lstrcmpW(name, MultipleInstancesPolicy))
2419 hr = read_text_value(reader, &value);
2420 if (hr == S_OK)
2422 int_val = TASK_INSTANCES_IGNORE_NEW;
2424 if (!lstrcmpW(value, IgnoreNew))
2425 int_val = TASK_INSTANCES_IGNORE_NEW;
2426 else
2427 FIXME("unhandled MultipleInstancesPolicy %s\n", debugstr_w(value));
2429 ITaskSettings_put_MultipleInstances(taskset, int_val);
2432 else if (!lstrcmpW(name, DisallowStartIfOnBatteries))
2434 hr = read_variantbool_value(reader, &bool_val);
2435 if (hr != S_OK) return hr;
2436 ITaskSettings_put_DisallowStartIfOnBatteries(taskset, bool_val);
2438 else if (!lstrcmpW(name, AllowStartOnDemand))
2440 hr = read_variantbool_value(reader, &bool_val);
2441 if (hr != S_OK) return hr;
2442 ITaskSettings_put_AllowDemandStart(taskset, bool_val);
2444 else if (!lstrcmpW(name, StopIfGoingOnBatteries))
2446 hr = read_variantbool_value(reader, &bool_val);
2447 if (hr != S_OK) return hr;
2448 ITaskSettings_put_StopIfGoingOnBatteries(taskset, bool_val);
2450 else if (!lstrcmpW(name, AllowHardTerminate))
2452 hr = read_variantbool_value(reader, &bool_val);
2453 if (hr != S_OK) return hr;
2454 ITaskSettings_put_AllowHardTerminate(taskset, bool_val);
2456 else if (!lstrcmpW(name, StartWhenAvailable))
2458 hr = read_variantbool_value(reader, &bool_val);
2459 if (hr != S_OK) return hr;
2460 ITaskSettings_put_StartWhenAvailable(taskset, bool_val);
2462 else if (!lstrcmpW(name, RunOnlyIfNetworkAvailable))
2464 hr = read_variantbool_value(reader, &bool_val);
2465 if (hr != S_OK) return hr;
2466 ITaskSettings_put_RunOnlyIfNetworkAvailable(taskset, bool_val);
2468 else if (!lstrcmpW(name, Enabled))
2470 hr = read_variantbool_value(reader, &bool_val);
2471 if (hr != S_OK) return hr;
2472 ITaskSettings_put_Enabled(taskset, bool_val);
2474 else if (!lstrcmpW(name, Hidden))
2476 hr = read_variantbool_value(reader, &bool_val);
2477 if (hr != S_OK) return hr;
2478 ITaskSettings_put_Hidden(taskset, bool_val);
2480 else if (!lstrcmpW(name, RunOnlyIfIdle))
2482 hr = read_variantbool_value(reader, &bool_val);
2483 if (hr != S_OK) return hr;
2484 ITaskSettings_put_RunOnlyIfIdle(taskset, bool_val);
2486 else if (!lstrcmpW(name, WakeToRun))
2488 hr = read_variantbool_value(reader, &bool_val);
2489 if (hr != S_OK) return hr;
2490 ITaskSettings_put_WakeToRun(taskset, bool_val);
2492 else if (!lstrcmpW(name, ExecutionTimeLimit))
2494 hr = read_text_value(reader, &value);
2495 if (hr == S_OK)
2496 ITaskSettings_put_ExecutionTimeLimit(taskset, value);
2498 else if (!lstrcmpW(name, Priority))
2500 hr = read_int_value(reader, &int_val);
2501 if (hr == S_OK)
2502 ITaskSettings_put_Priority(taskset, int_val);
2504 else if (!lstrcmpW(name, IdleSettings))
2506 hr = read_idle_settings(reader, taskset);
2507 if (hr != S_OK) return hr;
2509 else
2510 FIXME("unhandled Settings element %s\n", debugstr_w(name));
2512 break;
2514 case XmlNodeType_Whitespace:
2515 case XmlNodeType_Comment:
2516 break;
2518 default:
2519 FIXME("unhandled Settings node type %d\n", type);
2520 break;
2524 WARN("Settings was not terminated\n");
2525 return SCHED_E_MALFORMEDXML;
2528 static HRESULT read_registration_info(IXmlReader *reader, IRegistrationInfo *info)
2530 HRESULT hr;
2531 XmlNodeType type;
2532 const WCHAR *name;
2533 WCHAR *value;
2535 if (IXmlReader_IsEmptyElement(reader))
2537 TRACE("RegistrationInfo is empty\n");
2538 return S_OK;
2541 while (IXmlReader_Read(reader, &type) == S_OK)
2543 switch (type)
2545 case XmlNodeType_EndElement:
2546 hr = IXmlReader_GetLocalName(reader, &name, NULL);
2547 if (hr != S_OK) return hr;
2549 TRACE("/%s\n", debugstr_w(name));
2551 if (!lstrcmpW(name, RegistrationInfo))
2552 return S_OK;
2554 break;
2556 case XmlNodeType_Element:
2557 hr = IXmlReader_GetLocalName(reader, &name, NULL);
2558 if (hr != S_OK) return hr;
2560 TRACE("Element: %s\n", debugstr_w(name));
2562 if (!lstrcmpW(name, Author))
2564 hr = read_text_value(reader, &value);
2565 if (hr == S_OK)
2566 IRegistrationInfo_put_Author(info, value);
2568 else if (!lstrcmpW(name, Description))
2570 hr = read_text_value(reader, &value);
2571 if (hr == S_OK)
2572 IRegistrationInfo_put_Description(info, value);
2574 else
2575 FIXME("unhandled RegistrationInfo element %s\n", debugstr_w(name));
2577 break;
2579 case XmlNodeType_Whitespace:
2580 case XmlNodeType_Comment:
2581 break;
2583 default:
2584 FIXME("unhandled RegistrationInfo node type %d\n", type);
2585 break;
2589 WARN("RegistrationInfo was not terminated\n");
2590 return SCHED_E_MALFORMEDXML;
2593 static HRESULT read_task_attributes(IXmlReader *reader, ITaskDefinition *taskdef)
2595 HRESULT hr;
2596 ITaskSettings *taskset;
2597 const WCHAR *name;
2598 const WCHAR *value;
2599 BOOL xmlns_ok = FALSE;
2601 TRACE("\n");
2603 hr = ITaskDefinition_get_Settings(taskdef, &taskset);
2604 if (hr != S_OK) return hr;
2606 hr = IXmlReader_MoveToFirstAttribute(reader);
2608 while (hr == S_OK)
2610 hr = IXmlReader_GetLocalName(reader, &name, NULL);
2611 if (hr != S_OK) break;
2613 hr = IXmlReader_GetValue(reader, &value, NULL);
2614 if (hr != S_OK) break;
2616 TRACE("%s=%s\n", debugstr_w(name), debugstr_w(value));
2618 if (!lstrcmpW(name, version))
2620 TASK_COMPATIBILITY compatibility = TASK_COMPATIBILITY_V2;
2622 if (!lstrcmpW(value, v1_0))
2623 compatibility = TASK_COMPATIBILITY_AT;
2624 else if (!lstrcmpW(value, v1_1))
2625 compatibility = TASK_COMPATIBILITY_V1;
2626 else if (!lstrcmpW(value, v1_2))
2627 compatibility = TASK_COMPATIBILITY_V2;
2628 else if (!lstrcmpW(value, v1_3))
2629 compatibility = TASK_COMPATIBILITY_V2_1;
2630 else
2631 FIXME("unknown version %s\n", debugstr_w(value));
2633 ITaskSettings_put_Compatibility(taskset, compatibility);
2635 else if (!lstrcmpW(name, xmlns))
2637 if (lstrcmpW(value, task_ns))
2639 FIXME("unknown namespace %s\n", debugstr_w(value));
2640 break;
2642 xmlns_ok = TRUE;
2644 else
2645 FIXME("unhandled Task attribute %s\n", debugstr_w(name));
2647 hr = IXmlReader_MoveToNextAttribute(reader);
2650 ITaskSettings_Release(taskset);
2651 return xmlns_ok ? S_OK : SCHED_E_NAMESPACE;
2654 static HRESULT read_task(IXmlReader *reader, ITaskDefinition *taskdef)
2656 HRESULT hr;
2657 XmlNodeType type;
2658 const WCHAR *name;
2660 if (IXmlReader_IsEmptyElement(reader))
2662 TRACE("Task is empty\n");
2663 return S_OK;
2666 while (IXmlReader_Read(reader, &type) == S_OK)
2668 switch (type)
2670 case XmlNodeType_EndElement:
2671 hr = IXmlReader_GetLocalName(reader, &name, NULL);
2672 if (hr != S_OK) return hr;
2674 TRACE("/%s\n", debugstr_w(name));
2676 if (!lstrcmpW(name, Task))
2677 return S_OK;
2679 break;
2681 case XmlNodeType_Element:
2682 hr = IXmlReader_GetLocalName(reader, &name, NULL);
2683 if (hr != S_OK) return hr;
2685 TRACE("Element: %s\n", debugstr_w(name));
2687 if (!lstrcmpW(name, RegistrationInfo))
2689 IRegistrationInfo *info;
2691 hr = ITaskDefinition_get_RegistrationInfo(taskdef, &info);
2692 if (hr != S_OK) return hr;
2693 hr = read_registration_info(reader, info);
2694 IRegistrationInfo_Release(info);
2696 else if (!lstrcmpW(name, Settings))
2698 ITaskSettings *taskset;
2700 hr = ITaskDefinition_get_Settings(taskdef, &taskset);
2701 if (hr != S_OK) return hr;
2702 hr = read_settings(reader, taskset);
2703 ITaskSettings_Release(taskset);
2705 else if (!lstrcmpW(name, Triggers))
2706 hr = read_triggers(reader, taskdef);
2707 else if (!lstrcmpW(name, Principals))
2708 hr = read_principals(reader, taskdef);
2709 else if (!lstrcmpW(name, Actions))
2710 hr = read_actions(reader, taskdef);
2711 else
2712 FIXME("unhandled Task element %s\n", debugstr_w(name));
2714 if (hr != S_OK) return hr;
2715 break;
2717 case XmlNodeType_Comment:
2718 case XmlNodeType_Whitespace:
2719 break;
2721 default:
2722 FIXME("unhandled Task node type %d\n", type);
2723 break;
2727 WARN("Task was not terminated\n");
2728 return SCHED_E_MALFORMEDXML;
2731 static HRESULT read_xml(IXmlReader *reader, ITaskDefinition *taskdef)
2733 HRESULT hr;
2734 XmlNodeType type;
2735 const WCHAR *name;
2737 while (IXmlReader_Read(reader, &type) == S_OK)
2739 switch (type)
2741 case XmlNodeType_XmlDeclaration:
2742 TRACE("XmlDeclaration\n");
2743 break;
2745 case XmlNodeType_Element:
2746 hr = IXmlReader_GetLocalName(reader, &name, NULL);
2747 if (hr != S_OK) return hr;
2749 TRACE("Element: %s\n", debugstr_w(name));
2751 if (!lstrcmpW(name, Task))
2753 hr = read_task_attributes(reader, taskdef);
2754 if (hr != S_OK) return hr;
2756 return read_task(reader, taskdef);
2758 else
2759 FIXME("unhandled XML element %s\n", debugstr_w(name));
2761 break;
2763 case XmlNodeType_Comment:
2764 case XmlNodeType_Whitespace:
2765 break;
2767 default:
2768 FIXME("unhandled XML node type %d\n", type);
2769 break;
2773 WARN("Task definition was not found\n");
2774 return SCHED_E_MALFORMEDXML;
2777 static HRESULT WINAPI TaskDefinition_put_XmlText(ITaskDefinition *iface, BSTR xml)
2779 TaskDefinition *taskdef = impl_from_ITaskDefinition(iface);
2780 HRESULT hr;
2781 IStream *stream;
2782 IXmlReader *reader;
2783 HGLOBAL hmem;
2784 void *buf;
2786 TRACE("%p,%s\n", iface, debugstr_w(xml));
2788 if (!xml) return E_INVALIDARG;
2790 hmem = GlobalAlloc(0, lstrlenW(xml) * sizeof(WCHAR));
2791 if (!hmem) return E_OUTOFMEMORY;
2793 buf = GlobalLock(hmem);
2794 memcpy(buf, xml, lstrlenW(xml) * sizeof(WCHAR));
2795 GlobalUnlock(hmem);
2797 hr = CreateStreamOnHGlobal(hmem, TRUE, &stream);
2798 if (hr != S_OK)
2800 GlobalFree(hmem);
2801 return hr;
2804 hr = CreateXmlReader(&IID_IXmlReader, (void **)&reader, NULL);
2805 if (hr != S_OK)
2807 IStream_Release(stream);
2808 return hr;
2811 hr = IXmlReader_SetInput(reader, (IUnknown *)stream);
2812 if (hr == S_OK)
2814 if (taskdef->reginfo)
2816 IRegistrationInfo_Release(taskdef->reginfo);
2817 taskdef->reginfo = NULL;
2819 if (taskdef->taskset)
2821 ITaskSettings_Release(taskdef->taskset);
2822 taskdef->taskset = NULL;
2824 if (taskdef->triggers)
2826 ITriggerCollection_Release(taskdef->triggers);
2827 taskdef->triggers = NULL;
2829 if (taskdef->principal)
2831 IPrincipal_Release(taskdef->principal);
2832 taskdef->principal = NULL;
2834 if (taskdef->actions)
2836 IActionCollection_Release(taskdef->actions);
2837 taskdef->actions = NULL;
2840 hr = read_xml(reader, iface);
2843 IXmlReader_Release(reader);
2844 IStream_Release(stream);
2846 return hr;
2849 static const ITaskDefinitionVtbl TaskDefinition_vtbl =
2851 TaskDefinition_QueryInterface,
2852 TaskDefinition_AddRef,
2853 TaskDefinition_Release,
2854 TaskDefinition_GetTypeInfoCount,
2855 TaskDefinition_GetTypeInfo,
2856 TaskDefinition_GetIDsOfNames,
2857 TaskDefinition_Invoke,
2858 TaskDefinition_get_RegistrationInfo,
2859 TaskDefinition_put_RegistrationInfo,
2860 TaskDefinition_get_Triggers,
2861 TaskDefinition_put_Triggers,
2862 TaskDefinition_get_Settings,
2863 TaskDefinition_put_Settings,
2864 TaskDefinition_get_Data,
2865 TaskDefinition_put_Data,
2866 TaskDefinition_get_Principal,
2867 TaskDefinition_put_Principal,
2868 TaskDefinition_get_Actions,
2869 TaskDefinition_put_Actions,
2870 TaskDefinition_get_XmlText,
2871 TaskDefinition_put_XmlText
2874 HRESULT TaskDefinition_create(ITaskDefinition **obj)
2876 TaskDefinition *taskdef;
2878 taskdef = heap_alloc_zero(sizeof(*taskdef));
2879 if (!taskdef) return E_OUTOFMEMORY;
2881 taskdef->ITaskDefinition_iface.lpVtbl = &TaskDefinition_vtbl;
2882 taskdef->ref = 1;
2883 *obj = &taskdef->ITaskDefinition_iface;
2885 TRACE("created %p\n", *obj);
2887 return S_OK;
2890 typedef struct
2892 ITaskService ITaskService_iface;
2893 LONG ref;
2894 BOOL connected;
2895 DWORD version;
2896 WCHAR comp_name[MAX_COMPUTERNAME_LENGTH + 1];
2897 } TaskService;
2899 static inline TaskService *impl_from_ITaskService(ITaskService *iface)
2901 return CONTAINING_RECORD(iface, TaskService, ITaskService_iface);
2904 static ULONG WINAPI TaskService_AddRef(ITaskService *iface)
2906 TaskService *task_svc = impl_from_ITaskService(iface);
2907 return InterlockedIncrement(&task_svc->ref);
2910 static ULONG WINAPI TaskService_Release(ITaskService *iface)
2912 TaskService *task_svc = impl_from_ITaskService(iface);
2913 LONG ref = InterlockedDecrement(&task_svc->ref);
2915 if (!ref)
2917 TRACE("destroying %p\n", iface);
2918 heap_free(task_svc);
2921 return ref;
2924 static HRESULT WINAPI TaskService_QueryInterface(ITaskService *iface, REFIID riid, void **obj)
2926 if (!riid || !obj) return E_INVALIDARG;
2928 TRACE("%p,%s,%p\n", iface, debugstr_guid(riid), obj);
2930 if (IsEqualGUID(riid, &IID_ITaskService) ||
2931 IsEqualGUID(riid, &IID_IDispatch) ||
2932 IsEqualGUID(riid, &IID_IUnknown))
2934 ITaskService_AddRef(iface);
2935 *obj = iface;
2936 return S_OK;
2939 FIXME("interface %s is not implemented\n", debugstr_guid(riid));
2940 *obj = NULL;
2941 return E_NOINTERFACE;
2944 static HRESULT WINAPI TaskService_GetTypeInfoCount(ITaskService *iface, UINT *count)
2946 FIXME("%p,%p: stub\n", iface, count);
2947 return E_NOTIMPL;
2950 static HRESULT WINAPI TaskService_GetTypeInfo(ITaskService *iface, UINT index, LCID lcid, ITypeInfo **info)
2952 FIXME("%p,%u,%u,%p: stub\n", iface, index, lcid, info);
2953 return E_NOTIMPL;
2956 static HRESULT WINAPI TaskService_GetIDsOfNames(ITaskService *iface, REFIID riid, LPOLESTR *names,
2957 UINT count, LCID lcid, DISPID *dispid)
2959 FIXME("%p,%s,%p,%u,%u,%p: stub\n", iface, debugstr_guid(riid), names, count, lcid, dispid);
2960 return E_NOTIMPL;
2963 static HRESULT WINAPI TaskService_Invoke(ITaskService *iface, DISPID dispid, REFIID riid, LCID lcid, WORD flags,
2964 DISPPARAMS *params, VARIANT *result, EXCEPINFO *excepinfo, UINT *argerr)
2966 FIXME("%p,%d,%s,%04x,%04x,%p,%p,%p,%p: stub\n", iface, dispid, debugstr_guid(riid), lcid, flags,
2967 params, result, excepinfo, argerr);
2968 return E_NOTIMPL;
2971 static HRESULT WINAPI TaskService_GetFolder(ITaskService *iface, BSTR path, ITaskFolder **folder)
2973 TaskService *task_svc = impl_from_ITaskService(iface);
2975 TRACE("%p,%s,%p\n", iface, debugstr_w(path), folder);
2977 if (!folder) return E_POINTER;
2979 if (!task_svc->connected)
2980 return HRESULT_FROM_WIN32(ERROR_ONLY_IF_CONNECTED);
2982 return TaskFolder_create(path, NULL, folder, FALSE);
2985 static HRESULT WINAPI TaskService_GetRunningTasks(ITaskService *iface, LONG flags, IRunningTaskCollection **tasks)
2987 FIXME("%p,%x,%p: stub\n", iface, flags, tasks);
2988 return E_NOTIMPL;
2991 static HRESULT WINAPI TaskService_NewTask(ITaskService *iface, DWORD flags, ITaskDefinition **definition)
2993 TRACE("%p,%x,%p\n", iface, flags, definition);
2995 if (!definition) return E_POINTER;
2997 if (flags)
2998 FIXME("unsupported flags %x\n", flags);
3000 return TaskDefinition_create(definition);
3003 static inline BOOL is_variant_null(const VARIANT *var)
3005 return V_VT(var) == VT_EMPTY || V_VT(var) == VT_NULL ||
3006 (V_VT(var) == VT_BSTR && (V_BSTR(var) == NULL || !*V_BSTR(var)));
3009 static HRESULT start_schedsvc(void)
3011 static const WCHAR scheduleW[] = { 'S','c','h','e','d','u','l','e',0 };
3012 SC_HANDLE scm, service;
3013 SERVICE_STATUS_PROCESS status;
3014 ULONGLONG start_time;
3015 HRESULT hr = SCHED_E_SERVICE_NOT_RUNNING;
3017 TRACE("Trying to start %s service\n", debugstr_w(scheduleW));
3019 scm = OpenSCManagerW(NULL, NULL, 0);
3020 if (!scm) return SCHED_E_SERVICE_NOT_INSTALLED;
3022 service = OpenServiceW(scm, scheduleW, SERVICE_START | SERVICE_QUERY_STATUS);
3023 if (service)
3025 if (StartServiceW(service, 0, NULL) || GetLastError() == ERROR_SERVICE_ALREADY_RUNNING)
3027 start_time = GetTickCount64();
3030 DWORD dummy;
3032 if (!QueryServiceStatusEx(service, SC_STATUS_PROCESS_INFO, (BYTE *)&status, sizeof(status), &dummy))
3034 WARN("failed to query scheduler status (%u)\n", GetLastError());
3035 break;
3038 if (status.dwCurrentState == SERVICE_RUNNING)
3040 hr = S_OK;
3041 break;
3044 if (GetTickCount64() - start_time > 30000) break;
3045 Sleep(1000);
3047 } while (status.dwCurrentState == SERVICE_START_PENDING);
3049 if (status.dwCurrentState != SERVICE_RUNNING)
3050 WARN("scheduler failed to start %u\n", status.dwCurrentState);
3052 else
3053 WARN("failed to start scheduler service (%u)\n", GetLastError());
3055 CloseServiceHandle(service);
3057 else
3058 WARN("failed to open scheduler service (%u)\n", GetLastError());
3060 CloseServiceHandle(scm);
3061 return hr;
3064 static HRESULT WINAPI TaskService_Connect(ITaskService *iface, VARIANT server, VARIANT user, VARIANT domain, VARIANT password)
3066 static WCHAR ncalrpc[] = { 'n','c','a','l','r','p','c',0 };
3067 TaskService *task_svc = impl_from_ITaskService(iface);
3068 WCHAR comp_name[MAX_COMPUTERNAME_LENGTH + 1];
3069 DWORD len;
3070 HRESULT hr;
3071 RPC_WSTR binding_str;
3072 extern handle_t rpc_handle;
3074 TRACE("%p,%s,%s,%s,%s\n", iface, debugstr_variant(&server), debugstr_variant(&user),
3075 debugstr_variant(&domain), debugstr_variant(&password));
3077 if (!is_variant_null(&user) || !is_variant_null(&domain) || !is_variant_null(&password))
3078 FIXME("user/domain/password are ignored\n");
3080 len = sizeof(comp_name)/sizeof(comp_name[0]);
3081 if (!GetComputerNameW(comp_name, &len))
3082 return HRESULT_FROM_WIN32(GetLastError());
3084 if (!is_variant_null(&server))
3086 const WCHAR *server_name;
3088 if (V_VT(&server) != VT_BSTR)
3090 FIXME("server variant type %d is not supported\n", V_VT(&server));
3091 return HRESULT_FROM_WIN32(ERROR_BAD_NETPATH);
3094 /* skip UNC prefix if any */
3095 server_name = V_BSTR(&server);
3096 if (server_name[0] == '\\' && server_name[1] == '\\')
3097 server_name += 2;
3099 if (strcmpiW(server_name, comp_name))
3101 FIXME("connection to remote server %s is not supported\n", debugstr_w(V_BSTR(&server)));
3102 return HRESULT_FROM_WIN32(ERROR_BAD_NETPATH);
3106 hr = start_schedsvc();
3107 if (hr != S_OK) return hr;
3109 hr = RpcStringBindingComposeW(NULL, ncalrpc, NULL, NULL, NULL, &binding_str);
3110 if (hr != RPC_S_OK) return hr;
3111 hr = RpcBindingFromStringBindingW(binding_str, &rpc_handle);
3112 RpcStringFreeW(&binding_str);
3113 if (hr != RPC_S_OK) return hr;
3115 /* Make sure that the connection works */
3116 hr = SchRpcHighestVersion(&task_svc->version);
3117 if (hr != S_OK) return hr;
3119 TRACE("server version %#x\n", task_svc->version);
3121 strcpyW(task_svc->comp_name, comp_name);
3122 task_svc->connected = TRUE;
3124 return S_OK;
3127 static HRESULT WINAPI TaskService_get_Connected(ITaskService *iface, VARIANT_BOOL *connected)
3129 TaskService *task_svc = impl_from_ITaskService(iface);
3131 TRACE("%p,%p\n", iface, connected);
3133 if (!connected) return E_POINTER;
3135 *connected = task_svc->connected ? VARIANT_TRUE : VARIANT_FALSE;
3137 return S_OK;
3140 static HRESULT WINAPI TaskService_get_TargetServer(ITaskService *iface, BSTR *server)
3142 TaskService *task_svc = impl_from_ITaskService(iface);
3144 TRACE("%p,%p\n", iface, server);
3146 if (!server) return E_POINTER;
3148 if (!task_svc->connected)
3149 return HRESULT_FROM_WIN32(ERROR_ONLY_IF_CONNECTED);
3151 *server = SysAllocString(task_svc->comp_name);
3152 if (!*server) return E_OUTOFMEMORY;
3154 return S_OK;
3157 static HRESULT WINAPI TaskService_get_ConnectedUser(ITaskService *iface, BSTR *user)
3159 FIXME("%p,%p: stub\n", iface, user);
3160 return E_NOTIMPL;
3163 static HRESULT WINAPI TaskService_get_ConnectedDomain(ITaskService *iface, BSTR *domain)
3165 FIXME("%p,%p: stub\n", iface, domain);
3166 return E_NOTIMPL;
3169 static HRESULT WINAPI TaskService_get_HighestVersion(ITaskService *iface, DWORD *version)
3171 TaskService *task_svc = impl_from_ITaskService(iface);
3173 TRACE("%p,%p\n", iface, version);
3175 if (!version) return E_POINTER;
3177 if (!task_svc->connected)
3178 return HRESULT_FROM_WIN32(ERROR_ONLY_IF_CONNECTED);
3180 *version = task_svc->version;
3182 return S_OK;
3185 static const ITaskServiceVtbl TaskService_vtbl =
3187 TaskService_QueryInterface,
3188 TaskService_AddRef,
3189 TaskService_Release,
3190 TaskService_GetTypeInfoCount,
3191 TaskService_GetTypeInfo,
3192 TaskService_GetIDsOfNames,
3193 TaskService_Invoke,
3194 TaskService_GetFolder,
3195 TaskService_GetRunningTasks,
3196 TaskService_NewTask,
3197 TaskService_Connect,
3198 TaskService_get_Connected,
3199 TaskService_get_TargetServer,
3200 TaskService_get_ConnectedUser,
3201 TaskService_get_ConnectedDomain,
3202 TaskService_get_HighestVersion
3205 HRESULT TaskService_create(void **obj)
3207 TaskService *task_svc;
3209 task_svc = heap_alloc(sizeof(*task_svc));
3210 if (!task_svc) return E_OUTOFMEMORY;
3212 task_svc->ITaskService_iface.lpVtbl = &TaskService_vtbl;
3213 task_svc->ref = 1;
3214 task_svc->connected = FALSE;
3215 *obj = &task_svc->ITaskService_iface;
3217 TRACE("created %p\n", *obj);
3219 return S_OK;
3222 void __RPC_FAR *__RPC_USER MIDL_user_allocate(SIZE_T n)
3224 return HeapAlloc(GetProcessHeap(), 0, n);
3227 void __RPC_USER MIDL_user_free(void __RPC_FAR *p)
3229 HeapFree(GetProcessHeap(), 0, p);