Signed-off-by: Dmitry Timoshkov dmitry@baikal.ru --- dlls/mstask/task.c | 90 ++++++++++++++++++++++++++++++++++++++-- dlls/mstask/tests/task_trigger.c | 81 +++++++++++++++++++++++++++++++++--- 2 files changed, 163 insertions(+), 8 deletions(-)
diff --git a/dlls/mstask/task.c b/dlls/mstask/task.c index d487aeb5a5..c004764af0 100644 --- a/dlls/mstask/task.c +++ b/dlls/mstask/task.c @@ -408,11 +408,95 @@ static HRESULT WINAPI MSTASK_ITask_GetRunTimes( return E_NOTIMPL; }
-static HRESULT WINAPI MSTASK_ITask_GetNextRunTime(ITask *iface, SYSTEMTIME *st) +static void get_begin_time(const TASK_TRIGGER *trigger, FILETIME *ft) { - FIXME("(%p, %p): stub\n", iface, st); + SYSTEMTIME st;
- memset(st, 0, sizeof(*st)); + st.wYear = trigger->wBeginYear; + st.wMonth = trigger->wBeginMonth; + st.wDay = trigger->wBeginDay; + st.wDayOfWeek = 0; + st.wHour = 0; + st.wMinute = 0; + st.wSecond = 0; + st.wMilliseconds = 0; + SystemTimeToFileTime(&st, ft); +} + +static void get_end_time(const TASK_TRIGGER *trigger, FILETIME *ft) +{ + SYSTEMTIME st; + + if (!(trigger->rgFlags & TASK_TRIGGER_FLAG_HAS_END_DATE)) + { + ft->dwHighDateTime = ~0u; + ft->dwLowDateTime = ~0u; + return; + } + + st.wYear = trigger->wEndYear; + st.wMonth = trigger->wEndMonth; + st.wDay = trigger->wEndDay; + st.wDayOfWeek = 0; + st.wHour = 0; + st.wMinute = 0; + st.wSecond = 0; + st.wMilliseconds = 0; + SystemTimeToFileTime(&st, ft); +} + +static HRESULT WINAPI MSTASK_ITask_GetNextRunTime(ITask *iface, SYSTEMTIME *rt) +{ + TaskImpl *This = impl_from_ITask(iface); + SYSTEMTIME st, current_st; + FILETIME current_ft, begin_ft, end_ft, best_ft; + BOOL have_best_time = FALSE; + DWORD i; + + TRACE("(%p, %p)\n", iface, rt); + + GetLocalTime(¤t_st); + + for (i = 0; i < This->trigger_count; i++) + { + if (!(This->trigger[i].rgFlags & TASK_TRIGGER_FLAG_DISABLED)) + { + get_begin_time(&This->trigger[i], &begin_ft); + get_end_time(&This->trigger[i], &end_ft); + + switch (This->trigger[i].TriggerType) + { + case TASK_TIME_TRIGGER_ONCE: + st = current_st; + st.wHour = This->trigger[i].wStartHour; + st.wMinute = This->trigger[i].wStartMinute; + st.wSecond = 0; + st.wMilliseconds = 0; + SystemTimeToFileTime(&st, ¤t_ft); + if (CompareFileTime(&begin_ft, ¤t_ft) <= 0 && CompareFileTime(¤t_ft, &end_ft) < 0) + { + if (!have_best_time || CompareFileTime(¤t_ft, &best_ft) < 0) + { + best_ft = current_ft; + have_best_time = TRUE; + } + } + break; + + default: + FIXME("trigger type %u is not handled\n", This->trigger[i].TriggerType); + break; + } + } + } + + if (have_best_time) + { + FileTimeToSystemTime(&best_ft, rt); + return S_OK; + } + + memset(rt, 0, sizeof(*rt)); return SCHED_S_TASK_NO_VALID_TRIGGERS; }
diff --git a/dlls/mstask/tests/task_trigger.c b/dlls/mstask/tests/task_trigger.c index 9a20a5672c..e880ce4996 100644 --- a/dlls/mstask/tests/task_trigger.c +++ b/dlls/mstask/tests/task_trigger.c @@ -422,6 +422,53 @@ static void test_task_trigger(void) ok(ref == 0, "got %u\n", ref); }
+static void time_add_ms(SYSTEMTIME *st, DWORD ms) +{ + union + { + FILETIME ft; + ULONGLONG ll; + } ftll; + BOOL ret; + + trace("old: %u/%u/%u wday %u %u:%02u:%02u.%03u\n", + st->wDay, st->wMonth, st->wYear, st->wDayOfWeek, + st->wHour, st->wMinute, st->wSecond, st->wMilliseconds); + ret = SystemTimeToFileTime(st, &ftll.ft); + ok(ret, "SystemTimeToFileTime error %u\n", GetLastError()); + + ftll.ll += ms * (ULONGLONG)10000; + ret = FileTimeToSystemTime(&ftll.ft, st); + ok(ret, "FileTimeToSystemTime error %u\n", GetLastError()); + trace("new: %u/%u/%u wday %u %u:%02u:%02u.%03u\n", + st->wDay, st->wMonth, st->wYear, st->wDayOfWeek, + st->wHour, st->wMinute, st->wSecond, st->wMilliseconds); +} + +static void trigger_add_ms(TASK_TRIGGER *data, DWORD ms, SYSTEMTIME *ret) +{ + SYSTEMTIME st; + + st.wYear = data->wBeginYear; + st.wMonth = data->wBeginMonth; + st.wDayOfWeek = 0; + st.wDay = data->wBeginDay; + st.wHour = data->wStartHour; + st.wMinute = data->wStartMinute; + st.wSecond = 0; + st.wMilliseconds = 0; + + time_add_ms(&st, ms); + + data->wBeginYear = st.wYear; + data->wBeginMonth = st.wMonth; + data->wBeginDay = st.wDay; + data->wStartHour = st.wHour; + data->wStartMinute = st.wMinute; + + *ret = st; +} + static void test_GetNextRunTime(void) { static const WCHAR task_name[] = { 'T','e','s','t','i','n','g',0 }; @@ -429,8 +476,9 @@ static void test_GetNextRunTime(void) HRESULT hr; ITask *task; ITaskTrigger *trigger; + TASK_TRIGGER data; WORD idx; - SYSTEMTIME st; + SYSTEMTIME st, cmp;
hr = ITaskScheduler_NewWorkItem(test_task_scheduler, task_name, &CLSID_CTask, &IID_ITask, (IUnknown **)&task); @@ -442,9 +490,9 @@ static void test_GetNextRunTime(void) memset(&st, 0xff, sizeof(st)); hr = ITask_GetNextRunTime(task, &st); ok(hr == SCHED_S_TASK_NO_VALID_TRIGGERS, "got %#x\n", hr); - ok(!memcmp(&st, &st_empty, sizeof(st)), "got %d/%d/%d wday %d %d:%d:%d.%03d\n", + ok(!memcmp(&st, &st_empty, sizeof(st)), "got %u/%u/%u wday %u %u:%02u:%02u\n", st.wDay, st.wMonth, st.wYear, st.wDayOfWeek, - st.wHour, st.wMinute, st.wSecond, st.wMilliseconds); + st.wHour, st.wMinute, st.wSecond);
hr = ITask_CreateTrigger(task, &idx, &trigger); ok(hr == S_OK, "got %#x\n", hr); @@ -452,9 +500,32 @@ static void test_GetNextRunTime(void) memset(&st, 0xff, sizeof(st)); hr = ITask_GetNextRunTime(task, &st); ok(hr == SCHED_S_TASK_NO_VALID_TRIGGERS, "got %#x\n", hr); - ok(!memcmp(&st, &st_empty, sizeof(st)), "got %d/%d/%d wday %d %d:%d:%d.%03d\n", + ok(!memcmp(&st, &st_empty, sizeof(st)), "got %u/%u/%u wday %u %u:%02u:%02u\n", st.wDay, st.wMonth, st.wYear, st.wDayOfWeek, - st.wHour, st.wMinute, st.wSecond, st.wMilliseconds); + st.wHour, st.wMinute, st.wSecond); + + /* TASK_TIME_TRIGGER_ONCE */ + + hr = ITaskTrigger_GetTrigger(trigger, &data); + ok(hr == S_OK, "got %#x\n", hr); + data.rgFlags &= ~TASK_TRIGGER_FLAG_DISABLED; + data.TriggerType = TASK_TIME_TRIGGER_ONCE; + /* add 5 minutes to avoid races */ + trigger_add_ms(&data, 5 * 60 * 1000, &cmp); + hr = ITaskTrigger_SetTrigger(trigger, &data); + ok(hr == S_OK, "got %#x\n", hr); + + memset(&st, 0xff, sizeof(st)); + hr = ITask_GetNextRunTime(task, &st); + ok(hr == S_OK, "got %#x\n", hr); + ok(!memcmp(&st, &cmp, sizeof(st)), "got %u/%u/%u wday %u %u:%02u:%02u\n", + st.wDay, st.wMonth, st.wYear, st.wDayOfWeek, + st.wHour, st.wMinute, st.wSecond); + + /* FIXME: TASK_TIME_TRIGGER_DAILY */ + /* FIXME: TASK_TIME_TRIGGER_WEEKLY */ + /* FIXME: TASK_TIME_TRIGGER_MONTHLYDATE */ + /* FIXME: TASK_TIME_TRIGGER_MONTHLYDOW */
ITaskTrigger_Release(trigger); ITask_Release(task);