From: Oleg Nikulin <owl2@etersoft.ru> Implement TriggerCollection_get_Count() to return trigger count, implement TriggerCollection_get_Item() to retrieve triggers, modify TriggerCollection_Create() to add newly created triggers to the internal list, implement TriggerCollection_Clear() to clear the internal list. Add tests for ITriggerCollection. --- dlls/taskschd/task.c | 83 ++++++++++++++++++++++++++++----- dlls/taskschd/tests/scheduler.c | 65 ++++++++++++++++++++++++++ 2 files changed, 137 insertions(+), 11 deletions(-) diff --git a/dlls/taskschd/task.c b/dlls/taskschd/task.c index 419af3dc753..ce3e0403ec2 100644 --- a/dlls/taskschd/task.c +++ b/dlls/taskschd/task.c @@ -1189,6 +1189,8 @@ typedef struct { ITriggerCollection ITriggerCollection_iface; LONG ref; + ITrigger **list; + LONG count; } trigger_collection; static inline trigger_collection *impl_from_ITriggerCollection(ITriggerCollection *iface) @@ -1226,6 +1228,16 @@ static ULONG WINAPI TriggerCollection_AddRef(ITriggerCollection *iface) return ref; } +static void free_triggers_list(ITrigger **list, LONG count) +{ + LONG i; + + for (i = 0; i < count; i++) + ITrigger_Release(list[i]); + + free(list); +} + static ULONG WINAPI TriggerCollection_Release(ITriggerCollection *iface) { trigger_collection *This = impl_from_ITriggerCollection(iface); @@ -1234,7 +1246,10 @@ static ULONG WINAPI TriggerCollection_Release(ITriggerCollection *iface) TRACE("(%p) ref=%ld\n", This, ref); if(!ref) + { + free_triggers_list(This->list, This->count); free(This); + } return ref; } @@ -1273,15 +1288,34 @@ static HRESULT WINAPI TriggerCollection_Invoke(ITriggerCollection *iface, DISPID 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; + + TRACE("(%p)->(%p)\n", This, count); + + if (!count) return E_POINTER; + + *count = This->count; + + return S_OK; } static HRESULT WINAPI TriggerCollection_get_Item(ITriggerCollection *iface, LONG index, ITrigger **trigger) { trigger_collection *This = impl_from_ITriggerCollection(iface); - FIXME("(%p)->(%ld %p)\n", This, index, trigger); - return E_NOTIMPL; + + TRACE("(%p)->(%ld %p)\n", This, index, trigger); + + if (!trigger) return E_POINTER; + + /* collections are 1 based */ + if (index < 1) + return E_INVALIDARG; + if (index > This->count) + return E_FAIL; + + *trigger = This->list[index - 1]; + ITrigger_AddRef(*trigger); + + return S_OK; } static HRESULT WINAPI TriggerCollection_get__NewEnum(ITriggerCollection *iface, IUnknown **penum) @@ -1294,22 +1328,41 @@ static HRESULT WINAPI TriggerCollection_get__NewEnum(ITriggerCollection *iface, static HRESULT WINAPI TriggerCollection_Create(ITriggerCollection *iface, TASK_TRIGGER_TYPE2 type, ITrigger **trigger) { trigger_collection *This = impl_from_ITriggerCollection(iface); + HRESULT hr; TRACE("(%p)->(%d %p)\n", This, type, trigger); - switch(type) { + switch (type) + { case TASK_TRIGGER_DAILY: - return DailyTrigger_create(trigger); + hr = DailyTrigger_create(trigger); + break; case TASK_TRIGGER_REGISTRATION: - return RegistrationTrigger_create(trigger); + hr = RegistrationTrigger_create(trigger); + break; case TASK_TRIGGER_LOGON: - return LogonTrigger_create(trigger); + hr = LogonTrigger_create(trigger); + break; default: FIXME("Unimplemented type %d\n", type); return E_NOTIMPL; } - return S_OK; + if (SUCCEEDED(hr)) + { + ITrigger **new_array = realloc(This->list, (This->count + 1) * sizeof(*new_array)); + if (!new_array) + { + ITrigger_Release(*trigger); + *trigger = NULL; + return E_OUTOFMEMORY; + } + This->list = new_array; + This->list[This->count++] = *trigger; + ITrigger_AddRef(*trigger); + } + + return hr; } static HRESULT WINAPI TriggerCollection_Remove(ITriggerCollection *iface, VARIANT index) @@ -1322,8 +1375,14 @@ static HRESULT WINAPI TriggerCollection_Remove(ITriggerCollection *iface, VARIAN static HRESULT WINAPI TriggerCollection_Clear(ITriggerCollection *iface) { trigger_collection *This = impl_from_ITriggerCollection(iface); - FIXME("(%p)\n", This); - return E_NOTIMPL; + + TRACE("(%p)\n", This); + + free_triggers_list(This->list, This->count); + This->list = NULL; + This->count = 0; + + return S_OK; } static const ITriggerCollectionVtbl TriggerCollection_vtbl = { @@ -3178,6 +3237,8 @@ static HRESULT WINAPI TaskDefinition_get_Triggers(ITaskDefinition *iface, ITrigg collection->ITriggerCollection_iface.lpVtbl = &TriggerCollection_vtbl; collection->ref = 1; + collection->list = NULL; + collection->count = 0; This->triggers = &collection->ITriggerCollection_iface; } diff --git a/dlls/taskschd/tests/scheduler.c b/dlls/taskschd/tests/scheduler.c index 99fc7ff9d06..888215526f2 100644 --- a/dlls/taskschd/tests/scheduler.c +++ b/dlls/taskschd/tests/scheduler.c @@ -1640,6 +1640,69 @@ static void create_action(ITaskDefinition *taskdef) IActionCollection_Release(actions); } +static void test_trigger_collection(ITriggerCollection *trigger_col) +{ + ITrigger *trigger; + HRESULT hr; + LONG count; + + /* Collection may already contain triggers parsed from XML */ + hr = ITriggerCollection_Clear(trigger_col); + ok(hr == S_OK, "Clear failed: %08lx\n", hr); + + hr = ITriggerCollection_get_Count(trigger_col, NULL); + ok(hr == E_POINTER, "expected E_POINTER, got %#lx\n", hr); + + count = -1; + hr = ITriggerCollection_get_Count(trigger_col, &count); + ok(hr == S_OK, "get_Count failed: %08lx\n", hr); + ok(count == 0, "expected 0, got %ld\n", count); + + hr = ITriggerCollection_get_Item(trigger_col, 1, NULL); + ok(hr == E_POINTER, "expected E_POINTER, got %#lx\n", hr); + + hr = ITriggerCollection_get_Item(trigger_col, 1, &trigger); + ok(hr == E_FAIL, "expected E_FAIL, got %#lx\n", hr); + + hr = ITriggerCollection_Create(trigger_col, TASK_TRIGGER_DAILY, &trigger); + ok(hr == S_OK, "Create failed: %08lx\n", hr); + ITrigger_Release(trigger); + + hr = ITriggerCollection_Create(trigger_col, TASK_TRIGGER_DAILY, &trigger); + ok(hr == S_OK, "Create failed: %08lx\n", hr); + ITrigger_Release(trigger); + + count = -1; + hr = ITriggerCollection_get_Count(trigger_col, &count); + ok(hr == S_OK, "get_Count failed: %08lx\n", hr); + ok(count == 2, "expected 2, got %ld\n", count); + + hr = ITriggerCollection_get_Item(trigger_col, 0, &trigger); + ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %#lx\n", hr); + + hr = ITriggerCollection_get_Item(trigger_col, 3, &trigger); + ok(hr == E_FAIL, "expected E_FAIL, got %#lx\n", hr); + + hr = ITriggerCollection_get_Item(trigger_col, 1, &trigger); + ok(hr == S_OK, "get_Item failed: %08lx\n", hr); + ITrigger_Release(trigger); + + hr = ITriggerCollection_get_Item(trigger_col, 2, &trigger); + ok(hr == S_OK, "get_Item failed: %08lx\n", hr); + ITrigger_Release(trigger); + + hr = ITriggerCollection_Clear(trigger_col); + ok(hr == S_OK, "Clear failed: %08lx\n", hr); + + count = -1; + hr = ITriggerCollection_get_Count(trigger_col, &count); + ok(hr == S_OK, "get_Count failed: %08lx\n", hr); + ok(count == 0, "expected 0, got %ld\n", count); + + hr = ITriggerCollection_get_Item(trigger_col, 1, &trigger); + ok(hr == E_FAIL, "expected E_FAIL, got %#lx\n", hr); +} + static void test_action_collection(IActionCollection *actions_col) { IAction *action; @@ -2000,6 +2063,8 @@ static void test_TaskDefinition(void) ok(hr == S_OK, "get_Triggers failed: %08lx\n", hr); ok(trigger_col != NULL, "Triggers = NULL\n"); + test_trigger_collection(trigger_col); + hr = ITriggerCollection_Create(trigger_col, TASK_TRIGGER_DAILY, &trigger); ok(hr == S_OK, "Create failed: %08lx\n", hr); ok(trigger != NULL, "trigger = NULL\n"); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11065