From 3b1e5c81f4c75d3c5e14df3f54854cebded89d1d Mon Sep 17 00:00:00 2001 From: Dmitry Timoshkov Date: Mon, 14 May 2018 15:49:25 +0800 Subject: [PATCH] mstask: Move trigger management to the ITask implementation. Signed-off-by: Dmitry Timoshkov Signed-off-by: Alexandre Julliard --- dlls/mstask/mstask_private.h | 4 +- dlls/mstask/task.c | 193 ++++++++++++++-- dlls/mstask/task_trigger.c | 475 +++++++++++++-------------------------- dlls/mstask/tests/task_trigger.c | 11 - 4 files changed, 339 insertions(+), 344 deletions(-) rewrite dlls/mstask/task_trigger.c (71%) diff --git a/dlls/mstask/mstask_private.h b/dlls/mstask/mstask_private.h index 038c6c84c1c..dbaf5433b0e 100644 --- a/dlls/mstask/mstask_private.h +++ b/dlls/mstask/mstask_private.h @@ -27,9 +27,11 @@ extern LONG dll_ref DECLSPEC_HIDDEN; typedef struct ClassFactoryImpl ClassFactoryImpl; extern ClassFactoryImpl MSTASK_ClassFactory DECLSPEC_HIDDEN; -extern HRESULT TaskTriggerConstructor(LPVOID *ppObj) DECLSPEC_HIDDEN; +extern HRESULT TaskTriggerConstructor(ITask *task, WORD idx, ITaskTrigger **trigger) DECLSPEC_HIDDEN; extern HRESULT TaskSchedulerConstructor(LPVOID *ppObj) DECLSPEC_HIDDEN; extern HRESULT TaskConstructor(ITaskService *service, const WCHAR *task_name, ITask **task) DECLSPEC_HIDDEN; +extern HRESULT task_set_trigger(ITask *task, WORD idx, const TASK_TRIGGER *trigger) DECLSPEC_HIDDEN; +extern HRESULT task_get_trigger(ITask *task, WORD idx, TASK_TRIGGER *trigger) DECLSPEC_HIDDEN; static inline WCHAR *heap_strdupW(const WCHAR *src) { diff --git a/dlls/mstask/task.c b/dlls/mstask/task.c index 68452afa4fb..5129d9a513e 100644 --- a/dlls/mstask/task.c +++ b/dlls/mstask/task.c @@ -23,6 +23,7 @@ #include "windef.h" #include "winbase.h" +#include "winternl.h" #include "objbase.h" #include "taskschd.h" #include "mstask.h" @@ -144,15 +145,176 @@ static ULONG WINAPI MSTASK_ITask_Release( return ref; } +HRESULT task_set_trigger(ITask *task, WORD idx, const TASK_TRIGGER *src) +{ + TaskImpl *This = impl_from_ITask(task); + TIME_FIELDS field_time; + LARGE_INTEGER sys_time; + TASK_TRIGGER dst; + + TRACE("(%p, %u, %p)\n", task, idx, src); + + if (idx >= This->trigger_count) + return E_FAIL; + + /* Verify valid structure size */ + if (src->cbTriggerSize != sizeof(*src)) + return E_INVALIDARG; + dst.cbTriggerSize = src->cbTriggerSize; + + /* Reserved field must be zero */ + dst.Reserved1 = 0; + + /* Verify and set valid start date and time */ + memset(&field_time, 0, sizeof(field_time)); + field_time.Year = src->wBeginYear; + field_time.Month = src->wBeginMonth; + field_time.Day = src->wBeginDay; + field_time.Hour = src->wStartHour; + field_time.Minute = src->wStartMinute; + if (!RtlTimeFieldsToTime(&field_time, &sys_time)) + return E_INVALIDARG; + dst.wBeginYear = src->wBeginYear; + dst.wBeginMonth = src->wBeginMonth; + dst.wBeginDay = src->wBeginDay; + dst.wStartHour = src->wStartHour; + dst.wStartMinute = src->wStartMinute; + + /* Verify valid end date if TASK_TRIGGER_FLAG_HAS_END_DATE flag is set */ + if (src->rgFlags & TASK_TRIGGER_FLAG_HAS_END_DATE) + { + memset(&field_time, 0, sizeof(field_time)); + field_time.Year = src->wEndYear; + field_time.Month = src->wEndMonth; + field_time.Day = src->wEndDay; + if (!RtlTimeFieldsToTime(&field_time, &sys_time)) + return E_INVALIDARG; + } + + /* Set valid end date independent of TASK_TRIGGER_FLAG_HAS_END_DATE flag */ + dst.wEndYear = src->wEndYear; + dst.wEndMonth = src->wEndMonth; + dst.wEndDay = src->wEndDay; + + /* Verify duration and interval pair */ + if (src->MinutesDuration <= src->MinutesInterval && src->MinutesInterval > 0) + return E_INVALIDARG; + dst.MinutesDuration = src->MinutesDuration; + dst.MinutesInterval = src->MinutesInterval; + + /* Copy over flags */ + dst.rgFlags = src->rgFlags; + + /* Set TriggerType dependent fields of Type union */ + dst.TriggerType = src->TriggerType; + switch (src->TriggerType) + { + case TASK_TIME_TRIGGER_DAILY: + dst.Type.Daily.DaysInterval = src->Type.Daily.DaysInterval; + break; + case TASK_TIME_TRIGGER_WEEKLY: + dst.Type.Weekly.WeeksInterval = src->Type.Weekly.WeeksInterval; + dst.Type.Weekly.rgfDaysOfTheWeek = src->Type.Weekly.rgfDaysOfTheWeek; + break; + case TASK_TIME_TRIGGER_MONTHLYDATE: + dst.Type.MonthlyDate.rgfDays = src->Type.MonthlyDate.rgfDays; + dst.Type.MonthlyDate.rgfMonths = src->Type.MonthlyDate.rgfMonths; + break; + case TASK_TIME_TRIGGER_MONTHLYDOW: + dst.Type.MonthlyDOW.wWhichWeek = src->Type.MonthlyDOW.wWhichWeek; + dst.Type.MonthlyDOW.rgfDaysOfTheWeek = src->Type.MonthlyDOW.rgfDaysOfTheWeek; + dst.Type.MonthlyDOW.rgfMonths = src->Type.MonthlyDOW.rgfMonths; + break; + case TASK_TIME_TRIGGER_ONCE: + case TASK_EVENT_TRIGGER_ON_IDLE: + case TASK_EVENT_TRIGGER_AT_SYSTEMSTART: + case TASK_EVENT_TRIGGER_AT_LOGON: + default: + dst.Type = src->Type; + break; + } + + /* Reserved field must be zero */ + dst.Reserved2 = 0; + + /* wRandomMinutesInterval not currently used and is initialized to zero */ + dst.wRandomMinutesInterval = 0; + + This->trigger[idx] = dst; + + return S_OK; +} + +HRESULT task_get_trigger(ITask *task, WORD idx, TASK_TRIGGER *dst) +{ + TaskImpl *This = impl_from_ITask(task); + TASK_TRIGGER *src; + + TRACE("(%p, %u, %p)\n", task, idx, dst); + + if (idx >= This->trigger_count) + return SCHED_E_TRIGGER_NOT_FOUND; + + src = &This->trigger[idx]; + + /* Native implementation doesn't verify equivalent cbTriggerSize fields */ + + /* Copy relevant fields of the structure */ + dst->cbTriggerSize = src->cbTriggerSize; + dst->Reserved1 = 0; + dst->wBeginYear = src->wBeginYear; + dst->wBeginMonth = src->wBeginMonth; + dst->wBeginDay = src->wBeginDay; + dst->wEndYear = src->wEndYear; + dst->wEndMonth = src->wEndMonth; + dst->wEndDay = src->wEndDay; + dst->wStartHour = src->wStartHour; + dst->wStartMinute = src->wStartMinute; + dst->MinutesDuration = src->MinutesDuration; + dst->MinutesInterval = src->MinutesInterval; + dst->rgFlags = src->rgFlags; + dst->TriggerType = src->TriggerType; + switch (src->TriggerType) + { + case TASK_TIME_TRIGGER_DAILY: + dst->Type.Daily.DaysInterval = src->Type.Daily.DaysInterval; + break; + case TASK_TIME_TRIGGER_WEEKLY: + dst->Type.Weekly.WeeksInterval = src->Type.Weekly.WeeksInterval; + dst->Type.Weekly.rgfDaysOfTheWeek = src->Type.Weekly.rgfDaysOfTheWeek; + break; + case TASK_TIME_TRIGGER_MONTHLYDATE: + dst->Type.MonthlyDate.rgfDays = src->Type.MonthlyDate.rgfDays; + dst->Type.MonthlyDate.rgfMonths = src->Type.MonthlyDate.rgfMonths; + break; + case TASK_TIME_TRIGGER_MONTHLYDOW: + dst->Type.MonthlyDOW.wWhichWeek = src->Type.MonthlyDOW.wWhichWeek; + dst->Type.MonthlyDOW.rgfDaysOfTheWeek = src->Type.MonthlyDOW.rgfDaysOfTheWeek; + dst->Type.MonthlyDOW.rgfMonths = src->Type.MonthlyDOW.rgfMonths; + break; + case TASK_TIME_TRIGGER_ONCE: + case TASK_EVENT_TRIGGER_ON_IDLE: + case TASK_EVENT_TRIGGER_AT_SYSTEMSTART: + case TASK_EVENT_TRIGGER_AT_LOGON: + default: + break; + } + dst->Reserved2 = 0; + dst->wRandomMinutesInterval = 0; + + return S_OK; +} + static HRESULT WINAPI MSTASK_ITask_CreateTrigger(ITask *iface, WORD *idx, ITaskTrigger **task_trigger) { TaskImpl *This = impl_from_ITask(iface); TASK_TRIGGER *new_trigger; + SYSTEMTIME time; HRESULT hr; TRACE("(%p, %p, %p)\n", iface, idx, task_trigger); - hr = TaskTriggerConstructor((void **)task_trigger); + hr = TaskTriggerConstructor(iface, This->trigger_count, task_trigger); if (hr != S_OK) return hr; if (This->trigger) @@ -167,9 +329,22 @@ static HRESULT WINAPI MSTASK_ITask_CreateTrigger(ITask *iface, WORD *idx, ITaskT This->trigger = new_trigger; - hr = ITaskTrigger_GetTrigger(*task_trigger, &This->trigger[This->trigger_count]); - if (hr == S_OK) - *idx = This->trigger_count++; + new_trigger = &This->trigger[This->trigger_count]; + + /* Most fields default to zero. Initialize other fields to default values. */ + memset(new_trigger, 0, sizeof(*new_trigger)); + GetLocalTime(&time); + new_trigger->cbTriggerSize = sizeof(*new_trigger); + new_trigger->wBeginYear = time.wYear; + new_trigger->wBeginMonth = time.wMonth; + new_trigger->wBeginDay = time.wDay; + new_trigger->wStartHour = time.wHour; + new_trigger->wStartMinute = time.wMinute; + new_trigger->rgFlags = TASK_TRIGGER_FLAG_DISABLED; + new_trigger->TriggerType = TASK_TIME_TRIGGER_DAILY, + new_trigger->Type.Daily.DaysInterval = 1; + + *idx = This->trigger_count++; return hr; } @@ -204,21 +379,13 @@ static HRESULT WINAPI MSTASK_ITask_GetTriggerCount(ITask *iface, WORD *count) static HRESULT WINAPI MSTASK_ITask_GetTrigger(ITask *iface, WORD idx, ITaskTrigger **trigger) { TaskImpl *This = impl_from_ITask(iface); - HRESULT hr; TRACE("(%p, %u, %p)\n", iface, idx, trigger); if (idx >= This->trigger_count) return SCHED_E_TRIGGER_NOT_FOUND; - hr = TaskTriggerConstructor((void **)trigger); - if (hr != S_OK) return hr; - - hr = ITaskTrigger_SetTrigger(*trigger, &This->trigger[idx]); - if (hr != S_OK) - ITaskTrigger_Release(*trigger); - - return hr; + return TaskTriggerConstructor(iface, idx, trigger); } static HRESULT WINAPI MSTASK_ITask_GetTriggerString( diff --git a/dlls/mstask/task_trigger.c b/dlls/mstask/task_trigger.c dissimilarity index 71% index 0f24e1f9981..e3f190a315a 100644 --- a/dlls/mstask/task_trigger.c +++ b/dlls/mstask/task_trigger.c @@ -1,319 +1,156 @@ -/* - * Copyright (C) 2008 Google (Roy Shea) - * - * 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 - -#define COBJMACROS - -#include "windef.h" -#include "winbase.h" -#include "objbase.h" -#include "winternl.h" -#include "taskschd.h" -#include "mstask.h" -#include "mstask_private.h" -#include "wine/debug.h" - -WINE_DEFAULT_DEBUG_CHANNEL(mstask); - -typedef struct -{ - ITaskTrigger ITaskTrigger_iface; - LONG ref; - TASK_TRIGGER triggerCond; -} TaskTriggerImpl; - -static inline TaskTriggerImpl *impl_from_ITaskTrigger(ITaskTrigger *iface) -{ - return CONTAINING_RECORD(iface, TaskTriggerImpl, ITaskTrigger_iface); -} - -static HRESULT WINAPI MSTASK_ITaskTrigger_QueryInterface( - ITaskTrigger* iface, - REFIID riid, - void **ppvObject) -{ - TaskTriggerImpl *This = impl_from_ITaskTrigger(iface); - - TRACE("IID: %s\n", debugstr_guid(riid)); - if (ppvObject == NULL) - return E_POINTER; - - if (IsEqualGUID(riid, &IID_IUnknown) || - IsEqualGUID(riid, &IID_ITaskTrigger)) - { - *ppvObject = &This->ITaskTrigger_iface; - ITaskTrigger_AddRef(iface); - return S_OK; - } - - WARN("Unknown interface: %s\n", debugstr_guid(riid)); - *ppvObject = NULL; - return E_NOINTERFACE; -} - -static ULONG WINAPI MSTASK_ITaskTrigger_AddRef( - ITaskTrigger* iface) -{ - TaskTriggerImpl *This = impl_from_ITaskTrigger(iface); - ULONG ref; - TRACE("\n"); - ref = InterlockedIncrement(&This->ref); - return ref; -} - -static ULONG WINAPI MSTASK_ITaskTrigger_Release( - ITaskTrigger* iface) -{ - TaskTriggerImpl *This = impl_from_ITaskTrigger(iface); - ULONG ref; - TRACE("\n"); - ref = InterlockedDecrement(&This->ref); - if (ref == 0) - { - heap_free(This); - InterlockedDecrement(&dll_ref); - } - return ref; -} - -static HRESULT WINAPI MSTASK_ITaskTrigger_SetTrigger( - ITaskTrigger* iface, - const PTASK_TRIGGER pTrigger) -{ - TaskTriggerImpl * This = impl_from_ITaskTrigger(iface); - TIME_FIELDS field_time; - LARGE_INTEGER sys_time; - TASK_TRIGGER tmp_trigger_cond; - - TRACE("(%p, %p)\n", iface, pTrigger); - - if (!pTrigger) return E_INVALIDARG; - - /* Verify valid structure size */ - if (pTrigger->cbTriggerSize != sizeof(*pTrigger)) - return E_INVALIDARG; - tmp_trigger_cond.cbTriggerSize = pTrigger->cbTriggerSize; - - /* Reserved field must be zero */ - tmp_trigger_cond.Reserved1 = 0; - - /* Verify and set valid start date and time */ - memset(&field_time, 0, sizeof(field_time)); - field_time.Year = pTrigger->wBeginYear; - field_time.Month = pTrigger->wBeginMonth; - field_time.Day = pTrigger->wBeginDay; - field_time.Hour = pTrigger->wStartHour; - field_time.Minute = pTrigger->wStartMinute; - if (!RtlTimeFieldsToTime(&field_time, &sys_time)) - return E_INVALIDARG; - tmp_trigger_cond.wBeginYear = pTrigger->wBeginYear; - tmp_trigger_cond.wBeginMonth = pTrigger->wBeginMonth; - tmp_trigger_cond.wBeginDay = pTrigger->wBeginDay; - tmp_trigger_cond.wStartHour = pTrigger->wStartHour; - tmp_trigger_cond.wStartMinute = pTrigger->wStartMinute; - - /* Verify valid end date if TASK_TRIGGER_FLAG_HAS_END_DATE flag is set */ - if (pTrigger->rgFlags & TASK_TRIGGER_FLAG_HAS_END_DATE) - { - memset(&field_time, 0, sizeof(field_time)); - field_time.Year = pTrigger->wEndYear; - field_time.Month = pTrigger->wEndMonth; - field_time.Day = pTrigger->wEndDay; - if (!RtlTimeFieldsToTime(&field_time, &sys_time)) - return E_INVALIDARG; - } - - /* Set valid end date independent of TASK_TRIGGER_FLAG_HAS_END_DATE flag */ - tmp_trigger_cond.wEndYear = pTrigger->wEndYear; - tmp_trigger_cond.wEndMonth = pTrigger->wEndMonth; - tmp_trigger_cond.wEndDay = pTrigger->wEndDay; - - /* Verify duration and interval pair */ - if (pTrigger->MinutesDuration <= pTrigger->MinutesInterval && - pTrigger->MinutesInterval > 0) - return E_INVALIDARG; - tmp_trigger_cond.MinutesDuration = pTrigger->MinutesDuration; - tmp_trigger_cond.MinutesInterval = pTrigger->MinutesInterval; - - /* Copy over flags */ - tmp_trigger_cond.rgFlags = pTrigger->rgFlags; - - /* Set TriggerType dependent fields of Type union */ - tmp_trigger_cond.TriggerType = pTrigger->TriggerType; - switch (pTrigger->TriggerType) - { - case TASK_TIME_TRIGGER_DAILY: - tmp_trigger_cond.Type.Daily.DaysInterval = - pTrigger->Type.Daily.DaysInterval; - break; - case TASK_TIME_TRIGGER_WEEKLY: - tmp_trigger_cond.Type.Weekly.WeeksInterval = - pTrigger->Type.Weekly.WeeksInterval; - tmp_trigger_cond.Type.Weekly.rgfDaysOfTheWeek = - pTrigger->Type.Weekly.rgfDaysOfTheWeek; - break; - case TASK_TIME_TRIGGER_MONTHLYDATE: - tmp_trigger_cond.Type.MonthlyDate.rgfDays = - pTrigger->Type.MonthlyDate.rgfDays; - tmp_trigger_cond.Type.MonthlyDate.rgfMonths = - pTrigger->Type.MonthlyDate.rgfMonths; - break; - case TASK_TIME_TRIGGER_MONTHLYDOW: - tmp_trigger_cond.Type.MonthlyDOW.wWhichWeek = - pTrigger->Type.MonthlyDOW.wWhichWeek; - tmp_trigger_cond.Type.MonthlyDOW.rgfDaysOfTheWeek = - pTrigger->Type.MonthlyDOW.rgfDaysOfTheWeek; - tmp_trigger_cond.Type.MonthlyDOW.rgfMonths = - pTrigger->Type.MonthlyDOW.rgfMonths; - break; - case TASK_TIME_TRIGGER_ONCE: - case TASK_EVENT_TRIGGER_ON_IDLE: - case TASK_EVENT_TRIGGER_AT_SYSTEMSTART: - case TASK_EVENT_TRIGGER_AT_LOGON: - default: - tmp_trigger_cond.Type = This->triggerCond.Type; - break; - } - - /* Reserved field must be zero */ - tmp_trigger_cond.Reserved2 = 0; - - /* wRandomMinutesInterval not currently used and is initialized to zero */ - tmp_trigger_cond.wRandomMinutesInterval = 0; - - /* Update object copy of triggerCond */ - This->triggerCond = tmp_trigger_cond; - - return S_OK; -} - -static HRESULT WINAPI MSTASK_ITaskTrigger_GetTrigger( - ITaskTrigger* iface, - PTASK_TRIGGER pTrigger) -{ - TaskTriggerImpl * This = impl_from_ITaskTrigger(iface); - - TRACE("(%p, %p)\n", iface, pTrigger); - - if (!pTrigger) return E_INVALIDARG; - - /* Native implementation doesn't verify equivalent cbTriggerSize fields */ - - /* Copy relevant fields of the structure */ - pTrigger->cbTriggerSize = This->triggerCond.cbTriggerSize; - pTrigger->Reserved1 = 0; - pTrigger->wBeginYear = This->triggerCond.wBeginYear; - pTrigger->wBeginMonth = This->triggerCond.wBeginMonth; - pTrigger->wBeginDay = This->triggerCond.wBeginDay; - pTrigger->wEndYear = This->triggerCond.wEndYear; - pTrigger->wEndMonth = This->triggerCond.wEndMonth; - pTrigger->wEndDay = This->triggerCond.wEndDay; - pTrigger->wStartHour = This->triggerCond.wStartHour; - pTrigger->wStartMinute = This->triggerCond.wStartMinute; - pTrigger->MinutesDuration = This->triggerCond.MinutesDuration; - pTrigger->MinutesInterval = This->triggerCond.MinutesInterval; - pTrigger->rgFlags = This->triggerCond.rgFlags; - pTrigger->TriggerType = This->triggerCond.TriggerType; - switch (This->triggerCond.TriggerType) - { - case TASK_TIME_TRIGGER_DAILY: - pTrigger->Type.Daily.DaysInterval = - This->triggerCond.Type.Daily.DaysInterval; - break; - case TASK_TIME_TRIGGER_WEEKLY: - pTrigger->Type.Weekly.WeeksInterval = - This->triggerCond.Type.Weekly.WeeksInterval; - pTrigger->Type.Weekly.rgfDaysOfTheWeek = - This->triggerCond.Type.Weekly.rgfDaysOfTheWeek; - break; - case TASK_TIME_TRIGGER_MONTHLYDATE: - pTrigger->Type.MonthlyDate.rgfDays = - This->triggerCond.Type.MonthlyDate.rgfDays; - pTrigger->Type.MonthlyDate.rgfMonths = - This->triggerCond.Type.MonthlyDate.rgfMonths; - break; - case TASK_TIME_TRIGGER_MONTHLYDOW: - pTrigger->Type.MonthlyDOW.wWhichWeek = - This->triggerCond.Type.MonthlyDOW.wWhichWeek; - pTrigger->Type.MonthlyDOW.rgfDaysOfTheWeek = - This->triggerCond.Type.MonthlyDOW.rgfDaysOfTheWeek; - pTrigger->Type.MonthlyDOW.rgfMonths = - This->triggerCond.Type.MonthlyDOW.rgfMonths; - break; - case TASK_TIME_TRIGGER_ONCE: - case TASK_EVENT_TRIGGER_ON_IDLE: - case TASK_EVENT_TRIGGER_AT_SYSTEMSTART: - case TASK_EVENT_TRIGGER_AT_LOGON: - default: - break; - } - pTrigger->Reserved2 = 0; - pTrigger->wRandomMinutesInterval = 0; - return S_OK; -} - -static HRESULT WINAPI MSTASK_ITaskTrigger_GetTriggerString( - ITaskTrigger* iface, - LPWSTR *ppwszTrigger) -{ - FIXME("Not implemented\n"); - return E_NOTIMPL; -} - -static const ITaskTriggerVtbl MSTASK_ITaskTriggerVtbl = -{ - MSTASK_ITaskTrigger_QueryInterface, - MSTASK_ITaskTrigger_AddRef, - MSTASK_ITaskTrigger_Release, - MSTASK_ITaskTrigger_SetTrigger, - MSTASK_ITaskTrigger_GetTrigger, - MSTASK_ITaskTrigger_GetTriggerString -}; - -HRESULT TaskTriggerConstructor(LPVOID *ppObj) -{ - TaskTriggerImpl *This; - SYSTEMTIME time; - TRACE("(%p)\n", ppObj); - - This = heap_alloc(sizeof(*This)); - if (!This) - return E_OUTOFMEMORY; - - This->ITaskTrigger_iface.lpVtbl = &MSTASK_ITaskTriggerVtbl; - This->ref = 1; - - /* Most fields of triggerCond default to zero. Initialize other - * fields to default values. */ - memset(&This->triggerCond, 0, sizeof(TASK_TRIGGER)); - GetLocalTime(&time); - This->triggerCond.cbTriggerSize = sizeof(This->triggerCond); - This->triggerCond.wBeginYear = time.wYear; - This->triggerCond.wBeginMonth = time.wMonth; - This->triggerCond.wBeginDay = time.wDay; - This->triggerCond.wStartHour = time.wHour; - This->triggerCond.wStartMinute = time.wMinute; - This->triggerCond.rgFlags = TASK_TRIGGER_FLAG_DISABLED; - This->triggerCond.TriggerType = TASK_TIME_TRIGGER_DAILY, - This->triggerCond.Type.Daily.DaysInterval = 1; - - *ppObj = &This->ITaskTrigger_iface; - InterlockedIncrement(&dll_ref); - return S_OK; -} +/* + * Copyright (C) 2008 Google (Roy Shea) + * + * 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 + +#define COBJMACROS + +#include "windef.h" +#include "winbase.h" +#include "objbase.h" +#include "taskschd.h" +#include "mstask.h" +#include "mstask_private.h" +#include "wine/debug.h" + +WINE_DEFAULT_DEBUG_CHANNEL(mstask); + +typedef struct +{ + ITaskTrigger ITaskTrigger_iface; + LONG ref; + ITask *parent_task; + WORD trigger_index; +} TaskTriggerImpl; + +static inline TaskTriggerImpl *impl_from_ITaskTrigger(ITaskTrigger *iface) +{ + return CONTAINING_RECORD(iface, TaskTriggerImpl, ITaskTrigger_iface); +} + +static HRESULT WINAPI MSTASK_ITaskTrigger_QueryInterface( + ITaskTrigger* iface, + REFIID riid, + void **ppvObject) +{ + TaskTriggerImpl *This = impl_from_ITaskTrigger(iface); + + TRACE("IID: %s\n", debugstr_guid(riid)); + if (ppvObject == NULL) + return E_POINTER; + + if (IsEqualGUID(riid, &IID_IUnknown) || + IsEqualGUID(riid, &IID_ITaskTrigger)) + { + *ppvObject = &This->ITaskTrigger_iface; + ITaskTrigger_AddRef(iface); + return S_OK; + } + + WARN("Unknown interface: %s\n", debugstr_guid(riid)); + *ppvObject = NULL; + return E_NOINTERFACE; +} + +static ULONG WINAPI MSTASK_ITaskTrigger_AddRef( + ITaskTrigger* iface) +{ + TaskTriggerImpl *This = impl_from_ITaskTrigger(iface); + ULONG ref; + TRACE("\n"); + ref = InterlockedIncrement(&This->ref); + return ref; +} + +static ULONG WINAPI MSTASK_ITaskTrigger_Release( + ITaskTrigger* iface) +{ + TaskTriggerImpl *This = impl_from_ITaskTrigger(iface); + ULONG ref; + TRACE("\n"); + ref = InterlockedDecrement(&This->ref); + if (ref == 0) + { + ITask_Release(This->parent_task); + heap_free(This); + InterlockedDecrement(&dll_ref); + } + return ref; +} + +static HRESULT WINAPI MSTASK_ITaskTrigger_SetTrigger(ITaskTrigger *iface, const PTASK_TRIGGER trigger) +{ + TaskTriggerImpl *This = impl_from_ITaskTrigger(iface); + + TRACE("(%p, %p)\n", iface, trigger); + + if (!trigger) return E_INVALIDARG; + + return task_set_trigger(This->parent_task, This->trigger_index, trigger); +} + +static HRESULT WINAPI MSTASK_ITaskTrigger_GetTrigger(ITaskTrigger *iface, TASK_TRIGGER *trigger) +{ + TaskTriggerImpl *This = impl_from_ITaskTrigger(iface); + + TRACE("(%p, %p)\n", iface, trigger); + + if (!trigger) return E_INVALIDARG; + + return task_get_trigger(This->parent_task, This->trigger_index, trigger); +} + +static HRESULT WINAPI MSTASK_ITaskTrigger_GetTriggerString( + ITaskTrigger* iface, + LPWSTR *ppwszTrigger) +{ + FIXME("Not implemented\n"); + return E_NOTIMPL; +} + +static const ITaskTriggerVtbl MSTASK_ITaskTriggerVtbl = +{ + MSTASK_ITaskTrigger_QueryInterface, + MSTASK_ITaskTrigger_AddRef, + MSTASK_ITaskTrigger_Release, + MSTASK_ITaskTrigger_SetTrigger, + MSTASK_ITaskTrigger_GetTrigger, + MSTASK_ITaskTrigger_GetTriggerString +}; + +HRESULT TaskTriggerConstructor(ITask *task, WORD idx, ITaskTrigger **trigger) +{ + TaskTriggerImpl *This; + + TRACE("(%p, %u, %p)\n", task, idx, trigger); + + This = heap_alloc(sizeof(*This)); + if (!This) + return E_OUTOFMEMORY; + + This->ITaskTrigger_iface.lpVtbl = &MSTASK_ITaskTriggerVtbl; + This->ref = 1; + + ITask_AddRef(task); + This->parent_task = task; + This->trigger_index = idx; + + *trigger = &This->ITaskTrigger_iface; + InterlockedIncrement(&dll_ref); + return S_OK; +} diff --git a/dlls/mstask/tests/task_trigger.c b/dlls/mstask/tests/task_trigger.c index ab99af7b5d5..9a20a5672c4 100644 --- a/dlls/mstask/tests/task_trigger.c +++ b/dlls/mstask/tests/task_trigger.c @@ -499,14 +499,12 @@ static void test_trigger_manager(void) hr = ITask_CreateTrigger(task, &idx, &trigger0); ok(hr == S_OK, "got %#x\n", hr); ok(idx == 0, "got %u\n", idx); -todo_wine ok(obj_refcount(task) == 2, "got %u\n", obj_refcount(task)); idx = 0xdead; hr = ITask_CreateTrigger(task, &idx, &trigger1); ok(hr == S_OK, "got %#x\n", hr); ok(idx == 1, "got %u\n", idx); -todo_wine ok(obj_refcount(task) == 3, "got %u\n", obj_refcount(task)); count = 0xdead; @@ -524,9 +522,7 @@ todo_wine hr = get_task_trigger(task, 0, &state); ok(hr == S_OK, "got %#x\n", hr); -todo_wine ok(state.wBeginYear == 3000, "got %u\n", state.wBeginYear); -todo_wine ok(state.TriggerType == TASK_TIME_TRIGGER_ONCE, "got %u\n", state.TriggerType); hr = ITaskTrigger_GetTrigger(trigger1, &state1); @@ -539,7 +535,6 @@ todo_wine hr = get_task_trigger(task, 1, &state); ok(hr == S_OK, "got %#x\n", hr); -todo_wine ok(state.wBeginYear == 2000, "got %u\n", state.wBeginYear); ok(state.TriggerType == TASK_TIME_TRIGGER_DAILY, "got %u\n", state.TriggerType); @@ -552,14 +547,11 @@ todo_wine hr = get_task_trigger(task, 0, &state); ok(hr == S_OK, "got %#x\n", hr); -todo_wine ok(state.wBeginYear == 3000, "got %u\n", state.wBeginYear); -todo_wine ok(state.TriggerType == TASK_TIME_TRIGGER_ONCE, "got %u\n", state.TriggerType); hr = get_task_trigger(task, 1, &state); ok(hr == S_OK, "got %#x\n", hr); -todo_wine ok(state.wBeginYear == 2000, "got %u\n", state.wBeginYear); ok(state.TriggerType == TASK_TIME_TRIGGER_DAILY, "got %u\n", state.TriggerType); @@ -573,7 +565,6 @@ todo_wine hr = get_task_trigger(task, 0, &state); ok(hr == S_OK, "got %#x\n", hr); -todo_wine ok(state.wBeginYear == 2000, "got %u\n", state.wBeginYear); ok(state.TriggerType == TASK_TIME_TRIGGER_DAILY, "got %u\n", state.TriggerType); @@ -584,7 +575,6 @@ todo_wine ok(hr == S_OK, "got %#x\n", hr); hr = ITaskTrigger_SetTrigger(trigger1, &state1); -todo_wine ok(hr == E_FAIL, "got %#x\n", hr); count = 0xdead; @@ -592,7 +582,6 @@ todo_wine ok(hr == S_OK, "got %#x\n", hr); ok(count == 1, "got %u\n", count); -todo_wine ok(obj_refcount(task) == 3, "got %u\n", obj_refcount(task)); ref = ITaskTrigger_Release(trigger0); -- 2.11.4.GIT