/* * Copyright 2013 Dmitry Timoshkov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA */ #include <stdarg.h> #define COBJMACROS #include "windef.h" #include "winbase.h" #include "initguid.h" #include "objbase.h" #include "xmllite.h" #include "taskschd.h" #include "winsvc.h" #include "schrpc.h" #include "taskschd_private.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(taskschd); typedef struct { IDailyTrigger IDailyTrigger_iface; LONG ref; short interval; WCHAR *start_boundary; BOOL enabled; } DailyTrigger; static inline DailyTrigger *impl_from_IDailyTrigger(IDailyTrigger *iface) { return CONTAINING_RECORD(iface, DailyTrigger, IDailyTrigger_iface); } static HRESULT WINAPI DailyTrigger_QueryInterface(IDailyTrigger *iface, REFIID riid, void **ppv) { DailyTrigger *This = impl_from_IDailyTrigger(iface); TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv); if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IDispatch, riid) || IsEqualGUID(&IID_ITrigger, riid) || IsEqualGUID(&IID_IDailyTrigger, riid)) { *ppv = &This->IDailyTrigger_iface; } else { FIXME("unsupported riid %s\n", debugstr_guid(riid)); *ppv = NULL; return E_NOINTERFACE; } IUnknown_AddRef((IUnknown*)*ppv); return S_OK; } static ULONG WINAPI DailyTrigger_AddRef(IDailyTrigger *iface) { DailyTrigger *This = impl_from_IDailyTrigger(iface); LONG ref = InterlockedIncrement(&This->ref); TRACE("(%p) ref=%d\n", This, ref); return ref; } static ULONG WINAPI DailyTrigger_Release(IDailyTrigger *iface) { DailyTrigger *This = impl_from_IDailyTrigger(iface); LONG ref = InterlockedDecrement(&This->ref); TRACE("(%p) ref=%d\n", This, ref); if(!ref) { TRACE("destroying %p\n", iface); heap_free(This->start_boundary); heap_free(This); } return ref; } static HRESULT WINAPI DailyTrigger_GetTypeInfoCount(IDailyTrigger *iface, UINT *count) { DailyTrigger *This = impl_from_IDailyTrigger(iface); FIXME("(%p)->(%p)\n", This, count); return E_NOTIMPL; } static HRESULT WINAPI DailyTrigger_GetTypeInfo(IDailyTrigger *iface, UINT index, LCID lcid, ITypeInfo **info) { DailyTrigger *This = impl_from_IDailyTrigger(iface); FIXME("(%p)->(%u %u %p)\n", This, index, lcid, info); return E_NOTIMPL; } static HRESULT WINAPI DailyTrigger_GetIDsOfNames(IDailyTrigger *iface, REFIID riid, LPOLESTR *names, UINT count, LCID lcid, DISPID *dispid) { DailyTrigger *This = impl_from_IDailyTrigger(iface); FIXME("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), names, count, lcid, dispid); return E_NOTIMPL; } static HRESULT WINAPI DailyTrigger_Invoke(IDailyTrigger *iface, DISPID dispid, REFIID riid, LCID lcid, WORD flags, DISPPARAMS *params, VARIANT *result, EXCEPINFO *excepinfo, UINT *argerr) { DailyTrigger *This = impl_from_IDailyTrigger(iface); FIXME("(%p)->(%d %s %x %x %p %p %p %p)\n", This, dispid, debugstr_guid(riid), lcid, flags, params, result, excepinfo, argerr); return E_NOTIMPL; } static HRESULT WINAPI DailyTrigger_get_Type(IDailyTrigger *iface, TASK_TRIGGER_TYPE2 *type) { DailyTrigger *This = impl_from_IDailyTrigger(iface); FIXME("(%p)->(%p)\n", This, type); return E_NOTIMPL; } static HRESULT WINAPI DailyTrigger_get_Id(IDailyTrigger *iface, BSTR *id) { DailyTrigger *This = impl_from_IDailyTrigger(iface); FIXME("(%p)->(%p)\n", This, id); return E_NOTIMPL; } static HRESULT WINAPI DailyTrigger_put_Id(IDailyTrigger *iface, BSTR id) { DailyTrigger *This = impl_from_IDailyTrigger(iface); FIXME("(%p)->(%s)\n", This, debugstr_w(id)); return E_NOTIMPL; } static HRESULT WINAPI DailyTrigger_get_Repetition(IDailyTrigger *iface, IRepetitionPattern **repeat) { DailyTrigger *This = impl_from_IDailyTrigger(iface); FIXME("(%p)->(%p)\n", This, repeat); return E_NOTIMPL; } static HRESULT WINAPI DailyTrigger_put_Repetition(IDailyTrigger *iface, IRepetitionPattern *repeat) { DailyTrigger *This = impl_from_IDailyTrigger(iface); FIXME("(%p)->(%p)\n", This, repeat); return E_NOTIMPL; } static HRESULT WINAPI DailyTrigger_get_ExecutionTimeLimit(IDailyTrigger *iface, BSTR *limit) { DailyTrigger *This = impl_from_IDailyTrigger(iface); FIXME("(%p)->(%p)\n", This, limit); return E_NOTIMPL; } static HRESULT WINAPI DailyTrigger_put_ExecutionTimeLimit(IDailyTrigger *iface, BSTR limit) { DailyTrigger *This = impl_from_IDailyTrigger(iface); FIXME("(%p)->(%s)\n", This, debugstr_w(limit)); return E_NOTIMPL; } static HRESULT WINAPI DailyTrigger_get_StartBoundary(IDailyTrigger *iface, BSTR *start) { DailyTrigger *This = impl_from_IDailyTrigger(iface); TRACE("(%p)->(%p)\n", This, start); if (!start) return E_POINTER; if (!This->start_boundary) *start = NULL; else if (!(*start = SysAllocString(This->start_boundary))) return E_OUTOFMEMORY; return S_OK; } static HRESULT WINAPI DailyTrigger_put_StartBoundary(IDailyTrigger *iface, BSTR start) { DailyTrigger *This = impl_from_IDailyTrigger(iface); WCHAR *str = NULL; TRACE("(%p)->(%s)\n", This, debugstr_w(start)); if (start && !(str = heap_strdupW(start))) return E_OUTOFMEMORY; heap_free(This->start_boundary); This->start_boundary = str; return S_OK; } static HRESULT WINAPI DailyTrigger_get_EndBoundary(IDailyTrigger *iface, BSTR *end) { DailyTrigger *This = impl_from_IDailyTrigger(iface); FIXME("(%p)->(%p)\n", This, end); return E_NOTIMPL; } static HRESULT WINAPI DailyTrigger_put_EndBoundary(IDailyTrigger *iface, BSTR end) { DailyTrigger *This = impl_from_IDailyTrigger(iface); FIXME("(%p)->(%s)\n", This, debugstr_w(end)); return E_NOTIMPL; } static HRESULT WINAPI DailyTrigger_get_Enabled(IDailyTrigger *iface, VARIANT_BOOL *enabled) { DailyTrigger *This = impl_from_IDailyTrigger(iface); TRACE("(%p)->(%p)\n", This, enabled); if (!enabled) return E_POINTER; *enabled = This->enabled ? VARIANT_TRUE : VARIANT_FALSE; return S_OK; } static HRESULT WINAPI DailyTrigger_put_Enabled(IDailyTrigger *iface, VARIANT_BOOL enabled) { DailyTrigger *This = impl_from_IDailyTrigger(iface); TRACE("(%p)->(%x)\n", This, enabled); This->enabled = !!enabled; return S_OK; } static HRESULT WINAPI DailyTrigger_get_DaysInterval(IDailyTrigger *iface, short *days) { DailyTrigger *This = impl_from_IDailyTrigger(iface); TRACE("(%p)->(%p)\n", This, days); *days = This->interval; return S_OK; } static HRESULT WINAPI DailyTrigger_put_DaysInterval(IDailyTrigger *iface, short days) { DailyTrigger *This = impl_from_IDailyTrigger(iface); TRACE("(%p)->(%d)\n", This, days); if(days <= 0) return E_INVALIDARG; This->interval = days; return S_OK; } static HRESULT WINAPI DailyTrigger_get_RandomDelay(IDailyTrigger *iface, BSTR *pRandomDelay) { DailyTrigger *This = impl_from_IDailyTrigger(iface); FIXME("(%p)->(%p)\n", This, pRandomDelay); return E_NOTIMPL; } static HRESULT WINAPI DailyTrigger_put_RandomDelay(IDailyTrigger *iface, BSTR randomDelay) { DailyTrigger *This = impl_from_IDailyTrigger(iface); FIXME("(%p)->(%s)\n", This, debugstr_w(randomDelay)); return E_NOTIMPL; } static const IDailyTriggerVtbl DailyTrigger_vtbl = { DailyTrigger_QueryInterface, DailyTrigger_AddRef, DailyTrigger_Release, DailyTrigger_GetTypeInfoCount, DailyTrigger_GetTypeInfo, DailyTrigger_GetIDsOfNames, DailyTrigger_Invoke, DailyTrigger_get_Type, DailyTrigger_get_Id, DailyTrigger_put_Id, DailyTrigger_get_Repetition, DailyTrigger_put_Repetition, DailyTrigger_get_ExecutionTimeLimit, DailyTrigger_put_ExecutionTimeLimit, DailyTrigger_get_StartBoundary, DailyTrigger_put_StartBoundary, DailyTrigger_get_EndBoundary, DailyTrigger_put_EndBoundary, DailyTrigger_get_Enabled, DailyTrigger_put_Enabled, DailyTrigger_get_DaysInterval, DailyTrigger_put_DaysInterval, DailyTrigger_get_RandomDelay, DailyTrigger_put_RandomDelay }; static HRESULT DailyTrigger_create(ITrigger **trigger) { DailyTrigger *daily_trigger; daily_trigger = heap_alloc(sizeof(*daily_trigger)); if (!daily_trigger) return E_OUTOFMEMORY; daily_trigger->IDailyTrigger_iface.lpVtbl = &DailyTrigger_vtbl; daily_trigger->ref = 1; daily_trigger->interval = 1; daily_trigger->start_boundary = NULL; daily_trigger->enabled = TRUE; *trigger = (ITrigger*)&daily_trigger->IDailyTrigger_iface; return S_OK; } typedef struct { ITriggerCollection ITriggerCollection_iface; LONG ref; } trigger_collection; static inline trigger_collection *impl_from_ITriggerCollection(ITriggerCollection *iface) { return CONTAINING_RECORD(iface, trigger_collection, ITriggerCollection_iface); } static HRESULT WINAPI TriggerCollection_QueryInterface(ITriggerCollection *iface, REFIID riid, void **ppv) { trigger_collection *This = impl_from_ITriggerCollection(iface); TRACE("(%p)->(%s %p)\n", This, debugstr_guid(riid), ppv); if(IsEqualGUID(&IID_IUnknown, riid) || IsEqualGUID(&IID_IDispatch, riid) || IsEqualGUID(&IID_ITriggerCollection, riid)) { *ppv = &This->ITriggerCollection_iface; }else { FIXME("unimplemented interface %s\n", debugstr_guid(riid)); *ppv = NULL; return E_NOINTERFACE; } IUnknown_AddRef((IUnknown*)*ppv); return S_OK; } static ULONG WINAPI TriggerCollection_AddRef(ITriggerCollection *iface) { trigger_collection *This = impl_from_ITriggerCollection(iface); LONG ref = InterlockedIncrement(&This->ref); TRACE("(%p) ref=%d\n", This, ref); return ref; } static ULONG WINAPI TriggerCollection_Release(ITriggerCollection *iface) { trigger_collection *This = impl_from_ITriggerCollection(iface); LONG ref = InterlockedDecrement(&This->ref); TRACE("(%p) ref=%d\n", This, ref); if(!ref) heap_free(This); return ref; } static HRESULT WINAPI TriggerCollection_GetTypeInfoCount(ITriggerCollection *iface, UINT *count) { trigger_collection *This = impl_from_ITriggerCollection(iface); FIXME("(%p)->(%p)\n", This, count); return E_NOTIMPL; } static HRESULT WINAPI TriggerCollection_GetTypeInfo(ITriggerCollection *iface, UINT index, LCID lcid, ITypeInfo **info) { trigger_collection *This = impl_from_ITriggerCollection(iface); FIXME("(%p)->(%u %u %p)\n", This, index, lcid, info); return E_NOTIMPL; } static HRESULT WINAPI TriggerCollection_GetIDsOfNames(ITriggerCollection *iface, REFIID riid, LPOLESTR *names, UINT count, LCID lcid, DISPID *dispid) { trigger_collection *This = impl_from_ITriggerCollection(iface); FIXME("(%p)->(%s %p %u %u %p)\n", This, debugstr_guid(riid), names, count, lcid, dispid); return E_NOTIMPL; } static HRESULT WINAPI TriggerCollection_Invoke(ITriggerCollection *iface, DISPID dispid, REFIID riid, LCID lcid, WORD flags, DISPPARAMS *params, VARIANT *result, EXCEPINFO *excepinfo, UINT *argerr) { trigger_collection *This = impl_from_ITriggerCollection(iface); FIXME("(%p)->(%d %s %x %x %p %p %p %p)\n", This, dispid, debugstr_guid(riid), lcid, flags, params, result, excepinfo, argerr); return E_NOTIMPL; } static HRESULT WINAPI TriggerCollection_get_Count(ITriggerCollection *iface, LONG *count) { trigger_collection *This = impl_from_ITriggerCollection(iface); FIXME("(%p)->(%p)\n", This, count); return E_NOTIMPL; } static HRESULT WINAPI TriggerCollection_get_Item(ITriggerCollection *iface, LONG index, ITrigger **trigger) { trigger_collection *This = impl_from_ITriggerCollection(iface); FIXME("(%p)->(%d %p)\n", This, index, trigger); return E_NOTIMPL; } static HRESULT WINAPI TriggerCollection_get__NewEnum(ITriggerCollection *iface, IUnknown **penum) { trigger_collection *This = impl_from_ITriggerCollection(iface); FIXME("(%p)->(%p)\n", This, penum); return E_NOTIMPL; } static HRESULT WINAPI TriggerCollection_Create(ITriggerCollection *iface, TASK_TRIGGER_TYPE2 type, ITrigger **trigger) { trigger_collection *This = impl_from_ITriggerCollection(iface); TRACE("(%p)->(%d %p)\n", This, type, trigger); switch(type) { case TASK_TRIGGER_DAILY: return DailyTrigger_create(trigger); default: FIXME("Unimplemented type %d\n", type); return E_NOTIMPL; } return S_OK; } static HRESULT WINAPI TriggerCollection_Remove(ITriggerCollection *iface, VARIANT index) { trigger_collection *This = impl_from_ITriggerCollection(iface); FIXME("(%p)->(%s)\n", This, debugstr_variant(&index)); return E_NOTIMPL; } static HRESULT WINAPI TriggerCollection_Clear(ITriggerCollection *iface) { trigger_collection *This = impl_from_ITriggerCollection(iface); FIXME("(%p)\n", This); return E_NOTIMPL; } static const ITriggerCollectionVtbl TriggerCollection_vtbl = { TriggerCollection_QueryInterface, TriggerCollection_AddRef, TriggerCollection_Release, TriggerCollection_GetTypeInfoCount, TriggerCollection_GetTypeInfo, TriggerCollection_GetIDsOfNames, TriggerCollection_Invoke, TriggerCollection_get_Count, TriggerCollection_get_Item, TriggerCollection_get__NewEnum, TriggerCollection_Create, TriggerCollection_Remove, TriggerCollection_Clear }; typedef struct { IRegistrationInfo IRegistrationInfo_iface; LONG ref; WCHAR *description, *author, *version, *date, *documentation, *uri, *source; } registration_info; static inline registration_info *impl_from_IRegistrationInfo(IRegistrationInfo *iface) { return CONTAINING_RECORD(iface, registration_info, IRegistrationInfo_iface); } static ULONG WINAPI RegistrationInfo_AddRef(IRegistrationInfo *iface) { registration_info *reginfo = impl_from_IRegistrationInfo(iface); return InterlockedIncrement(®info->ref); } static ULONG WINAPI RegistrationInfo_Release(IRegistrationInfo *iface) { registration_info *reginfo = impl_from_IRegistrationInfo(iface); LONG ref = InterlockedDecrement(®info->ref); if (!ref) { TRACE("destroying %p\n", iface); heap_free(reginfo->description); heap_free(reginfo->author); heap_free(reginfo->version); heap_free(reginfo->date); heap_free(reginfo->documentation); heap_free(reginfo->uri); heap_free(reginfo->source); heap_free(reginfo); } return ref; } static HRESULT WINAPI RegistrationInfo_QueryInterface(IRegistrationInfo *iface, REFIID riid, void **obj) { if (!riid || !obj) return E_INVALIDARG; TRACE("%p,%s,%p\n", iface, debugstr_guid(riid), obj); if (IsEqualGUID(riid, &IID_IRegistrationInfo) || IsEqualGUID(riid, &IID_IDispatch) || IsEqualGUID(riid, &IID_IUnknown)) { IRegistrationInfo_AddRef(iface); *obj = iface; return S_OK; } FIXME("interface %s is not implemented\n", debugstr_guid(riid)); *obj = NULL; return E_NOINTERFACE; } static HRESULT WINAPI RegistrationInfo_GetTypeInfoCount(IRegistrationInfo *iface, UINT *count) { FIXME("%p,%p: stub\n", iface, count); return E_NOTIMPL; } static HRESULT WINAPI RegistrationInfo_GetTypeInfo(IRegistrationInfo *iface, UINT index, LCID lcid, ITypeInfo **info) { FIXME("%p,%u,%u,%p: stub\n", iface, index, lcid, info); return E_NOTIMPL; } static HRESULT WINAPI RegistrationInfo_GetIDsOfNames(IRegistrationInfo *iface, REFIID riid, LPOLESTR *names, UINT count, LCID lcid, DISPID *dispid) { FIXME("%p,%s,%p,%u,%u,%p: stub\n", iface, debugstr_guid(riid), names, count, lcid, dispid); return E_NOTIMPL; } static HRESULT WINAPI RegistrationInfo_Invoke(IRegistrationInfo *iface, DISPID dispid, REFIID riid, LCID lcid, WORD flags, DISPPARAMS *params, VARIANT *result, EXCEPINFO *excepinfo, UINT *argerr) { FIXME("%p,%d,%s,%04x,%04x,%p,%p,%p,%p: stub\n", iface, dispid, debugstr_guid(riid), lcid, flags, params, result, excepinfo, argerr); return E_NOTIMPL; } static HRESULT WINAPI RegistrationInfo_get_Description(IRegistrationInfo *iface, BSTR *description) { registration_info *reginfo = impl_from_IRegistrationInfo(iface); TRACE("%p,%p\n", iface, description); if (!description) return E_POINTER; if (!reginfo->description) *description = NULL; else if (!(*description = SysAllocString(reginfo->description))) return E_OUTOFMEMORY; return S_OK; } static HRESULT WINAPI RegistrationInfo_put_Description(IRegistrationInfo *iface, BSTR description) { registration_info *reginfo = impl_from_IRegistrationInfo(iface); WCHAR *str = NULL; TRACE("%p,%s\n", iface, debugstr_w(description)); if (description && !(str = heap_strdupW(description))) return E_OUTOFMEMORY; heap_free(reginfo->description); reginfo->description = str; return S_OK; } static HRESULT WINAPI RegistrationInfo_get_Author(IRegistrationInfo *iface, BSTR *author) { registration_info *reginfo = impl_from_IRegistrationInfo(iface); TRACE("%p,%p\n", iface, author); if (!author) return E_POINTER; if (!reginfo->author) *author = NULL; else if (!(*author = SysAllocString(reginfo->author))) return E_OUTOFMEMORY; return S_OK; } static HRESULT WINAPI RegistrationInfo_put_Author(IRegistrationInfo *iface, BSTR author) { registration_info *reginfo = impl_from_IRegistrationInfo(iface); WCHAR *str = NULL; TRACE("%p,%s\n", iface, debugstr_w(author)); if (author && !(str = heap_strdupW(author))) return E_OUTOFMEMORY; heap_free(reginfo->author); reginfo->author = str; return S_OK; } static HRESULT WINAPI RegistrationInfo_get_Version(IRegistrationInfo *iface, BSTR *version) { registration_info *reginfo = impl_from_IRegistrationInfo(iface); TRACE("%p,%p\n", iface, version); if (!version) return E_POINTER; if (!reginfo->version) *version = NULL; else if (!(*version = SysAllocString(reginfo->version))) return E_OUTOFMEMORY; return S_OK; } static HRESULT WINAPI RegistrationInfo_put_Version(IRegistrationInfo *iface, BSTR version) { registration_info *reginfo = impl_from_IRegistrationInfo(iface); WCHAR *str = NULL; TRACE("%p,%s\n", iface, debugstr_w(version)); if (version && !(str = heap_strdupW(version))) return E_OUTOFMEMORY; heap_free(reginfo->version); reginfo->version = str; return S_OK; } static HRESULT WINAPI RegistrationInfo_get_Date(IRegistrationInfo *iface, BSTR *date) { registration_info *reginfo = impl_from_IRegistrationInfo(iface); TRACE("%p,%p\n", iface, date); if (!date) return E_POINTER; if (!reginfo->date) *date = NULL; else if (!(*date = SysAllocString(reginfo->date))) return E_OUTOFMEMORY; return S_OK; } static HRESULT WINAPI RegistrationInfo_put_Date(IRegistrationInfo *iface, BSTR date) { registration_info *reginfo = impl_from_IRegistrationInfo(iface); WCHAR *str = NULL; TRACE("%p,%s\n", iface, debugstr_w(date)); if (date && !(str = heap_strdupW(date))) return E_OUTOFMEMORY; heap_free(reginfo->date); reginfo->date = str; return S_OK; } static HRESULT WINAPI RegistrationInfo_get_Documentation(IRegistrationInfo *iface, BSTR *doc) { registration_info *reginfo = impl_from_IRegistrationInfo(iface); TRACE("%p,%p\n", iface, doc); if (!doc) return E_POINTER; if (!reginfo->documentation) *doc = NULL; else if (!(*doc = SysAllocString(reginfo->documentation))) return E_OUTOFMEMORY; return S_OK; } static HRESULT WINAPI RegistrationInfo_put_Documentation(IRegistrationInfo *iface, BSTR doc) { registration_info *reginfo = impl_from_IRegistrationInfo(iface); WCHAR *str = NULL; TRACE("%p,%s\n", iface, debugstr_w(doc)); if (doc && !(str = heap_strdupW(doc))) return E_OUTOFMEMORY; heap_free(reginfo->documentation); reginfo->documentation = str; return S_OK; } static HRESULT WINAPI RegistrationInfo_get_XmlText(IRegistrationInfo *iface, BSTR *xml) { FIXME("%p,%p: stub\n", iface, xml); return E_NOTIMPL; } static HRESULT WINAPI RegistrationInfo_put_XmlText(IRegistrationInfo *iface, BSTR xml) { FIXME("%p,%s: stub\n", iface, debugstr_w(xml)); return E_NOTIMPL; } static HRESULT WINAPI RegistrationInfo_get_URI(IRegistrationInfo *iface, BSTR *uri) { registration_info *reginfo = impl_from_IRegistrationInfo(iface); TRACE("%p,%p\n", iface, uri); if (!uri) return E_POINTER; if (!reginfo->uri) *uri = NULL; else if (!(*uri = SysAllocString(reginfo->uri))) return E_OUTOFMEMORY; return S_OK; } static HRESULT WINAPI RegistrationInfo_put_URI(IRegistrationInfo *iface, BSTR uri) { registration_info *reginfo = impl_from_IRegistrationInfo(iface); WCHAR *str = NULL; TRACE("%p,%s\n", iface, debugstr_w(uri)); if (uri && !(str = heap_strdupW(uri))) return E_OUTOFMEMORY; heap_free(reginfo->uri); reginfo->uri = str; return S_OK; } static HRESULT WINAPI RegistrationInfo_get_SecurityDescriptor(IRegistrationInfo *iface, VARIANT *sddl) { FIXME("%p,%p: stub\n", iface, sddl); return E_NOTIMPL; } static HRESULT WINAPI RegistrationInfo_put_SecurityDescriptor(IRegistrationInfo *iface, VARIANT sddl) { FIXME("%p,%s: stub\n", iface, debugstr_variant(&sddl)); return S_OK; } static HRESULT WINAPI RegistrationInfo_get_Source(IRegistrationInfo *iface, BSTR *source) { registration_info *reginfo = impl_from_IRegistrationInfo(iface); TRACE("%p,%p\n", iface, source); if (!source) return E_POINTER; if (!reginfo->source) *source = NULL; else if (!(*source = SysAllocString(reginfo->source))) return E_OUTOFMEMORY; return S_OK; } static HRESULT WINAPI RegistrationInfo_put_Source(IRegistrationInfo *iface, BSTR source) { registration_info *reginfo = impl_from_IRegistrationInfo(iface); WCHAR *str = NULL; TRACE("%p,%s\n", iface, debugstr_w(source)); if (source && !(str = heap_strdupW(source))) return E_OUTOFMEMORY; heap_free(reginfo->source); reginfo->source = str; return S_OK; } static const IRegistrationInfoVtbl RegistrationInfo_vtbl = { RegistrationInfo_QueryInterface, RegistrationInfo_AddRef, RegistrationInfo_Release, RegistrationInfo_GetTypeInfoCount, RegistrationInfo_GetTypeInfo, RegistrationInfo_GetIDsOfNames, RegistrationInfo_Invoke, RegistrationInfo_get_Description, RegistrationInfo_put_Description, RegistrationInfo_get_Author, RegistrationInfo_put_Author, RegistrationInfo_get_Version, RegistrationInfo_put_Version, RegistrationInfo_get_Date, RegistrationInfo_put_Date, RegistrationInfo_get_Documentation, RegistrationInfo_put_Documentation, RegistrationInfo_get_XmlText, RegistrationInfo_put_XmlText, RegistrationInfo_get_URI, RegistrationInfo_put_URI, RegistrationInfo_get_SecurityDescriptor, RegistrationInfo_put_SecurityDescriptor, RegistrationInfo_get_Source, RegistrationInfo_put_Source }; static HRESULT RegistrationInfo_create(IRegistrationInfo **obj) { registration_info *reginfo; reginfo = heap_alloc_zero(sizeof(*reginfo)); if (!reginfo) return E_OUTOFMEMORY; reginfo->IRegistrationInfo_iface.lpVtbl = &RegistrationInfo_vtbl; reginfo->ref = 1; *obj = ®info->IRegistrationInfo_iface; TRACE("created %p\n", *obj); return S_OK; } typedef struct { ITaskSettings ITaskSettings_iface; LONG ref; WCHAR *restart_interval; WCHAR *execution_time_limit; WCHAR *delete_expired_task_after; int restart_count; int priority; TASK_INSTANCES_POLICY policy; TASK_COMPATIBILITY compatibility; BOOL allow_on_demand_start; BOOL stop_if_going_on_batteries; BOOL disallow_start_if_on_batteries; BOOL allow_hard_terminate; BOOL start_when_available; BOOL run_only_if_network_available; BOOL enabled; BOOL hidden; BOOL run_only_if_idle; BOOL wake_to_run; } TaskSettings; static inline TaskSettings *impl_from_ITaskSettings(ITaskSettings *iface) { return CONTAINING_RECORD(iface, TaskSettings, ITaskSettings_iface); } static ULONG WINAPI TaskSettings_AddRef(ITaskSettings *iface) { TaskSettings *taskset = impl_from_ITaskSettings(iface); return InterlockedIncrement(&taskset->ref); } static ULONG WINAPI TaskSettings_Release(ITaskSettings *iface) { TaskSettings *taskset = impl_from_ITaskSettings(iface); LONG ref = InterlockedDecrement(&taskset->ref); if (!ref) { TRACE("destroying %p\n", iface); heap_free(taskset->restart_interval); heap_free(taskset->execution_time_limit); heap_free(taskset->delete_expired_task_after); heap_free(taskset); } return ref; } static HRESULT WINAPI TaskSettings_QueryInterface(ITaskSettings *iface, REFIID riid, void **obj) { if (!riid || !obj) return E_INVALIDARG; TRACE("%p,%s,%p\n", iface, debugstr_guid(riid), obj); if (IsEqualGUID(riid, &IID_ITaskSettings) || IsEqualGUID(riid, &IID_IDispatch) || IsEqualGUID(riid, &IID_IUnknown)) { ITaskSettings_AddRef(iface); *obj = iface; return S_OK; } FIXME("interface %s is not implemented\n", debugstr_guid(riid)); *obj = NULL; return E_NOINTERFACE; } static HRESULT WINAPI TaskSettings_GetTypeInfoCount(ITaskSettings *iface, UINT *count) { FIXME("%p,%p: stub\n", iface, count); return E_NOTIMPL; } static HRESULT WINAPI TaskSettings_GetTypeInfo(ITaskSettings *iface, UINT index, LCID lcid, ITypeInfo **info) { FIXME("%p,%u,%u,%p: stub\n", iface, index, lcid, info); return E_NOTIMPL; } static HRESULT WINAPI TaskSettings_GetIDsOfNames(ITaskSettings *iface, REFIID riid, LPOLESTR *names, UINT count, LCID lcid, DISPID *dispid) { FIXME("%p,%s,%p,%u,%u,%p: stub\n", iface, debugstr_guid(riid), names, count, lcid, dispid); return E_NOTIMPL; } static HRESULT WINAPI TaskSettings_Invoke(ITaskSettings *iface, DISPID dispid, REFIID riid, LCID lcid, WORD flags, DISPPARAMS *params, VARIANT *result, EXCEPINFO *excepinfo, UINT *argerr) { FIXME("%p,%d,%s,%04x,%04x,%p,%p,%p,%p: stub\n", iface, dispid, debugstr_guid(riid), lcid, flags, params, result, excepinfo, argerr); return E_NOTIMPL; } static HRESULT WINAPI TaskSettings_get_AllowDemandStart(ITaskSettings *iface, VARIANT_BOOL *allow) { TaskSettings *taskset = impl_from_ITaskSettings(iface); TRACE("%p,%p\n", iface, allow); if (!allow) return E_POINTER; *allow = taskset->allow_on_demand_start ? VARIANT_TRUE : VARIANT_FALSE; return S_OK; } static HRESULT WINAPI TaskSettings_put_AllowDemandStart(ITaskSettings *iface, VARIANT_BOOL allow) { TaskSettings *taskset = impl_from_ITaskSettings(iface); TRACE("%p,%d\n", iface, allow); taskset->allow_on_demand_start = !!allow; return S_OK; } static HRESULT WINAPI TaskSettings_get_RestartInterval(ITaskSettings *iface, BSTR *interval) { TaskSettings *taskset = impl_from_ITaskSettings(iface); TRACE("%p,%p\n", iface, interval); if (!interval) return E_POINTER; if (!taskset->restart_interval) { *interval = NULL; return S_OK; } if (!taskset->restart_interval) *interval = NULL; else if (!(*interval = SysAllocString(taskset->restart_interval))) return E_OUTOFMEMORY; return S_OK; } static HRESULT WINAPI TaskSettings_put_RestartInterval(ITaskSettings *iface, BSTR interval) { TaskSettings *taskset = impl_from_ITaskSettings(iface); WCHAR *str = NULL; TRACE("%p,%s\n", iface, debugstr_w(interval)); if (interval && !(str = heap_strdupW(interval))) return E_OUTOFMEMORY; heap_free(taskset->restart_interval); taskset->restart_interval = str; return S_OK; } static HRESULT WINAPI TaskSettings_get_RestartCount(ITaskSettings *iface, INT *count) { TaskSettings *taskset = impl_from_ITaskSettings(iface); TRACE("%p,%p\n", iface, count); if (!count) return E_POINTER; *count = taskset->restart_count; return S_OK; } static HRESULT WINAPI TaskSettings_put_RestartCount(ITaskSettings *iface, INT count) { TaskSettings *taskset = impl_from_ITaskSettings(iface); TRACE("%p,%d\n", iface, count); taskset->restart_count = count; return S_OK; } static HRESULT WINAPI TaskSettings_get_MultipleInstances(ITaskSettings *iface, TASK_INSTANCES_POLICY *policy) { TaskSettings *taskset = impl_from_ITaskSettings(iface); TRACE("%p,%p\n", iface, policy); if (!policy) return E_POINTER; *policy = taskset->policy; return S_OK; } static HRESULT WINAPI TaskSettings_put_MultipleInstances(ITaskSettings *iface, TASK_INSTANCES_POLICY policy) { TaskSettings *taskset = impl_from_ITaskSettings(iface); TRACE("%p,%d\n", iface, policy); taskset->policy = policy; return S_OK; } static HRESULT WINAPI TaskSettings_get_StopIfGoingOnBatteries(ITaskSettings *iface, VARIANT_BOOL *stop) { TaskSettings *taskset = impl_from_ITaskSettings(iface); TRACE("%p,%p\n", iface, stop); if (!stop) return E_POINTER; *stop = taskset->stop_if_going_on_batteries ? VARIANT_TRUE : VARIANT_FALSE; return S_OK; } static HRESULT WINAPI TaskSettings_put_StopIfGoingOnBatteries(ITaskSettings *iface, VARIANT_BOOL stop) { TaskSettings *taskset = impl_from_ITaskSettings(iface); TRACE("%p,%d\n", iface, stop); taskset->stop_if_going_on_batteries = !!stop; return S_OK; } static HRESULT WINAPI TaskSettings_get_DisallowStartIfOnBatteries(ITaskSettings *iface, VARIANT_BOOL *disallow) { TaskSettings *taskset = impl_from_ITaskSettings(iface); TRACE("%p,%p\n", iface, disallow); if (!disallow) return E_POINTER; *disallow = taskset->disallow_start_if_on_batteries ? VARIANT_TRUE : VARIANT_FALSE; return S_OK; } static HRESULT WINAPI TaskSettings_put_DisallowStartIfOnBatteries(ITaskSettings *iface, VARIANT_BOOL disallow) { TaskSettings *taskset = impl_from_ITaskSettings(iface); TRACE("%p,%d\n", iface, disallow); taskset->disallow_start_if_on_batteries = !!disallow; return S_OK; } static HRESULT WINAPI TaskSettings_get_AllowHardTerminate(ITaskSettings *iface, VARIANT_BOOL *allow) { TaskSettings *taskset = impl_from_ITaskSettings(iface); TRACE("%p,%p\n", iface, allow); if (!allow) return E_POINTER; *allow = taskset->allow_hard_terminate ? VARIANT_TRUE : VARIANT_FALSE; return S_OK; } static HRESULT WINAPI TaskSettings_put_AllowHardTerminate(ITaskSettings *iface, VARIANT_BOOL allow) { TaskSettings *taskset = impl_from_ITaskSettings(iface); TRACE("%p,%d\n", iface, allow); taskset->allow_hard_terminate = !!allow; return S_OK; } static HRESULT WINAPI TaskSettings_get_StartWhenAvailable(ITaskSettings *iface, VARIANT_BOOL *start) { TaskSettings *taskset = impl_from_ITaskSettings(iface); TRACE("%p,%p\n", iface, start); if (!start) return E_POINTER; *start = taskset->start_when_available ? VARIANT_TRUE : VARIANT_FALSE; return S_OK; } static HRESULT WINAPI TaskSettings_put_StartWhenAvailable(ITaskSettings *iface, VARIANT_BOOL start) { TaskSettings *taskset = impl_from_ITaskSettings(iface); TRACE("%p,%d\n", iface, start); taskset->start_when_available = !!start; return S_OK; } static HRESULT WINAPI TaskSettings_get_XmlText(ITaskSettings *iface, BSTR *xml) { FIXME("%p,%p: stub\n", iface, xml); return E_NOTIMPL; } static HRESULT WINAPI TaskSettings_put_XmlText(ITaskSettings *iface, BSTR xml) { FIXME("%p,%s: stub\n", iface, debugstr_w(xml)); return E_NOTIMPL; } static HRESULT WINAPI TaskSettings_get_RunOnlyIfNetworkAvailable(ITaskSettings *iface, VARIANT_BOOL *run) { TaskSettings *taskset = impl_from_ITaskSettings(iface); TRACE("%p,%p\n", iface, run); if (!run) return E_POINTER; *run = taskset->run_only_if_network_available ? VARIANT_TRUE : VARIANT_FALSE; return S_OK; } static HRESULT WINAPI TaskSettings_put_RunOnlyIfNetworkAvailable(ITaskSettings *iface, VARIANT_BOOL run) { TaskSettings *taskset = impl_from_ITaskSettings(iface); TRACE("%p,%d\n", iface, run); taskset->run_only_if_network_available = !!run; return S_OK; } static HRESULT WINAPI TaskSettings_get_ExecutionTimeLimit(ITaskSettings *iface, BSTR *limit) { TaskSettings *taskset = impl_from_ITaskSettings(iface); TRACE("%p,%p\n", iface, limit); if (!limit) return E_POINTER; if (!taskset->execution_time_limit) { *limit = NULL; return S_OK; } if (!taskset->execution_time_limit) *limit = NULL; else if (!(*limit = SysAllocString(taskset->execution_time_limit))) return E_OUTOFMEMORY; return S_OK; } static HRESULT WINAPI TaskSettings_put_ExecutionTimeLimit(ITaskSettings *iface, BSTR limit) { TaskSettings *taskset = impl_from_ITaskSettings(iface); WCHAR *str = NULL; TRACE("%p,%s\n", iface, debugstr_w(limit)); if (limit && !(str = heap_strdupW(limit))) return E_OUTOFMEMORY; heap_free(taskset->execution_time_limit); taskset->execution_time_limit = str; return S_OK; } static HRESULT WINAPI TaskSettings_get_Enabled(ITaskSettings *iface, VARIANT_BOOL *enabled) { TaskSettings *taskset = impl_from_ITaskSettings(iface); TRACE("%p,%p\n", iface, enabled); if (!enabled) return E_POINTER; *enabled = taskset->enabled ? VARIANT_TRUE : VARIANT_FALSE; return S_OK; } static HRESULT WINAPI TaskSettings_put_Enabled(ITaskSettings *iface, VARIANT_BOOL enabled) { TaskSettings *taskset = impl_from_ITaskSettings(iface); TRACE("%p,%d\n", iface, enabled); taskset->enabled = !!enabled; return S_OK; } static HRESULT WINAPI TaskSettings_get_DeleteExpiredTaskAfter(ITaskSettings *iface, BSTR *delay) { TaskSettings *taskset = impl_from_ITaskSettings(iface); TRACE("%p,%p\n", iface, delay); if (!delay) return E_POINTER; if (!taskset->delete_expired_task_after) *delay = NULL; else if (!(*delay = SysAllocString(taskset->delete_expired_task_after))) return E_OUTOFMEMORY; return S_OK; } static HRESULT WINAPI TaskSettings_put_DeleteExpiredTaskAfter(ITaskSettings *iface, BSTR delay) { TaskSettings *taskset = impl_from_ITaskSettings(iface); WCHAR *str = NULL; TRACE("%p,%s\n", iface, debugstr_w(delay)); if (delay && !(str = heap_strdupW(delay))) return E_OUTOFMEMORY; heap_free(taskset->delete_expired_task_after); taskset->delete_expired_task_after = str; return S_OK; } static HRESULT WINAPI TaskSettings_get_Priority(ITaskSettings *iface, INT *priority) { TaskSettings *taskset = impl_from_ITaskSettings(iface); TRACE("%p,%p\n", iface, priority); if (!priority) return E_POINTER; *priority = taskset->priority; return S_OK; } static HRESULT WINAPI TaskSettings_put_Priority(ITaskSettings *iface, INT priority) { TaskSettings *taskset = impl_from_ITaskSettings(iface); TRACE("%p,%d\n", iface, priority); taskset->priority = priority; return S_OK; } static HRESULT WINAPI TaskSettings_get_Compatibility(ITaskSettings *iface, TASK_COMPATIBILITY *level) { TaskSettings *taskset = impl_from_ITaskSettings(iface); TRACE("%p,%p\n", iface, level); if (!level) return E_POINTER; *level = taskset->compatibility; return S_OK; } static HRESULT WINAPI TaskSettings_put_Compatibility(ITaskSettings *iface, TASK_COMPATIBILITY level) { TaskSettings *taskset = impl_from_ITaskSettings(iface); TRACE("%p,%d\n", iface, level); taskset->compatibility = level; return S_OK; } static HRESULT WINAPI TaskSettings_get_Hidden(ITaskSettings *iface, VARIANT_BOOL *hidden) { TaskSettings *taskset = impl_from_ITaskSettings(iface); TRACE("%p,%p\n", iface, hidden); if (!hidden) return E_POINTER; *hidden = taskset->hidden ? VARIANT_TRUE : VARIANT_FALSE; return S_OK; } static HRESULT WINAPI TaskSettings_put_Hidden(ITaskSettings *iface, VARIANT_BOOL hidden) { TaskSettings *taskset = impl_from_ITaskSettings(iface); TRACE("%p,%d\n", iface, hidden); taskset->hidden = !!hidden; return S_OK; } static HRESULT WINAPI TaskSettings_get_IdleSettings(ITaskSettings *iface, IIdleSettings **settings) { FIXME("%p,%p: stub\n", iface, settings); return E_NOTIMPL; } static HRESULT WINAPI TaskSettings_put_IdleSettings(ITaskSettings *iface, IIdleSettings *settings) { FIXME("%p,%p: stub\n", iface, settings); return E_NOTIMPL; } static HRESULT WINAPI TaskSettings_get_RunOnlyIfIdle(ITaskSettings *iface, VARIANT_BOOL *run) { TaskSettings *taskset = impl_from_ITaskSettings(iface); TRACE("%p,%p\n", iface, run); if (!run) return E_POINTER; *run = taskset->run_only_if_idle ? VARIANT_TRUE : VARIANT_FALSE; return S_OK; } static HRESULT WINAPI TaskSettings_put_RunOnlyIfIdle(ITaskSettings *iface, VARIANT_BOOL run) { TaskSettings *taskset = impl_from_ITaskSettings(iface); TRACE("%p,%d\n", iface, run); taskset->run_only_if_idle = !!run; return S_OK; } static HRESULT WINAPI TaskSettings_get_WakeToRun(ITaskSettings *iface, VARIANT_BOOL *wake) { TaskSettings *taskset = impl_from_ITaskSettings(iface); TRACE("%p,%p\n", iface, wake); if (!wake) return E_POINTER; *wake = taskset->wake_to_run ? VARIANT_TRUE : VARIANT_FALSE; return S_OK; } static HRESULT WINAPI TaskSettings_put_WakeToRun(ITaskSettings *iface, VARIANT_BOOL wake) { TaskSettings *taskset = impl_from_ITaskSettings(iface); TRACE("%p,%d\n", iface, wake); taskset->wake_to_run = !!wake; return S_OK; } static HRESULT WINAPI TaskSettings_get_NetworkSettings(ITaskSettings *iface, INetworkSettings **settings) { FIXME("%p,%p: stub\n", iface, settings); return E_NOTIMPL; } static HRESULT WINAPI TaskSettings_put_NetworkSettings(ITaskSettings *iface, INetworkSettings *settings) { FIXME("%p,%p: stub\n", iface, settings); return E_NOTIMPL; } static const ITaskSettingsVtbl TaskSettings_vtbl = { TaskSettings_QueryInterface, TaskSettings_AddRef, TaskSettings_Release, TaskSettings_GetTypeInfoCount, TaskSettings_GetTypeInfo, TaskSettings_GetIDsOfNames, TaskSettings_Invoke, TaskSettings_get_AllowDemandStart, TaskSettings_put_AllowDemandStart, TaskSettings_get_RestartInterval, TaskSettings_put_RestartInterval, TaskSettings_get_RestartCount, TaskSettings_put_RestartCount, TaskSettings_get_MultipleInstances, TaskSettings_put_MultipleInstances, TaskSettings_get_StopIfGoingOnBatteries, TaskSettings_put_StopIfGoingOnBatteries, TaskSettings_get_DisallowStartIfOnBatteries, TaskSettings_put_DisallowStartIfOnBatteries, TaskSettings_get_AllowHardTerminate, TaskSettings_put_AllowHardTerminate, TaskSettings_get_StartWhenAvailable, TaskSettings_put_StartWhenAvailable, TaskSettings_get_XmlText, TaskSettings_put_XmlText, TaskSettings_get_RunOnlyIfNetworkAvailable, TaskSettings_put_RunOnlyIfNetworkAvailable, TaskSettings_get_ExecutionTimeLimit, TaskSettings_put_ExecutionTimeLimit, TaskSettings_get_Enabled, TaskSettings_put_Enabled, TaskSettings_get_DeleteExpiredTaskAfter, TaskSettings_put_DeleteExpiredTaskAfter, TaskSettings_get_Priority, TaskSettings_put_Priority, TaskSettings_get_Compatibility, TaskSettings_put_Compatibility, TaskSettings_get_Hidden, TaskSettings_put_Hidden, TaskSettings_get_IdleSettings, TaskSettings_put_IdleSettings, TaskSettings_get_RunOnlyIfIdle, TaskSettings_put_RunOnlyIfIdle, TaskSettings_get_WakeToRun, TaskSettings_put_WakeToRun, TaskSettings_get_NetworkSettings, TaskSettings_put_NetworkSettings }; static HRESULT TaskSettings_create(ITaskSettings **obj) { static const WCHAR exec_time_limit[] = { 'P','T','7','2','H',0 }; TaskSettings *taskset; taskset = heap_alloc(sizeof(*taskset)); if (!taskset) return E_OUTOFMEMORY; taskset->ITaskSettings_iface.lpVtbl = &TaskSettings_vtbl; taskset->ref = 1; /* set the defaults */ taskset->restart_interval = NULL; taskset->execution_time_limit = heap_strdupW(exec_time_limit); taskset->delete_expired_task_after = NULL; taskset->restart_count = 0; taskset->priority = 7; taskset->policy = TASK_INSTANCES_IGNORE_NEW; taskset->compatibility = TASK_COMPATIBILITY_V2; taskset->allow_on_demand_start = TRUE; taskset->stop_if_going_on_batteries = TRUE; taskset->disallow_start_if_on_batteries = TRUE; taskset->allow_hard_terminate = TRUE; taskset->start_when_available = FALSE; taskset->run_only_if_network_available = FALSE; taskset->enabled = TRUE; taskset->hidden = FALSE; taskset->run_only_if_idle = FALSE; taskset->wake_to_run = FALSE; *obj = &taskset->ITaskSettings_iface; TRACE("created %p\n", *obj); return S_OK; } typedef struct { IPrincipal IPrincipal_iface; LONG ref; } Principal; static inline Principal *impl_from_IPrincipal(IPrincipal *iface) { return CONTAINING_RECORD(iface, Principal, IPrincipal_iface); } static ULONG WINAPI Principal_AddRef(IPrincipal *iface) { Principal *principal = impl_from_IPrincipal(iface); return InterlockedIncrement(&principal->ref); } static ULONG WINAPI Principal_Release(IPrincipal *iface) { Principal *principal = impl_from_IPrincipal(iface); LONG ref = InterlockedDecrement(&principal->ref); if (!ref) { TRACE("destroying %p\n", iface); heap_free(principal); } return ref; } static HRESULT WINAPI Principal_QueryInterface(IPrincipal *iface, REFIID riid, void **obj) { if (!riid || !obj) return E_INVALIDARG; TRACE("%p,%s,%p\n", iface, debugstr_guid(riid), obj); if (IsEqualGUID(riid, &IID_IPrincipal) || IsEqualGUID(riid, &IID_IDispatch) || IsEqualGUID(riid, &IID_IUnknown)) { IPrincipal_AddRef(iface); *obj = iface; return S_OK; } FIXME("interface %s is not implemented\n", debugstr_guid(riid)); *obj = NULL; return E_NOINTERFACE; } static HRESULT WINAPI Principal_GetTypeInfoCount(IPrincipal *iface, UINT *count) { FIXME("%p,%p: stub\n", iface, count); return E_NOTIMPL; } static HRESULT WINAPI Principal_GetTypeInfo(IPrincipal *iface, UINT index, LCID lcid, ITypeInfo **info) { FIXME("%p,%u,%u,%p: stub\n", iface, index, lcid, info); return E_NOTIMPL; } static HRESULT WINAPI Principal_GetIDsOfNames(IPrincipal *iface, REFIID riid, LPOLESTR *names, UINT count, LCID lcid, DISPID *dispid) { FIXME("%p,%s,%p,%u,%u,%p: stub\n", iface, debugstr_guid(riid), names, count, lcid, dispid); return E_NOTIMPL; } static HRESULT WINAPI Principal_Invoke(IPrincipal *iface, DISPID dispid, REFIID riid, LCID lcid, WORD flags, DISPPARAMS *params, VARIANT *result, EXCEPINFO *excepinfo, UINT *argerr) { FIXME("%p,%d,%s,%04x,%04x,%p,%p,%p,%p: stub\n", iface, dispid, debugstr_guid(riid), lcid, flags, params, result, excepinfo, argerr); return E_NOTIMPL; } static HRESULT WINAPI Principal_get_Id(IPrincipal *iface, BSTR *id) { FIXME("%p,%p: stub\n", iface, id); return E_NOTIMPL; } static HRESULT WINAPI Principal_put_Id(IPrincipal *iface, BSTR id) { FIXME("%p,%s: stub\n", iface, debugstr_w(id)); return S_OK; } static HRESULT WINAPI Principal_get_DisplayName(IPrincipal *iface, BSTR *name) { FIXME("%p,%p: stub\n", iface, name); return E_NOTIMPL; } static HRESULT WINAPI Principal_put_DisplayName(IPrincipal *iface, BSTR name) { FIXME("%p,%s: stub\n", iface, debugstr_w(name)); return E_NOTIMPL; } static HRESULT WINAPI Principal_get_UserId(IPrincipal *iface, BSTR *user_id) { FIXME("%p,%p: stub\n", iface, user_id); return E_NOTIMPL; } static HRESULT WINAPI Principal_put_UserId(IPrincipal *iface, BSTR user_id) { FIXME("%p,%s: stub\n", iface, debugstr_w(user_id)); return S_OK; } static HRESULT WINAPI Principal_get_LogonType(IPrincipal *iface, TASK_LOGON_TYPE *logon_type) { FIXME("%p,%p: stub\n", iface, logon_type); return E_NOTIMPL; } static HRESULT WINAPI Principal_put_LogonType(IPrincipal *iface, TASK_LOGON_TYPE logon_type) { FIXME("%p,%u: stub\n", iface, logon_type); return E_NOTIMPL; } static HRESULT WINAPI Principal_get_GroupId(IPrincipal *iface, BSTR *group_id) { FIXME("%p,%p: stub\n", iface, group_id); return E_NOTIMPL; } static HRESULT WINAPI Principal_put_GroupId(IPrincipal *iface, BSTR group_id) { FIXME("%p,%s: stub\n", iface, debugstr_w(group_id)); return E_NOTIMPL; } static HRESULT WINAPI Principal_get_RunLevel(IPrincipal *iface, TASK_RUNLEVEL_TYPE *run_level) { FIXME("%p,%p: stub\n", iface, run_level); return E_NOTIMPL; } static HRESULT WINAPI Principal_put_RunLevel(IPrincipal *iface, TASK_RUNLEVEL_TYPE run_level) { FIXME("%p,%u: stub\n", iface, run_level); return E_NOTIMPL; } static const IPrincipalVtbl Principal_vtbl = { Principal_QueryInterface, Principal_AddRef, Principal_Release, Principal_GetTypeInfoCount, Principal_GetTypeInfo, Principal_GetIDsOfNames, Principal_Invoke, Principal_get_Id, Principal_put_Id, Principal_get_DisplayName, Principal_put_DisplayName, Principal_get_UserId, Principal_put_UserId, Principal_get_LogonType, Principal_put_LogonType, Principal_get_GroupId, Principal_put_GroupId, Principal_get_RunLevel, Principal_put_RunLevel }; static HRESULT Principal_create(IPrincipal **obj) { Principal *principal; principal = heap_alloc(sizeof(*principal)); if (!principal) return E_OUTOFMEMORY; principal->IPrincipal_iface.lpVtbl = &Principal_vtbl; principal->ref = 1; *obj = &principal->IPrincipal_iface; TRACE("created %p\n", *obj); return S_OK; } typedef struct { IExecAction IExecAction_iface; LONG ref; WCHAR *path; WCHAR *directory; WCHAR *args; WCHAR *id; } ExecAction; static inline ExecAction *impl_from_IExecAction(IExecAction *iface) { return CONTAINING_RECORD(iface, ExecAction, IExecAction_iface); } static ULONG WINAPI ExecAction_AddRef(IExecAction *iface) { ExecAction *action = impl_from_IExecAction(iface); return InterlockedIncrement(&action->ref); } static ULONG WINAPI ExecAction_Release(IExecAction *iface) { ExecAction *action = impl_from_IExecAction(iface); LONG ref = InterlockedDecrement(&action->ref); if (!ref) { TRACE("destroying %p\n", iface); heap_free(action->path); heap_free(action->directory); heap_free(action->args); heap_free(action->id); heap_free(action); } return ref; } static HRESULT WINAPI ExecAction_QueryInterface(IExecAction *iface, REFIID riid, void **obj) { if (!riid || !obj) return E_INVALIDARG; TRACE("%p,%s,%p\n", iface, debugstr_guid(riid), obj); if (IsEqualGUID(riid, &IID_IExecAction) || IsEqualGUID(riid, &IID_IAction) || IsEqualGUID(riid, &IID_IDispatch) || IsEqualGUID(riid, &IID_IUnknown)) { IExecAction_AddRef(iface); *obj = iface; return S_OK; } FIXME("interface %s is not implemented\n", debugstr_guid(riid)); *obj = NULL; return E_NOINTERFACE; } static HRESULT WINAPI ExecAction_GetTypeInfoCount(IExecAction *iface, UINT *count) { FIXME("%p,%p: stub\n", iface, count); return E_NOTIMPL; } static HRESULT WINAPI ExecAction_GetTypeInfo(IExecAction *iface, UINT index, LCID lcid, ITypeInfo **info) { FIXME("%p,%u,%u,%p: stub\n", iface, index, lcid, info); return E_NOTIMPL; } static HRESULT WINAPI ExecAction_GetIDsOfNames(IExecAction *iface, REFIID riid, LPOLESTR *names, UINT count, LCID lcid, DISPID *dispid) { FIXME("%p,%s,%p,%u,%u,%p: stub\n", iface, debugstr_guid(riid), names, count, lcid, dispid); return E_NOTIMPL; } static HRESULT WINAPI ExecAction_Invoke(IExecAction *iface, DISPID dispid, REFIID riid, LCID lcid, WORD flags, DISPPARAMS *params, VARIANT *result, EXCEPINFO *excepinfo, UINT *argerr) { FIXME("%p,%d,%s,%04x,%04x,%p,%p,%p,%p: stub\n", iface, dispid, debugstr_guid(riid), lcid, flags, params, result, excepinfo, argerr); return E_NOTIMPL; } static HRESULT WINAPI ExecAction_get_Id(IExecAction *iface, BSTR *id) { ExecAction *action = impl_from_IExecAction(iface); TRACE("%p,%p\n", iface, id); if (!id) return E_POINTER; if (!action->id) *id = NULL; else if (!(*id = SysAllocString(action->id))) return E_OUTOFMEMORY; return S_OK; } static HRESULT WINAPI ExecAction_put_Id(IExecAction *iface, BSTR id) { ExecAction *action = impl_from_IExecAction(iface); WCHAR *str = NULL; TRACE("%p,%s\n", iface, debugstr_w(id)); if (id && !(str = heap_strdupW((id)))) return E_OUTOFMEMORY; heap_free(action->id); action->id = str; return S_OK; } static HRESULT WINAPI ExecAction_get_Type(IExecAction *iface, TASK_ACTION_TYPE *type) { TRACE("%p,%p\n", iface, type); if (!type) return E_POINTER; *type = TASK_ACTION_EXEC; return S_OK; } static HRESULT WINAPI ExecAction_get_Path(IExecAction *iface, BSTR *path) { ExecAction *action = impl_from_IExecAction(iface); TRACE("%p,%p\n", iface, path); if (!path) return E_POINTER; if (!action->path) *path = NULL; else if (!(*path = SysAllocString(action->path))) return E_OUTOFMEMORY; return S_OK; } static HRESULT WINAPI ExecAction_put_Path(IExecAction *iface, BSTR path) { ExecAction *action = impl_from_IExecAction(iface); WCHAR *str = NULL; TRACE("%p,%s\n", iface, debugstr_w(path)); if (path && !(str = heap_strdupW((path)))) return E_OUTOFMEMORY; heap_free(action->path); action->path = str; return S_OK; } static HRESULT WINAPI ExecAction_get_Arguments(IExecAction *iface, BSTR *arguments) { ExecAction *action = impl_from_IExecAction(iface); TRACE("%p,%p\n", iface, arguments); if (!arguments) return E_POINTER; if (!action->args) *arguments = NULL; else if (!(*arguments = SysAllocString(action->args))) return E_OUTOFMEMORY; return S_OK; } static HRESULT WINAPI ExecAction_put_Arguments(IExecAction *iface, BSTR arguments) { ExecAction *action = impl_from_IExecAction(iface); WCHAR *str = NULL; TRACE("%p,%s\n", iface, debugstr_w(arguments)); if (arguments && !(str = heap_strdupW((arguments)))) return E_OUTOFMEMORY; heap_free(action->args); action->args = str; return S_OK; } static HRESULT WINAPI ExecAction_get_WorkingDirectory(IExecAction *iface, BSTR *directory) { ExecAction *action = impl_from_IExecAction(iface); TRACE("%p,%p\n", iface, directory); if (!directory) return E_POINTER; if (!action->directory) *directory = NULL; else if (!(*directory = SysAllocString(action->directory))) return E_OUTOFMEMORY; return S_OK; } static HRESULT WINAPI ExecAction_put_WorkingDirectory(IExecAction *iface, BSTR directory) { ExecAction *action = impl_from_IExecAction(iface); WCHAR *str = NULL; TRACE("%p,%s\n", iface, debugstr_w(directory)); if (directory && !(str = heap_strdupW((directory)))) return E_OUTOFMEMORY; heap_free(action->directory); action->directory = str; return S_OK; } static const IExecActionVtbl Action_vtbl = { ExecAction_QueryInterface, ExecAction_AddRef, ExecAction_Release, ExecAction_GetTypeInfoCount, ExecAction_GetTypeInfo, ExecAction_GetIDsOfNames, ExecAction_Invoke, ExecAction_get_Id, ExecAction_put_Id, ExecAction_get_Type, ExecAction_get_Path, ExecAction_put_Path, ExecAction_get_Arguments, ExecAction_put_Arguments, ExecAction_get_WorkingDirectory, ExecAction_put_WorkingDirectory }; static HRESULT ExecAction_create(IExecAction **obj) { ExecAction *action; action = heap_alloc(sizeof(*action)); if (!action) return E_OUTOFMEMORY; action->IExecAction_iface.lpVtbl = &Action_vtbl; action->ref = 1; action->path = NULL; action->directory = NULL; action->args = NULL; action->id = NULL; *obj = &action->IExecAction_iface; TRACE("created %p\n", *obj); return S_OK; } typedef struct { IActionCollection IActionCollection_iface; LONG ref; } Actions; static inline Actions *impl_from_IActionCollection(IActionCollection *iface) { return CONTAINING_RECORD(iface, Actions, IActionCollection_iface); } static ULONG WINAPI Actions_AddRef(IActionCollection *iface) { Actions *actions = impl_from_IActionCollection(iface); return InterlockedIncrement(&actions->ref); } static ULONG WINAPI Actions_Release(IActionCollection *iface) { Actions *actions = impl_from_IActionCollection(iface); LONG ref = InterlockedDecrement(&actions->ref); if (!ref) { TRACE("destroying %p\n", iface); heap_free(actions); } return ref; } static HRESULT WINAPI Actions_QueryInterface(IActionCollection *iface, REFIID riid, void **obj) { if (!riid || !obj) return E_INVALIDARG; TRACE("%p,%s,%p\n", iface, debugstr_guid(riid), obj); if (IsEqualGUID(riid, &IID_IActionCollection) || IsEqualGUID(riid, &IID_IDispatch) || IsEqualGUID(riid, &IID_IUnknown)) { IActionCollection_AddRef(iface); *obj = iface; return S_OK; } FIXME("interface %s is not implemented\n", debugstr_guid(riid)); *obj = NULL; return E_NOINTERFACE; } static HRESULT WINAPI Actions_GetTypeInfoCount(IActionCollection *iface, UINT *count) { FIXME("%p,%p: stub\n", iface, count); return E_NOTIMPL; } static HRESULT WINAPI Actions_GetTypeInfo(IActionCollection *iface, UINT index, LCID lcid, ITypeInfo **info) { FIXME("%p,%u,%u,%p: stub\n", iface, index, lcid, info); return E_NOTIMPL; } static HRESULT WINAPI Actions_GetIDsOfNames(IActionCollection *iface, REFIID riid, LPOLESTR *names, UINT count, LCID lcid, DISPID *dispid) { FIXME("%p,%s,%p,%u,%u,%p: stub\n", iface, debugstr_guid(riid), names, count, lcid, dispid); return E_NOTIMPL; } static HRESULT WINAPI Actions_Invoke(IActionCollection *iface, DISPID dispid, REFIID riid, LCID lcid, WORD flags, DISPPARAMS *params, VARIANT *result, EXCEPINFO *excepinfo, UINT *argerr) { FIXME("%p,%d,%s,%04x,%04x,%p,%p,%p,%p: stub\n", iface, dispid, debugstr_guid(riid), lcid, flags, params, result, excepinfo, argerr); return E_NOTIMPL; } static HRESULT WINAPI Actions_get_Count(IActionCollection *iface, LONG *count) { FIXME("%p,%p: stub\n", iface, count); return E_NOTIMPL; } static HRESULT WINAPI Actions_get_Item(IActionCollection *iface, LONG index, IAction **action) { FIXME("%p,%d,%p: stub\n", iface, index, action); return E_NOTIMPL; } static HRESULT WINAPI Actions_get__NewEnum(IActionCollection *iface, IUnknown **penum) { FIXME("%p,%p: stub\n", iface, penum); return E_NOTIMPL; } static HRESULT WINAPI Actions_get_XmlText(IActionCollection *iface, BSTR *xml) { FIXME("%p,%p: stub\n", iface, xml); return E_NOTIMPL; } static HRESULT WINAPI Actions_put_XmlText(IActionCollection *iface, BSTR xml) { FIXME("%p,%s: stub\n", iface, debugstr_w(xml)); return E_NOTIMPL; } static HRESULT WINAPI Actions_Create(IActionCollection *iface, TASK_ACTION_TYPE type, IAction **action) { TRACE("%p,%u,%p\n", iface, type, action); switch (type) { case TASK_ACTION_EXEC: return ExecAction_create((IExecAction **)action); default: FIXME("unimplemented type %u\n", type); return E_NOTIMPL; } } static HRESULT WINAPI Actions_Remove(IActionCollection *iface, VARIANT index) { FIXME("%p,%s: stub\n", iface, debugstr_variant(&index)); return E_NOTIMPL; } static HRESULT WINAPI Actions_Clear(IActionCollection *iface) { FIXME("%p: stub\n", iface); return E_NOTIMPL; } static HRESULT WINAPI Actions_get_Context(IActionCollection *iface, BSTR *ctx) { FIXME("%p,%p: stub\n", iface, ctx); return E_NOTIMPL; } static HRESULT WINAPI Actions_put_Context(IActionCollection *iface, BSTR ctx) { FIXME("%p,%s: stub\n", iface, debugstr_w(ctx)); return S_OK; } static const IActionCollectionVtbl Actions_vtbl = { Actions_QueryInterface, Actions_AddRef, Actions_Release, Actions_GetTypeInfoCount, Actions_GetTypeInfo, Actions_GetIDsOfNames, Actions_Invoke, Actions_get_Count, Actions_get_Item, Actions_get__NewEnum, Actions_get_XmlText, Actions_put_XmlText, Actions_Create, Actions_Remove, Actions_Clear, Actions_get_Context, Actions_put_Context }; static HRESULT Actions_create(IActionCollection **obj) { Actions *actions; actions = heap_alloc(sizeof(*actions)); if (!actions) return E_OUTOFMEMORY; actions->IActionCollection_iface.lpVtbl = &Actions_vtbl; actions->ref = 1; *obj = &actions->IActionCollection_iface; TRACE("created %p\n", *obj); return S_OK; } typedef struct { ITaskDefinition ITaskDefinition_iface; LONG ref; IRegistrationInfo *reginfo; ITaskSettings *taskset; ITriggerCollection *triggers; IPrincipal *principal; IActionCollection *actions; } TaskDefinition; static inline TaskDefinition *impl_from_ITaskDefinition(ITaskDefinition *iface) { return CONTAINING_RECORD(iface, TaskDefinition, ITaskDefinition_iface); } static ULONG WINAPI TaskDefinition_AddRef(ITaskDefinition *iface) { TaskDefinition *taskdef = impl_from_ITaskDefinition(iface); return InterlockedIncrement(&taskdef->ref); } static ULONG WINAPI TaskDefinition_Release(ITaskDefinition *iface) { TaskDefinition *taskdef = impl_from_ITaskDefinition(iface); LONG ref = InterlockedDecrement(&taskdef->ref); if (!ref) { TRACE("destroying %p\n", iface); if (taskdef->reginfo) IRegistrationInfo_Release(taskdef->reginfo); if (taskdef->taskset) ITaskSettings_Release(taskdef->taskset); if (taskdef->triggers) ITriggerCollection_Release(taskdef->triggers); if (taskdef->principal) IPrincipal_Release(taskdef->principal); if (taskdef->actions) IActionCollection_Release(taskdef->actions); heap_free(taskdef); } return ref; } static HRESULT WINAPI TaskDefinition_QueryInterface(ITaskDefinition *iface, REFIID riid, void **obj) { if (!riid || !obj) return E_INVALIDARG; TRACE("%p,%s,%p\n", iface, debugstr_guid(riid), obj); if (IsEqualGUID(riid, &IID_ITaskDefinition) || IsEqualGUID(riid, &IID_IDispatch) || IsEqualGUID(riid, &IID_IUnknown)) { ITaskDefinition_AddRef(iface); *obj = iface; return S_OK; } FIXME("interface %s is not implemented\n", debugstr_guid(riid)); *obj = NULL; return E_NOINTERFACE; } static HRESULT WINAPI TaskDefinition_GetTypeInfoCount(ITaskDefinition *iface, UINT *count) { FIXME("%p,%p: stub\n", iface, count); return E_NOTIMPL; } static HRESULT WINAPI TaskDefinition_GetTypeInfo(ITaskDefinition *iface, UINT index, LCID lcid, ITypeInfo **info) { FIXME("%p,%u,%u,%p: stub\n", iface, index, lcid, info); return E_NOTIMPL; } static HRESULT WINAPI TaskDefinition_GetIDsOfNames(ITaskDefinition *iface, REFIID riid, LPOLESTR *names, UINT count, LCID lcid, DISPID *dispid) { FIXME("%p,%s,%p,%u,%u,%p: stub\n", iface, debugstr_guid(riid), names, count, lcid, dispid); return E_NOTIMPL; } static HRESULT WINAPI TaskDefinition_Invoke(ITaskDefinition *iface, DISPID dispid, REFIID riid, LCID lcid, WORD flags, DISPPARAMS *params, VARIANT *result, EXCEPINFO *excepinfo, UINT *argerr) { FIXME("%p,%d,%s,%04x,%04x,%p,%p,%p,%p: stub\n", iface, dispid, debugstr_guid(riid), lcid, flags, params, result, excepinfo, argerr); return E_NOTIMPL; } static HRESULT WINAPI TaskDefinition_get_RegistrationInfo(ITaskDefinition *iface, IRegistrationInfo **info) { TaskDefinition *taskdef = impl_from_ITaskDefinition(iface); HRESULT hr; TRACE("%p,%p\n", iface, info); if (!info) return E_POINTER; if (!taskdef->reginfo) { hr = RegistrationInfo_create(&taskdef->reginfo); if (hr != S_OK) return hr; } IRegistrationInfo_AddRef(taskdef->reginfo); *info = taskdef->reginfo; return S_OK; } static HRESULT WINAPI TaskDefinition_put_RegistrationInfo(ITaskDefinition *iface, IRegistrationInfo *info) { TaskDefinition *taskdef = impl_from_ITaskDefinition(iface); TRACE("%p,%p\n", iface, info); if (!info) return E_POINTER; if (taskdef->reginfo) IRegistrationInfo_Release(taskdef->reginfo); IRegistrationInfo_AddRef(info); taskdef->reginfo = info; return S_OK; } static HRESULT WINAPI TaskDefinition_get_Triggers(ITaskDefinition *iface, ITriggerCollection **triggers) { TaskDefinition *This = impl_from_ITaskDefinition(iface); TRACE("%p,%p\n", This, triggers); if (!This->triggers) { trigger_collection *collection; collection = heap_alloc(sizeof(*collection)); if (!collection) return E_OUTOFMEMORY; collection->ITriggerCollection_iface.lpVtbl = &TriggerCollection_vtbl; collection->ref = 1; This->triggers = &collection->ITriggerCollection_iface; } ITriggerCollection_AddRef(*triggers = This->triggers); return S_OK; } static HRESULT WINAPI TaskDefinition_put_Triggers(ITaskDefinition *iface, ITriggerCollection *triggers) { TaskDefinition *taskdef = impl_from_ITaskDefinition(iface); TRACE("%p,%p\n", iface, triggers); if (!triggers) return E_POINTER; if (taskdef->triggers) ITriggerCollection_Release(taskdef->triggers); ITriggerCollection_AddRef(triggers); taskdef->triggers = triggers; return S_OK; } static HRESULT WINAPI TaskDefinition_get_Settings(ITaskDefinition *iface, ITaskSettings **settings) { TaskDefinition *taskdef = impl_from_ITaskDefinition(iface); HRESULT hr; TRACE("%p,%p\n", iface, settings); if (!settings) return E_POINTER; if (!taskdef->taskset) { hr = TaskSettings_create(&taskdef->taskset); if (hr != S_OK) return hr; } ITaskSettings_AddRef(taskdef->taskset); *settings = taskdef->taskset; return S_OK; } static HRESULT WINAPI TaskDefinition_put_Settings(ITaskDefinition *iface, ITaskSettings *settings) { TaskDefinition *taskdef = impl_from_ITaskDefinition(iface); TRACE("%p,%p\n", iface, settings); if (!settings) return E_POINTER; if (taskdef->taskset) ITaskSettings_Release(taskdef->taskset); ITaskSettings_AddRef(settings); taskdef->taskset = settings; return S_OK; } static HRESULT WINAPI TaskDefinition_get_Data(ITaskDefinition *iface, BSTR *data) { FIXME("%p,%p: stub\n", iface, data); return E_NOTIMPL; } static HRESULT WINAPI TaskDefinition_put_Data(ITaskDefinition *iface, BSTR data) { FIXME("%p,%p: stub\n", iface, data); return E_NOTIMPL; } static HRESULT WINAPI TaskDefinition_get_Principal(ITaskDefinition *iface, IPrincipal **principal) { TaskDefinition *taskdef = impl_from_ITaskDefinition(iface); HRESULT hr; TRACE("%p,%p\n", iface, principal); if (!principal) return E_POINTER; if (!taskdef->principal) { hr = Principal_create(&taskdef->principal); if (hr != S_OK) return hr; } IPrincipal_AddRef(taskdef->principal); *principal = taskdef->principal; return S_OK; } static HRESULT WINAPI TaskDefinition_put_Principal(ITaskDefinition *iface, IPrincipal *principal) { TaskDefinition *taskdef = impl_from_ITaskDefinition(iface); TRACE("%p,%p\n", iface, principal); if (!principal) return E_POINTER; if (taskdef->principal) IPrincipal_Release(taskdef->principal); IPrincipal_AddRef(principal); taskdef->principal = principal; return S_OK; } static HRESULT WINAPI TaskDefinition_get_Actions(ITaskDefinition *iface, IActionCollection **actions) { TaskDefinition *taskdef = impl_from_ITaskDefinition(iface); HRESULT hr; TRACE("%p,%p\n", iface, actions); if (!actions) return E_POINTER; if (!taskdef->actions) { hr = Actions_create(&taskdef->actions); if (hr != S_OK) return hr; } IActionCollection_AddRef(taskdef->actions); *actions = taskdef->actions; return S_OK; } static HRESULT WINAPI TaskDefinition_put_Actions(ITaskDefinition *iface, IActionCollection *actions) { TaskDefinition *taskdef = impl_from_ITaskDefinition(iface); TRACE("%p,%p\n", iface, actions); if (!actions) return E_POINTER; if (taskdef->actions) IActionCollection_Release(taskdef->actions); IActionCollection_AddRef(actions); taskdef->actions = actions; return S_OK; } static const WCHAR Task[] = {'T','a','s','k',0}; static const WCHAR version[] = {'v','e','r','s','i','o','n',0}; static const WCHAR v1_0[] = {'1','.','0',0}; static const WCHAR v1_1[] = {'1','.','1',0}; static const WCHAR v1_2[] = {'1','.','2',0}; static const WCHAR v1_3[] = {'1','.','3',0}; static const WCHAR xmlns[] = {'x','m','l','n','s',0}; 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}; static const WCHAR RegistrationInfo[] = {'R','e','g','i','s','t','r','a','t','i','o','n','I','n','f','o',0}; static const WCHAR Author[] = {'A','u','t','h','o','r',0}; static const WCHAR Description[] = {'D','e','s','c','r','i','p','t','i','o','n',0}; static const WCHAR Source[] = {'S','o','u','r','c','e',0}; static const WCHAR Date[] = {'D','a','t','e',0}; static const WCHAR Version[] = {'V','e','r','s','i','o','n',0}; static const WCHAR Documentation[] = {'D','o','c','u','m','e','n','t','a','t','i','o','n',0}; static const WCHAR URI[] = {'U','R','I',0}; static const WCHAR SecurityDescriptor[] = {'S','e','c','u','r','i','t','y','D','e','s','c','r','i','p','t','o','r',0}; static const WCHAR Settings[] = {'S','e','t','t','i','n','g','s',0}; static const WCHAR Triggers[] = {'T','r','i','g','g','e','r','s',0}; static const WCHAR Principals[] = {'P','r','i','n','c','i','p','a','l','s',0}; static const WCHAR principalW[] = {'P','r','i','n','c','i','p','a','l',0}; static const WCHAR id[] = {'i','d',0}; static const WCHAR UserId[] = {'U','s','e','r','I','d',0}; static const WCHAR LogonType[] = {'L','o','g','o','n','T','y','p','e',0}; static const WCHAR GroupId[] = {'G','r','o','u','p','I','d',0}; static const WCHAR DisplayName[] = {'D','i','s','p','l','a','y','N','a','m','e',0}; static const WCHAR HighestAvailable[] = {'H','i','g','h','e','s','t','A','v','a','i','l','a','b','l','e',0}; static const WCHAR Password[] = {'P','a','s','s','w','o','r','d',0}; static const WCHAR S4U[] = {'S','4','U',0}; static const WCHAR InteractiveToken[] = {'I','n','t','e','r','a','c','t','i','v','e','T','o','k','e','n',0}; static const WCHAR RunLevel[] = {'R','u','n','L','e','v','e','l',0}; static const WCHAR LeastPrivilege[] = {'L','e','a','s','t','P','r','i','v','i','l','e','g','e',0}; static const WCHAR actionsW[] = {'A','c','t','i','o','n','s',0}; static const WCHAR Exec[] = {'E','x','e','c',0}; 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}; static const WCHAR IgnoreNew[] = {'I','g','n','o','r','e','N','e','w',0}; 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}; static const WCHAR AllowStartOnDemand[] = {'A','l','l','o','w','S','t','a','r','t','O','n','D','e','m','a','n','d',0}; 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}; static const WCHAR AllowHardTerminate[] = {'A','l','l','o','w','H','a','r','d','T','e','r','m','i','n','a','t','e',0}; static const WCHAR StartWhenAvailable[] = {'S','t','a','r','t','W','h','e','n','A','v','a','i','l','a','b','l','e',0}; 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}; static const WCHAR Enabled[] = {'E','n','a','b','l','e','d',0}; static const WCHAR Hidden[] = {'H','i','d','d','e','n',0}; static const WCHAR RunOnlyIfIdle[] = {'R','u','n','O','n','l','y','I','f','I','d','l','e',0}; static const WCHAR WakeToRun[] = {'W','a','k','e','T','o','R','u','n',0}; static const WCHAR ExecutionTimeLimit[] = {'E','x','e','c','u','t','i','o','n','T','i','m','e','L','i','m','i','t',0}; static const WCHAR Priority[] = {'P','r','i','o','r','i','t','y',0}; static const WCHAR IdleSettings[] = {'I','d','l','e','S','e','t','t','i','n','g','s',0}; static int xml_indent; static inline void push_indent(void) { xml_indent += 2; } static inline void pop_indent(void) { xml_indent -= 2; } static inline HRESULT write_stringW(IStream *stream, const WCHAR *str) { return IStream_Write(stream, str, lstrlenW(str) * sizeof(WCHAR), NULL); } static void write_indent(IStream *stream) { static const WCHAR spacesW[] = {' ',' ',0}; int i; for (i = 0; i < xml_indent; i += 2) write_stringW(stream, spacesW); } static const WCHAR start_element[] = {'<',0}; static const WCHAR start_end_element[] = {'<','/',0}; static const WCHAR close_element[] = {'>',0}; static const WCHAR end_empty_element[] = {'/','>',0}; static const WCHAR eol[] = {'\n',0}; static const WCHAR spaceW[] = {' ',0}; static const WCHAR equalW[] = {'=',0}; static const WCHAR quoteW[] = {'"',0}; static inline HRESULT write_empty_element(IStream *stream, const WCHAR *name) { write_indent(stream); write_stringW(stream, start_element); write_stringW(stream, name); write_stringW(stream, end_empty_element); return write_stringW(stream, eol); } static inline HRESULT write_element(IStream *stream, const WCHAR *name) { write_indent(stream); write_stringW(stream, start_element); write_stringW(stream, name); write_stringW(stream, close_element); return write_stringW(stream, eol); } static inline HRESULT write_element_end(IStream *stream, const WCHAR *name) { write_indent(stream); write_stringW(stream, start_end_element); write_stringW(stream, name); write_stringW(stream, close_element); return write_stringW(stream, eol); } static inline HRESULT write_text_value(IStream *stream, const WCHAR *name, const WCHAR *value) { write_indent(stream); write_stringW(stream, start_element); write_stringW(stream, name); write_stringW(stream, close_element); write_stringW(stream, value); write_stringW(stream, start_end_element); write_stringW(stream, name); write_stringW(stream, close_element); return write_stringW(stream, eol); } static HRESULT write_task_attributes(IStream *stream, ITaskDefinition *taskdef) { HRESULT hr; ITaskSettings *taskset; TASK_COMPATIBILITY level; const WCHAR *compatibility; hr = ITaskDefinition_get_Settings(taskdef, &taskset); if (hr != S_OK) return hr; hr = ITaskSettings_get_Compatibility(taskset, &level); if (hr != S_OK) level = TASK_COMPATIBILITY_V2_1; ITaskSettings_Release(taskset); switch (level) { case TASK_COMPATIBILITY_AT: compatibility = v1_0; break; case TASK_COMPATIBILITY_V1: compatibility = v1_1; break; case TASK_COMPATIBILITY_V2: compatibility = v1_2; break; default: compatibility = v1_3; break; } write_stringW(stream, start_element); write_stringW(stream, Task); write_stringW(stream, spaceW); write_stringW(stream, version); write_stringW(stream, equalW); write_stringW(stream, quoteW); write_stringW(stream, compatibility); write_stringW(stream, quoteW); write_stringW(stream, spaceW); write_stringW(stream, xmlns); write_stringW(stream, equalW); write_stringW(stream, quoteW); write_stringW(stream, task_ns); write_stringW(stream, quoteW); write_stringW(stream, close_element); return write_stringW(stream, eol); } static HRESULT write_registration_info(IStream *stream, IRegistrationInfo *reginfo) { HRESULT hr; BSTR bstr; VARIANT var; if (!reginfo) return write_empty_element(stream, RegistrationInfo); hr = write_element(stream, RegistrationInfo); if (hr != S_OK) return hr; push_indent(); hr = IRegistrationInfo_get_Source(reginfo, &bstr); if (hr == S_OK && bstr) { hr = write_text_value(stream, Source, bstr); SysFreeString(bstr); if (hr != S_OK) return hr; } hr = IRegistrationInfo_get_Date(reginfo, &bstr); if (hr == S_OK && bstr) { hr = write_text_value(stream, Date, bstr); SysFreeString(bstr); if (hr != S_OK) return hr; } hr = IRegistrationInfo_get_Author(reginfo, &bstr); if (hr == S_OK && bstr) { hr = write_text_value(stream, Author, bstr); SysFreeString(bstr); if (hr != S_OK) return hr; } hr = IRegistrationInfo_get_Version(reginfo, &bstr); if (hr == S_OK && bstr) { hr = write_text_value(stream, Version, bstr); SysFreeString(bstr); if (hr != S_OK) return hr; } hr = IRegistrationInfo_get_Description(reginfo, &bstr); if (hr == S_OK && bstr) { hr = write_text_value(stream, Description, bstr); SysFreeString(bstr); if (hr != S_OK) return hr; } hr = IRegistrationInfo_get_Documentation(reginfo, &bstr); if (hr == S_OK && bstr) { hr = write_text_value(stream, Documentation, bstr); SysFreeString(bstr); if (hr != S_OK) return hr; } hr = IRegistrationInfo_get_URI(reginfo, &bstr); if (hr == S_OK && bstr) { hr = write_text_value(stream, URI, bstr); SysFreeString(bstr); if (hr != S_OK) return hr; } hr = IRegistrationInfo_get_SecurityDescriptor(reginfo, &var); if (hr == S_OK) { if (V_VT(&var) == VT_BSTR) { hr = write_text_value(stream, SecurityDescriptor, V_BSTR(&var)); VariantClear(&var); if (hr != S_OK) return hr; } else FIXME("SecurityInfo variant type %d is not supported\n", V_VT(&var)); } pop_indent(); return write_element_end(stream, RegistrationInfo); } static HRESULT write_principal(IStream *stream, IPrincipal *principal) { HRESULT hr; BSTR bstr; TASK_LOGON_TYPE logon; TASK_RUNLEVEL_TYPE level; if (!principal) return write_empty_element(stream, Principals); hr = write_element(stream, Principals); if (hr != S_OK) return hr; push_indent(); hr = IPrincipal_get_Id(principal, &bstr); if (hr == S_OK) { write_indent(stream); write_stringW(stream, start_element); write_stringW(stream, principalW); write_stringW(stream, spaceW); write_stringW(stream, id); write_stringW(stream, equalW); write_stringW(stream, quoteW); write_stringW(stream, bstr); write_stringW(stream, quoteW); write_stringW(stream, close_element); write_stringW(stream, eol); SysFreeString(bstr); } else write_element(stream, principalW); push_indent(); hr = IPrincipal_get_GroupId(principal, &bstr); if (hr == S_OK) { hr = write_text_value(stream, GroupId, bstr); SysFreeString(bstr); if (hr != S_OK) return hr; } hr = IPrincipal_get_DisplayName(principal, &bstr); if (hr == S_OK) { hr = write_text_value(stream, DisplayName, bstr); SysFreeString(bstr); if (hr != S_OK) return hr; } hr = IPrincipal_get_UserId(principal, &bstr); if (hr == S_OK && lstrlenW(bstr)) { hr = write_text_value(stream, UserId, bstr); SysFreeString(bstr); if (hr != S_OK) return hr; } hr = IPrincipal_get_RunLevel(principal, &level); if (hr == S_OK) { const WCHAR *level_str = NULL; switch (level) { case TASK_RUNLEVEL_HIGHEST: level_str = HighestAvailable; break; case TASK_RUNLEVEL_LUA: level_str = LeastPrivilege; break; default: FIXME("Principal run level %d\n", level); break; } if (level_str) { hr = write_text_value(stream, RunLevel, level_str); if (hr != S_OK) return hr; } } hr = IPrincipal_get_LogonType(principal, &logon); if (hr == S_OK) { const WCHAR *logon_str = NULL; switch (logon) { case TASK_LOGON_PASSWORD: logon_str = Password; break; case TASK_LOGON_S4U: logon_str = S4U; break; case TASK_LOGON_INTERACTIVE_TOKEN: logon_str = InteractiveToken; break; default: FIXME("Principal logon type %d\n", logon); break; } if (logon_str) { hr = write_text_value(stream, LogonType, logon_str); if (hr != S_OK) return hr; } } pop_indent(); write_element_end(stream, principalW); pop_indent(); return write_element_end(stream, Principals); } static HRESULT write_settings(IStream *stream, ITaskSettings *settings) { if (!settings) return write_empty_element(stream, Settings); FIXME("stub\n"); return S_OK; } static HRESULT write_triggers(IStream *stream, ITriggerCollection *triggers) { if (!triggers) return write_empty_element(stream, Triggers); FIXME("stub\n"); return S_OK; } static HRESULT write_actions(IStream *stream, IActionCollection *actions) { if (!actions) { write_element(stream, actionsW); push_indent(); write_empty_element(stream, Exec); pop_indent(); return write_element_end(stream, actionsW); } FIXME("stub\n"); return S_OK; } static HRESULT WINAPI TaskDefinition_get_XmlText(ITaskDefinition *iface, BSTR *xml) { TaskDefinition *taskdef = impl_from_ITaskDefinition(iface); HRESULT hr; IStream *stream; HGLOBAL hmem; void *p; TRACE("%p,%p\n", iface, xml); hmem = GlobalAlloc(GMEM_MOVEABLE | GMEM_NODISCARD, 16); if (!hmem) return E_OUTOFMEMORY; hr = CreateStreamOnHGlobal(hmem, TRUE, &stream); if (hr != S_OK) { GlobalFree(hmem); return hr; } hr = write_task_attributes(stream, &taskdef->ITaskDefinition_iface); if (hr != S_OK) goto failed; push_indent(); hr = write_registration_info(stream, taskdef->reginfo); if (hr != S_OK) goto failed; hr = write_triggers(stream, taskdef->triggers); if (hr != S_OK) goto failed; hr = write_principal(stream, taskdef->principal); if (hr != S_OK) goto failed; hr = write_settings(stream, taskdef->taskset); if (hr != S_OK) goto failed; hr = write_actions(stream, taskdef->actions); if (hr != S_OK) goto failed; pop_indent(); write_element_end(stream, Task); IStream_Write(stream, "\0\0", 2, NULL); p = GlobalLock(hmem); *xml = SysAllocString(p); GlobalUnlock(hmem); IStream_Release(stream); return *xml ? S_OK : E_OUTOFMEMORY; failed: IStream_Release(stream); return hr; } static HRESULT read_text_value(IXmlReader *reader, WCHAR **value) { HRESULT hr; XmlNodeType type; while (IXmlReader_Read(reader, &type) == S_OK) { switch (type) { case XmlNodeType_Text: hr = IXmlReader_GetValue(reader, (const WCHAR **)value, NULL); if (hr != S_OK) return hr; TRACE("%s\n", debugstr_w(*value)); return S_OK; case XmlNodeType_Whitespace: case XmlNodeType_Comment: break; default: FIXME("unexpected node type %d\n", type); return E_FAIL; } } return E_FAIL; } static HRESULT read_variantbool_value(IXmlReader *reader, VARIANT_BOOL *vbool) { static const WCHAR trueW[] = {'t','r','u','e',0}; static const WCHAR falseW[] = {'f','a','l','s','e',0}; HRESULT hr; WCHAR *value; hr = read_text_value(reader, &value); if (hr != S_OK) return hr; if (!lstrcmpW(value, trueW)) *vbool = VARIANT_TRUE; else if (!lstrcmpW(value, falseW)) *vbool = VARIANT_FALSE; else { WARN("unexpected bool value %s\n", debugstr_w(value)); return SCHED_E_INVALIDVALUE; } return S_OK; } static HRESULT read_int_value(IXmlReader *reader, int *int_val) { HRESULT hr; WCHAR *value; hr = read_text_value(reader, &value); if (hr != S_OK) return hr; *int_val = wcstol(value, NULL, 10); return S_OK; } static HRESULT read_triggers(IXmlReader *reader, ITaskDefinition *taskdef) { FIXME("stub\n"); return S_OK; } static HRESULT read_principal_attributes(IXmlReader *reader, IPrincipal *principal) { HRESULT hr; const WCHAR *name; const WCHAR *value; hr = IXmlReader_MoveToFirstAttribute(reader); while (hr == S_OK) { hr = IXmlReader_GetLocalName(reader, &name, NULL); if (hr != S_OK) break; hr = IXmlReader_GetValue(reader, &value, NULL); if (hr != S_OK) break; TRACE("%s=%s\n", debugstr_w(name), debugstr_w(value)); if (!lstrcmpW(name, id)) IPrincipal_put_Id(principal, (BSTR)value); else FIXME("unhandled Principal attribute %s\n", debugstr_w(name)); hr = IXmlReader_MoveToNextAttribute(reader); } return S_OK; } static HRESULT read_principal(IXmlReader *reader, IPrincipal *principal) { HRESULT hr; XmlNodeType type; const WCHAR *name; WCHAR *value; if (IXmlReader_IsEmptyElement(reader)) { TRACE("Principal is empty\n"); return S_OK; } read_principal_attributes(reader, principal); while (IXmlReader_Read(reader, &type) == S_OK) { switch (type) { case XmlNodeType_EndElement: hr = IXmlReader_GetLocalName(reader, &name, NULL); if (hr != S_OK) return hr; TRACE("/%s\n", debugstr_w(name)); if (!lstrcmpW(name, principalW)) return S_OK; break; case XmlNodeType_Element: hr = IXmlReader_GetLocalName(reader, &name, NULL); if (hr != S_OK) return hr; TRACE("Element: %s\n", debugstr_w(name)); if (!lstrcmpW(name, UserId)) { hr = read_text_value(reader, &value); if (hr == S_OK) IPrincipal_put_UserId(principal, value); } else if (!lstrcmpW(name, LogonType)) { hr = read_text_value(reader, &value); if (hr == S_OK) { TASK_LOGON_TYPE logon = TASK_LOGON_NONE; if (!lstrcmpW(value, InteractiveToken)) logon = TASK_LOGON_INTERACTIVE_TOKEN; else FIXME("unhandled LogonType %s\n", debugstr_w(value)); IPrincipal_put_LogonType(principal, logon); } } else if (!lstrcmpW(name, RunLevel)) { hr = read_text_value(reader, &value); if (hr == S_OK) { TASK_RUNLEVEL_TYPE level = TASK_RUNLEVEL_LUA; if (!lstrcmpW(value, LeastPrivilege)) level = TASK_RUNLEVEL_LUA; else FIXME("unhandled RunLevel %s\n", debugstr_w(value)); IPrincipal_put_RunLevel(principal, level); } } else FIXME("unhandled Principal element %s\n", debugstr_w(name)); break; case XmlNodeType_Whitespace: case XmlNodeType_Comment: break; default: FIXME("unhandled Principal node type %d\n", type); break; } } WARN("Principal was not terminated\n"); return E_FAIL; } static HRESULT read_principals(IXmlReader *reader, ITaskDefinition *taskdef) { HRESULT hr; XmlNodeType type; const WCHAR *name; if (IXmlReader_IsEmptyElement(reader)) { TRACE("Principals is empty\n"); return S_OK; } while (IXmlReader_Read(reader, &type) == S_OK) { switch (type) { case XmlNodeType_EndElement: hr = IXmlReader_GetLocalName(reader, &name, NULL); if (hr != S_OK) return hr; TRACE("/%s\n", debugstr_w(name)); if (!lstrcmpW(name, Principals)) return S_OK; break; case XmlNodeType_Element: hr = IXmlReader_GetLocalName(reader, &name, NULL); if (hr != S_OK) return hr; TRACE("Element: %s\n", debugstr_w(name)); if (!lstrcmpW(name, principalW)) { IPrincipal *principal; hr = ITaskDefinition_get_Principal(taskdef, &principal); if (hr != S_OK) return hr; hr = read_principal(reader, principal); IPrincipal_Release(principal); } else FIXME("unhandled Principals element %s\n", debugstr_w(name)); break; case XmlNodeType_Whitespace: case XmlNodeType_Comment: break; default: FIXME("unhandled Principals node type %d\n", type); break; } } WARN("Principals was not terminated\n"); return E_FAIL; } static HRESULT read_actions(IXmlReader *reader, ITaskDefinition *taskdef) { FIXME("stub\n"); return S_OK; } static HRESULT read_idle_settings(IXmlReader *reader, ITaskSettings *taskset) { FIXME("stub\n"); return S_OK; } static HRESULT read_settings(IXmlReader *reader, ITaskSettings *taskset) { HRESULT hr; XmlNodeType type; const WCHAR *name; WCHAR *value; VARIANT_BOOL bool_val; int int_val; if (IXmlReader_IsEmptyElement(reader)) { TRACE("Settings is empty\n"); return S_OK; } while (IXmlReader_Read(reader, &type) == S_OK) { switch (type) { case XmlNodeType_EndElement: hr = IXmlReader_GetLocalName(reader, &name, NULL); if (hr != S_OK) return hr; TRACE("/%s\n", debugstr_w(name)); if (!lstrcmpW(name, Settings)) return S_OK; break; case XmlNodeType_Element: hr = IXmlReader_GetLocalName(reader, &name, NULL); if (hr != S_OK) return hr; TRACE("Element: %s\n", debugstr_w(name)); if (!lstrcmpW(name, MultipleInstancesPolicy)) { hr = read_text_value(reader, &value); if (hr == S_OK) { int_val = TASK_INSTANCES_IGNORE_NEW; if (!lstrcmpW(value, IgnoreNew)) int_val = TASK_INSTANCES_IGNORE_NEW; else FIXME("unhandled MultipleInstancesPolicy %s\n", debugstr_w(value)); ITaskSettings_put_MultipleInstances(taskset, int_val); } } else if (!lstrcmpW(name, DisallowStartIfOnBatteries)) { hr = read_variantbool_value(reader, &bool_val); if (hr != S_OK) return hr; ITaskSettings_put_DisallowStartIfOnBatteries(taskset, bool_val); } else if (!lstrcmpW(name, AllowStartOnDemand)) { hr = read_variantbool_value(reader, &bool_val); if (hr != S_OK) return hr; ITaskSettings_put_AllowDemandStart(taskset, bool_val); } else if (!lstrcmpW(name, StopIfGoingOnBatteries)) { hr = read_variantbool_value(reader, &bool_val); if (hr != S_OK) return hr; ITaskSettings_put_StopIfGoingOnBatteries(taskset, bool_val); } else if (!lstrcmpW(name, AllowHardTerminate)) { hr = read_variantbool_value(reader, &bool_val); if (hr != S_OK) return hr; ITaskSettings_put_AllowHardTerminate(taskset, bool_val); } else if (!lstrcmpW(name, StartWhenAvailable)) { hr = read_variantbool_value(reader, &bool_val); if (hr != S_OK) return hr; ITaskSettings_put_StartWhenAvailable(taskset, bool_val); } else if (!lstrcmpW(name, RunOnlyIfNetworkAvailable)) { hr = read_variantbool_value(reader, &bool_val); if (hr != S_OK) return hr; ITaskSettings_put_RunOnlyIfNetworkAvailable(taskset, bool_val); } else if (!lstrcmpW(name, Enabled)) { hr = read_variantbool_value(reader, &bool_val); if (hr != S_OK) return hr; ITaskSettings_put_Enabled(taskset, bool_val); } else if (!lstrcmpW(name, Hidden)) { hr = read_variantbool_value(reader, &bool_val); if (hr != S_OK) return hr; ITaskSettings_put_Hidden(taskset, bool_val); } else if (!lstrcmpW(name, RunOnlyIfIdle)) { hr = read_variantbool_value(reader, &bool_val); if (hr != S_OK) return hr; ITaskSettings_put_RunOnlyIfIdle(taskset, bool_val); } else if (!lstrcmpW(name, WakeToRun)) { hr = read_variantbool_value(reader, &bool_val); if (hr != S_OK) return hr; ITaskSettings_put_WakeToRun(taskset, bool_val); } else if (!lstrcmpW(name, ExecutionTimeLimit)) { hr = read_text_value(reader, &value); if (hr == S_OK) ITaskSettings_put_ExecutionTimeLimit(taskset, value); } else if (!lstrcmpW(name, Priority)) { hr = read_int_value(reader, &int_val); if (hr == S_OK) ITaskSettings_put_Priority(taskset, int_val); } else if (!lstrcmpW(name, IdleSettings)) { hr = read_idle_settings(reader, taskset); if (hr != S_OK) return hr; } else FIXME("unhandled Settings element %s\n", debugstr_w(name)); break; case XmlNodeType_Whitespace: case XmlNodeType_Comment: break; default: FIXME("unhandled Settings node type %d\n", type); break; } } WARN("Settings was not terminated\n"); return SCHED_E_MALFORMEDXML; } static HRESULT read_registration_info(IXmlReader *reader, IRegistrationInfo *info) { HRESULT hr; XmlNodeType type; const WCHAR *name; WCHAR *value; if (IXmlReader_IsEmptyElement(reader)) { TRACE("RegistrationInfo is empty\n"); return S_OK; } while (IXmlReader_Read(reader, &type) == S_OK) { switch (type) { case XmlNodeType_EndElement: hr = IXmlReader_GetLocalName(reader, &name, NULL); if (hr != S_OK) return hr; TRACE("/%s\n", debugstr_w(name)); if (!lstrcmpW(name, RegistrationInfo)) return S_OK; break; case XmlNodeType_Element: hr = IXmlReader_GetLocalName(reader, &name, NULL); if (hr != S_OK) return hr; TRACE("Element: %s\n", debugstr_w(name)); if (!lstrcmpW(name, Author)) { hr = read_text_value(reader, &value); if (hr == S_OK) IRegistrationInfo_put_Author(info, value); } else if (!lstrcmpW(name, Description)) { hr = read_text_value(reader, &value); if (hr == S_OK) IRegistrationInfo_put_Description(info, value); } else if (!lstrcmpW(name, Version)) { hr = read_text_value(reader, &value); if (hr == S_OK) IRegistrationInfo_put_Version(info, value); } else if (!lstrcmpW(name, Date)) { hr = read_text_value(reader, &value); if (hr == S_OK) IRegistrationInfo_put_Date(info, value); } else if (!lstrcmpW(name, Documentation)) { hr = read_text_value(reader, &value); if (hr == S_OK) IRegistrationInfo_put_Documentation(info, value); } else if (!lstrcmpW(name, URI)) { hr = read_text_value(reader, &value); if (hr == S_OK) IRegistrationInfo_put_URI(info, value); } else if (!lstrcmpW(name, Source)) { hr = read_text_value(reader, &value); if (hr == S_OK) IRegistrationInfo_put_Source(info, value); } else FIXME("unhandled RegistrationInfo element %s\n", debugstr_w(name)); break; case XmlNodeType_Whitespace: case XmlNodeType_Comment: break; default: FIXME("unhandled RegistrationInfo node type %d\n", type); break; } } WARN("RegistrationInfo was not terminated\n"); return SCHED_E_MALFORMEDXML; } static HRESULT read_task_attributes(IXmlReader *reader, ITaskDefinition *taskdef) { HRESULT hr; ITaskSettings *taskset; const WCHAR *name; const WCHAR *value; BOOL xmlns_ok = FALSE; TRACE("\n"); hr = ITaskDefinition_get_Settings(taskdef, &taskset); if (hr != S_OK) return hr; hr = IXmlReader_MoveToFirstAttribute(reader); while (hr == S_OK) { hr = IXmlReader_GetLocalName(reader, &name, NULL); if (hr != S_OK) break; hr = IXmlReader_GetValue(reader, &value, NULL); if (hr != S_OK) break; TRACE("%s=%s\n", debugstr_w(name), debugstr_w(value)); if (!lstrcmpW(name, version)) { TASK_COMPATIBILITY compatibility = TASK_COMPATIBILITY_V2; if (!lstrcmpW(value, v1_0)) compatibility = TASK_COMPATIBILITY_AT; else if (!lstrcmpW(value, v1_1)) compatibility = TASK_COMPATIBILITY_V1; else if (!lstrcmpW(value, v1_2)) compatibility = TASK_COMPATIBILITY_V2; else if (!lstrcmpW(value, v1_3)) compatibility = TASK_COMPATIBILITY_V2_1; else FIXME("unknown version %s\n", debugstr_w(value)); ITaskSettings_put_Compatibility(taskset, compatibility); } else if (!lstrcmpW(name, xmlns)) { if (lstrcmpW(value, task_ns)) { FIXME("unknown namespace %s\n", debugstr_w(value)); break; } xmlns_ok = TRUE; } else FIXME("unhandled Task attribute %s\n", debugstr_w(name)); hr = IXmlReader_MoveToNextAttribute(reader); } ITaskSettings_Release(taskset); return xmlns_ok ? S_OK : SCHED_E_NAMESPACE; } static HRESULT read_task(IXmlReader *reader, ITaskDefinition *taskdef) { HRESULT hr; XmlNodeType type; const WCHAR *name; if (IXmlReader_IsEmptyElement(reader)) { TRACE("Task is empty\n"); return S_OK; } while (IXmlReader_Read(reader, &type) == S_OK) { switch (type) { case XmlNodeType_EndElement: hr = IXmlReader_GetLocalName(reader, &name, NULL); if (hr != S_OK) return hr; TRACE("/%s\n", debugstr_w(name)); if (!lstrcmpW(name, Task)) return S_OK; break; case XmlNodeType_Element: hr = IXmlReader_GetLocalName(reader, &name, NULL); if (hr != S_OK) return hr; TRACE("Element: %s\n", debugstr_w(name)); if (!lstrcmpW(name, RegistrationInfo)) { IRegistrationInfo *info; hr = ITaskDefinition_get_RegistrationInfo(taskdef, &info); if (hr != S_OK) return hr; hr = read_registration_info(reader, info); IRegistrationInfo_Release(info); } else if (!lstrcmpW(name, Settings)) { ITaskSettings *taskset; hr = ITaskDefinition_get_Settings(taskdef, &taskset); if (hr != S_OK) return hr; hr = read_settings(reader, taskset); ITaskSettings_Release(taskset); } else if (!lstrcmpW(name, Triggers)) hr = read_triggers(reader, taskdef); else if (!lstrcmpW(name, Principals)) hr = read_principals(reader, taskdef); else if (!lstrcmpW(name, actionsW)) hr = read_actions(reader, taskdef); else FIXME("unhandled Task element %s\n", debugstr_w(name)); if (hr != S_OK) return hr; break; case XmlNodeType_Comment: case XmlNodeType_Whitespace: break; default: FIXME("unhandled Task node type %d\n", type); break; } } WARN("Task was not terminated\n"); return SCHED_E_MALFORMEDXML; } static HRESULT read_xml(IXmlReader *reader, ITaskDefinition *taskdef) { HRESULT hr; XmlNodeType type; const WCHAR *name; while (IXmlReader_Read(reader, &type) == S_OK) { switch (type) { case XmlNodeType_XmlDeclaration: TRACE("XmlDeclaration\n"); break; case XmlNodeType_Element: hr = IXmlReader_GetLocalName(reader, &name, NULL); if (hr != S_OK) return hr; TRACE("Element: %s\n", debugstr_w(name)); if (!lstrcmpW(name, Task)) { hr = read_task_attributes(reader, taskdef); if (hr != S_OK) return hr; return read_task(reader, taskdef); } else FIXME("unhandled XML element %s\n", debugstr_w(name)); break; case XmlNodeType_Comment: case XmlNodeType_Whitespace: break; default: FIXME("unhandled XML node type %d\n", type); break; } } WARN("Task definition was not found\n"); return SCHED_E_MALFORMEDXML; } static HRESULT WINAPI TaskDefinition_put_XmlText(ITaskDefinition *iface, BSTR xml) { TaskDefinition *taskdef = impl_from_ITaskDefinition(iface); HRESULT hr; IStream *stream; IXmlReader *reader; HGLOBAL hmem; void *buf; TRACE("%p,%s\n", iface, debugstr_w(xml)); if (!xml) return E_INVALIDARG; hmem = GlobalAlloc(0, lstrlenW(xml) * sizeof(WCHAR)); if (!hmem) return E_OUTOFMEMORY; buf = GlobalLock(hmem); memcpy(buf, xml, lstrlenW(xml) * sizeof(WCHAR)); GlobalUnlock(hmem); hr = CreateStreamOnHGlobal(hmem, TRUE, &stream); if (hr != S_OK) { GlobalFree(hmem); return hr; } hr = CreateXmlReader(&IID_IXmlReader, (void **)&reader, NULL); if (hr != S_OK) { IStream_Release(stream); return hr; } hr = IXmlReader_SetInput(reader, (IUnknown *)stream); if (hr == S_OK) { if (taskdef->reginfo) { IRegistrationInfo_Release(taskdef->reginfo); taskdef->reginfo = NULL; } if (taskdef->taskset) { ITaskSettings_Release(taskdef->taskset); taskdef->taskset = NULL; } if (taskdef->triggers) { ITriggerCollection_Release(taskdef->triggers); taskdef->triggers = NULL; } if (taskdef->principal) { IPrincipal_Release(taskdef->principal); taskdef->principal = NULL; } if (taskdef->actions) { IActionCollection_Release(taskdef->actions); taskdef->actions = NULL; } hr = read_xml(reader, iface); } IXmlReader_Release(reader); IStream_Release(stream); return hr; } static const ITaskDefinitionVtbl TaskDefinition_vtbl = { TaskDefinition_QueryInterface, TaskDefinition_AddRef, TaskDefinition_Release, TaskDefinition_GetTypeInfoCount, TaskDefinition_GetTypeInfo, TaskDefinition_GetIDsOfNames, TaskDefinition_Invoke, TaskDefinition_get_RegistrationInfo, TaskDefinition_put_RegistrationInfo, TaskDefinition_get_Triggers, TaskDefinition_put_Triggers, TaskDefinition_get_Settings, TaskDefinition_put_Settings, TaskDefinition_get_Data, TaskDefinition_put_Data, TaskDefinition_get_Principal, TaskDefinition_put_Principal, TaskDefinition_get_Actions, TaskDefinition_put_Actions, TaskDefinition_get_XmlText, TaskDefinition_put_XmlText }; HRESULT TaskDefinition_create(ITaskDefinition **obj) { TaskDefinition *taskdef; taskdef = heap_alloc_zero(sizeof(*taskdef)); if (!taskdef) return E_OUTOFMEMORY; taskdef->ITaskDefinition_iface.lpVtbl = &TaskDefinition_vtbl; taskdef->ref = 1; *obj = &taskdef->ITaskDefinition_iface; TRACE("created %p\n", *obj); return S_OK; } typedef struct { ITaskService ITaskService_iface; LONG ref; BOOL connected; DWORD version; WCHAR comp_name[MAX_COMPUTERNAME_LENGTH + 1]; } TaskService; static inline TaskService *impl_from_ITaskService(ITaskService *iface) { return CONTAINING_RECORD(iface, TaskService, ITaskService_iface); } static ULONG WINAPI TaskService_AddRef(ITaskService *iface) { TaskService *task_svc = impl_from_ITaskService(iface); return InterlockedIncrement(&task_svc->ref); } static ULONG WINAPI TaskService_Release(ITaskService *iface) { TaskService *task_svc = impl_from_ITaskService(iface); LONG ref = InterlockedDecrement(&task_svc->ref); if (!ref) { TRACE("destroying %p\n", iface); heap_free(task_svc); } return ref; } static HRESULT WINAPI TaskService_QueryInterface(ITaskService *iface, REFIID riid, void **obj) { if (!riid || !obj) return E_INVALIDARG; TRACE("%p,%s,%p\n", iface, debugstr_guid(riid), obj); if (IsEqualGUID(riid, &IID_ITaskService) || IsEqualGUID(riid, &IID_IDispatch) || IsEqualGUID(riid, &IID_IUnknown)) { ITaskService_AddRef(iface); *obj = iface; return S_OK; } FIXME("interface %s is not implemented\n", debugstr_guid(riid)); *obj = NULL; return E_NOINTERFACE; } static HRESULT WINAPI TaskService_GetTypeInfoCount(ITaskService *iface, UINT *count) { FIXME("%p,%p: stub\n", iface, count); return E_NOTIMPL; } static HRESULT WINAPI TaskService_GetTypeInfo(ITaskService *iface, UINT index, LCID lcid, ITypeInfo **info) { FIXME("%p,%u,%u,%p: stub\n", iface, index, lcid, info); return E_NOTIMPL; } static HRESULT WINAPI TaskService_GetIDsOfNames(ITaskService *iface, REFIID riid, LPOLESTR *names, UINT count, LCID lcid, DISPID *dispid) { FIXME("%p,%s,%p,%u,%u,%p: stub\n", iface, debugstr_guid(riid), names, count, lcid, dispid); return E_NOTIMPL; } static HRESULT WINAPI TaskService_Invoke(ITaskService *iface, DISPID dispid, REFIID riid, LCID lcid, WORD flags, DISPPARAMS *params, VARIANT *result, EXCEPINFO *excepinfo, UINT *argerr) { FIXME("%p,%d,%s,%04x,%04x,%p,%p,%p,%p: stub\n", iface, dispid, debugstr_guid(riid), lcid, flags, params, result, excepinfo, argerr); return E_NOTIMPL; } static HRESULT WINAPI TaskService_GetFolder(ITaskService *iface, BSTR path, ITaskFolder **folder) { TaskService *task_svc = impl_from_ITaskService(iface); TRACE("%p,%s,%p\n", iface, debugstr_w(path), folder); if (!folder) return E_POINTER; if (!task_svc->connected) return HRESULT_FROM_WIN32(ERROR_ONLY_IF_CONNECTED); return TaskFolder_create(path, NULL, folder, FALSE); } static HRESULT WINAPI TaskService_GetRunningTasks(ITaskService *iface, LONG flags, IRunningTaskCollection **tasks) { FIXME("%p,%x,%p: stub\n", iface, flags, tasks); return E_NOTIMPL; } static HRESULT WINAPI TaskService_NewTask(ITaskService *iface, DWORD flags, ITaskDefinition **definition) { TRACE("%p,%x,%p\n", iface, flags, definition); if (!definition) return E_POINTER; if (flags) FIXME("unsupported flags %x\n", flags); return TaskDefinition_create(definition); } static inline BOOL is_variant_null(const VARIANT *var) { return V_VT(var) == VT_EMPTY || V_VT(var) == VT_NULL || (V_VT(var) == VT_BSTR && (V_BSTR(var) == NULL || !*V_BSTR(var))); } static HRESULT start_schedsvc(void) { static const WCHAR scheduleW[] = { 'S','c','h','e','d','u','l','e',0 }; SC_HANDLE scm, service; SERVICE_STATUS_PROCESS status; ULONGLONG start_time; HRESULT hr = SCHED_E_SERVICE_NOT_RUNNING; TRACE("Trying to start %s service\n", debugstr_w(scheduleW)); scm = OpenSCManagerW(NULL, NULL, 0); if (!scm) return SCHED_E_SERVICE_NOT_INSTALLED; service = OpenServiceW(scm, scheduleW, SERVICE_START | SERVICE_QUERY_STATUS); if (service) { if (StartServiceW(service, 0, NULL) || GetLastError() == ERROR_SERVICE_ALREADY_RUNNING) { start_time = GetTickCount64(); do { DWORD dummy; if (!QueryServiceStatusEx(service, SC_STATUS_PROCESS_INFO, (BYTE *)&status, sizeof(status), &dummy)) { WARN("failed to query scheduler status (%u)\n", GetLastError()); break; } if (status.dwCurrentState == SERVICE_RUNNING) { hr = S_OK; break; } if (GetTickCount64() - start_time > 30000) break; Sleep(1000); } while (status.dwCurrentState == SERVICE_START_PENDING); if (status.dwCurrentState != SERVICE_RUNNING) WARN("scheduler failed to start %u\n", status.dwCurrentState); } else WARN("failed to start scheduler service (%u)\n", GetLastError()); CloseServiceHandle(service); } else WARN("failed to open scheduler service (%u)\n", GetLastError()); CloseServiceHandle(scm); return hr; } static HRESULT WINAPI TaskService_Connect(ITaskService *iface, VARIANT server, VARIANT user, VARIANT domain, VARIANT password) { static WCHAR ncalrpc[] = { 'n','c','a','l','r','p','c',0 }; TaskService *task_svc = impl_from_ITaskService(iface); WCHAR comp_name[MAX_COMPUTERNAME_LENGTH + 1]; DWORD len; HRESULT hr; RPC_WSTR binding_str; extern handle_t schrpc_handle; TRACE("%p,%s,%s,%s,%s\n", iface, debugstr_variant(&server), debugstr_variant(&user), debugstr_variant(&domain), debugstr_variant(&password)); if (!is_variant_null(&user) || !is_variant_null(&domain) || !is_variant_null(&password)) FIXME("user/domain/password are ignored\n"); len = ARRAY_SIZE(comp_name); if (!GetComputerNameW(comp_name, &len)) return HRESULT_FROM_WIN32(GetLastError()); if (!is_variant_null(&server)) { const WCHAR *server_name; if (V_VT(&server) != VT_BSTR) { FIXME("server variant type %d is not supported\n", V_VT(&server)); return HRESULT_FROM_WIN32(ERROR_BAD_NETPATH); } /* skip UNC prefix if any */ server_name = V_BSTR(&server); if (server_name[0] == '\\' && server_name[1] == '\\') server_name += 2; if (wcsicmp(server_name, comp_name)) { FIXME("connection to remote server %s is not supported\n", debugstr_w(V_BSTR(&server))); return HRESULT_FROM_WIN32(ERROR_BAD_NETPATH); } } hr = start_schedsvc(); if (hr != S_OK) return hr; hr = RpcStringBindingComposeW(NULL, ncalrpc, NULL, NULL, NULL, &binding_str); if (hr != RPC_S_OK) return hr; hr = RpcBindingFromStringBindingW(binding_str, &schrpc_handle); RpcStringFreeW(&binding_str); if (hr != RPC_S_OK) return hr; /* Make sure that the connection works */ hr = SchRpcHighestVersion(&task_svc->version); if (hr != S_OK) return hr; TRACE("server version %#x\n", task_svc->version); lstrcpyW(task_svc->comp_name, comp_name); task_svc->connected = TRUE; return S_OK; } static HRESULT WINAPI TaskService_get_Connected(ITaskService *iface, VARIANT_BOOL *connected) { TaskService *task_svc = impl_from_ITaskService(iface); TRACE("%p,%p\n", iface, connected); if (!connected) return E_POINTER; *connected = task_svc->connected ? VARIANT_TRUE : VARIANT_FALSE; return S_OK; } static HRESULT WINAPI TaskService_get_TargetServer(ITaskService *iface, BSTR *server) { TaskService *task_svc = impl_from_ITaskService(iface); TRACE("%p,%p\n", iface, server); if (!server) return E_POINTER; if (!task_svc->connected) return HRESULT_FROM_WIN32(ERROR_ONLY_IF_CONNECTED); *server = SysAllocString(task_svc->comp_name); if (!*server) return E_OUTOFMEMORY; return S_OK; } static HRESULT WINAPI TaskService_get_ConnectedUser(ITaskService *iface, BSTR *user) { FIXME("%p,%p: stub\n", iface, user); return E_NOTIMPL; } static HRESULT WINAPI TaskService_get_ConnectedDomain(ITaskService *iface, BSTR *domain) { FIXME("%p,%p: stub\n", iface, domain); return E_NOTIMPL; } static HRESULT WINAPI TaskService_get_HighestVersion(ITaskService *iface, DWORD *version) { TaskService *task_svc = impl_from_ITaskService(iface); TRACE("%p,%p\n", iface, version); if (!version) return E_POINTER; if (!task_svc->connected) return HRESULT_FROM_WIN32(ERROR_ONLY_IF_CONNECTED); *version = task_svc->version; return S_OK; } static const ITaskServiceVtbl TaskService_vtbl = { TaskService_QueryInterface, TaskService_AddRef, TaskService_Release, TaskService_GetTypeInfoCount, TaskService_GetTypeInfo, TaskService_GetIDsOfNames, TaskService_Invoke, TaskService_GetFolder, TaskService_GetRunningTasks, TaskService_NewTask, TaskService_Connect, TaskService_get_Connected, TaskService_get_TargetServer, TaskService_get_ConnectedUser, TaskService_get_ConnectedDomain, TaskService_get_HighestVersion }; HRESULT TaskService_create(void **obj) { TaskService *task_svc; task_svc = heap_alloc(sizeof(*task_svc)); if (!task_svc) return E_OUTOFMEMORY; task_svc->ITaskService_iface.lpVtbl = &TaskService_vtbl; task_svc->ref = 1; task_svc->connected = FALSE; *obj = &task_svc->ITaskService_iface; TRACE("created %p\n", *obj); return S_OK; } void __RPC_FAR *__RPC_USER MIDL_user_allocate(SIZE_T n) { return HeapAlloc(GetProcessHeap(), 0, n); } void __RPC_USER MIDL_user_free(void __RPC_FAR *p) { HeapFree(GetProcessHeap(), 0, p); }