[PATCH 0/5] MR11065: taskschd: Implement several methods in IActionCollection, ITriggerCollection and IPrincipal
I have an app that crashes in Wine because it requires some task scheduler features that are not implemented yet -- https://gitlab.winehq.org/wine/wine/-/merge_requests/11065
From: Oleg Nikulin <owl2@etersoft.ru> Implement Actions_get_Count() to return action count, implement Actions_get_Item() to retrieve actions, modify Actions_Create() to add newly created actions to the internal list, implement Actions_Clear() to clear the internal list. Add tests for IActionCollection. --- dlls/taskschd/task.c | 77 ++++++++++++++++++++++++++++++--- dlls/taskschd/tests/scheduler.c | 70 ++++++++++++++++++++++++++++++ 2 files changed, 140 insertions(+), 7 deletions(-) diff --git a/dlls/taskschd/task.c b/dlls/taskschd/task.c index 7525a52566d..419af3dc753 100644 --- a/dlls/taskschd/task.c +++ b/dlls/taskschd/task.c @@ -2783,6 +2783,8 @@ typedef struct { IActionCollection IActionCollection_iface; LONG ref; + IAction **list; + LONG count; } Actions; static inline Actions *impl_from_IActionCollection(IActionCollection *iface) @@ -2796,6 +2798,16 @@ static ULONG WINAPI Actions_AddRef(IActionCollection *iface) return InterlockedIncrement(&actions->ref); } +static void free_list(IAction **list, LONG count) +{ + LONG i; + + for (i = 0; i < count; i++) + IAction_Release(list[i]); + + free(list); +} + static ULONG WINAPI Actions_Release(IActionCollection *iface) { Actions *actions = impl_from_IActionCollection(iface); @@ -2804,6 +2816,7 @@ static ULONG WINAPI Actions_Release(IActionCollection *iface) if (!ref) { TRACE("destroying %p\n", iface); + free_list(actions->list, actions->count); free(actions); } @@ -2859,14 +2872,35 @@ static HRESULT WINAPI Actions_Invoke(IActionCollection *iface, DISPID dispid, RE static HRESULT WINAPI Actions_get_Count(IActionCollection *iface, LONG *count) { - FIXME("%p,%p: stub\n", iface, count); - return E_NOTIMPL; + Actions *actions = impl_from_IActionCollection(iface); + + TRACE("%p,%p\n", iface, count); + + if (!count) return E_POINTER; + + *count = actions->count; + + return S_OK; } static HRESULT WINAPI Actions_get_Item(IActionCollection *iface, LONG index, IAction **action) { - FIXME("%p,%ld,%p: stub\n", iface, index, action); - return E_NOTIMPL; + Actions *actions = impl_from_IActionCollection(iface); + + TRACE("%p,%ld,%p\n", iface, index, action); + + if (!action) return E_POINTER; + + /* collections are 1 based */ + if (index < 1) + return E_INVALIDARG; + if (index > actions->count) + return E_FAIL; + + *action = actions->list[index - 1]; + IAction_AddRef(*action); + + return S_OK; } static HRESULT WINAPI Actions_get__NewEnum(IActionCollection *iface, IUnknown **penum) @@ -2889,17 +2923,37 @@ static HRESULT WINAPI Actions_put_XmlText(IActionCollection *iface, BSTR xml) static HRESULT WINAPI Actions_Create(IActionCollection *iface, TASK_ACTION_TYPE type, IAction **action) { + Actions *actions = impl_from_IActionCollection(iface); + HRESULT hr; + TRACE("%p,%u,%p\n", iface, type, action); switch (type) { case TASK_ACTION_EXEC: - return ExecAction_create((IExecAction **)action); + hr = ExecAction_create((IExecAction **)action); + break; default: FIXME("unimplemented type %u\n", type); return E_NOTIMPL; } + + if (SUCCEEDED(hr)) + { + IAction **new_array = realloc(actions->list, (actions->count + 1) * sizeof(*new_array)); + if (!new_array) + { + IAction_Release(*action); + *action = NULL; + return E_OUTOFMEMORY; + } + actions->list = new_array; + actions->list[actions->count++] = *action; + IAction_AddRef(*action); + } + + return hr; } static HRESULT WINAPI Actions_Remove(IActionCollection *iface, VARIANT index) @@ -2910,8 +2964,15 @@ static HRESULT WINAPI Actions_Remove(IActionCollection *iface, VARIANT index) static HRESULT WINAPI Actions_Clear(IActionCollection *iface) { - FIXME("%p: stub\n", iface); - return E_NOTIMPL; + Actions *actions = impl_from_IActionCollection(iface); + + TRACE("%p\n", iface); + + free_list(actions->list, actions->count); + actions->list = NULL; + actions->count = 0; + + return S_OK; } static HRESULT WINAPI Actions_get_Context(IActionCollection *iface, BSTR *ctx) @@ -2956,6 +3017,8 @@ static HRESULT Actions_create(IActionCollection **obj) actions->IActionCollection_iface.lpVtbl = &Actions_vtbl; actions->ref = 1; + actions->list = NULL; + actions->count = 0; *obj = &actions->IActionCollection_iface; diff --git a/dlls/taskschd/tests/scheduler.c b/dlls/taskschd/tests/scheduler.c index 025522f322c..99fc7ff9d06 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_action_collection(IActionCollection *actions_col) +{ + IAction *action; + HRESULT hr; + LONG count; + + /* Collection may already contain actions parsed from XML */ + hr = IActionCollection_Clear(actions_col); + ok(hr == S_OK, "Clear failed: %08lx\n", hr); + + hr = IActionCollection_get_Count(actions_col, NULL); + ok(hr == E_POINTER, "expected E_POINTER, got %#lx\n", hr); + + count = -1; + hr = IActionCollection_get_Count(actions_col, &count); + ok(hr == S_OK, "get_Count failed: %08lx\n", hr); + ok(count == 0, "expected 0, got %ld\n", count); + + hr = IActionCollection_get_Item(actions_col, 1, NULL); + ok(hr == E_POINTER, "expected E_POINTER, got %#lx\n", hr); + + hr = IActionCollection_get_Item(actions_col, 1, &action); + ok(hr == E_FAIL, "expected E_FAIL, got %#lx\n", hr); + + hr = IActionCollection_Create(actions_col, TASK_ACTION_EXEC, &action); + ok(hr == S_OK, "Create failed: %08lx\n", hr); + IAction_Release(action); + + hr = IActionCollection_Create(actions_col, TASK_ACTION_EXEC, &action); + ok(hr == S_OK, "Create failed: %08lx\n", hr); + IAction_Release(action); + + count = -1; + hr = IActionCollection_get_Count(actions_col, &count); + ok(hr == S_OK, "get_Count failed: %08lx\n", hr); + ok(count == 2, "expected 2, got %ld\n", count); + + hr = IActionCollection_get_Item(actions_col, 0, &action); + ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %#lx\n", hr); + + hr = IActionCollection_get_Item(actions_col, 3, &action); + ok(hr == E_FAIL, "expected E_FAIL, got %#lx\n", hr); + + hr = IActionCollection_get_Item(actions_col, 1, &action); + ok(hr == S_OK, "get_Item failed: %08lx\n", hr); + IAction_Release(action); + + hr = IActionCollection_get_Item(actions_col, 2, &action); + ok(hr == S_OK, "get_Item failed: %08lx\n", hr); + IAction_Release(action); + + hr = IActionCollection_Clear(actions_col); + ok(hr == S_OK, "Clear failed: %08lx\n", hr); + + count = -1; + hr = IActionCollection_get_Count(actions_col, &count); + ok(hr == S_OK, "get_Count failed: %08lx\n", hr); + ok(count == 0, "expected 0, got %ld\n", count); + + hr = IActionCollection_get_Item(actions_col, 1, &action); + ok(hr == E_FAIL, "expected E_FAIL, got %#lx\n", hr); +} + static void test_TaskDefinition(void) { static WCHAR xml0[] = L""; @@ -1742,6 +1805,7 @@ static void test_TaskDefinition(void) VARIANT_FALSE, VARIANT_FALSE, VARIANT_TRUE, VARIANT_TRUE, VARIANT_FALSE, VARIANT_TRUE, VARIANT_TRUE, VARIANT_TRUE }; ITriggerCollection *trigger_col, *trigger_col2; + IActionCollection *actions_col; HRESULT hr; ITaskService *service; ITaskDefinition *taskdef; @@ -1960,6 +2024,12 @@ static void test_TaskDefinition(void) ok(trigger_col == trigger_col2, "Mismatched triggers\n"); ITriggerCollection_Release(trigger_col2); + hr = ITaskDefinition_get_Actions(taskdef, &actions_col); + ok(hr == S_OK, "get_Actions failed: %08lx\n", hr); + ok(actions_col != NULL, "Actions = NULL\n"); + test_action_collection(actions_col); + IActionCollection_Release(actions_col); + IRegistrationInfo_Release(reginfo); ITaskDefinition_Release(taskdef); ITaskService_Release(service); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11065
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
From: Oleg Nikulin <owl2@etersoft.ru> Check that bstr is not null. Also simplify empty string check: use *bstr instead of lstrlenW(bstr). --- dlls/taskschd/task.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/dlls/taskschd/task.c b/dlls/taskschd/task.c index ce3e0403ec2..c22fc6be983 100644 --- a/dlls/taskschd/task.c +++ b/dlls/taskschd/task.c @@ -3651,7 +3651,8 @@ static HRESULT write_principal(IStream *stream, IPrincipal *principal) if (hr != S_OK) return hr; } hr = IPrincipal_get_UserId(principal, &bstr); - if (hr == S_OK && lstrlenW(bstr)) + /* IPrincipal_get_UserId returns S_OK with bstr == NULL if UserId has not been set beforehand */ + if (hr == S_OK && bstr && *bstr) { hr = write_text_value(stream, L"UserId", bstr); SysFreeString(bstr); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11065
From: Oleg Nikulin <owl2@etersoft.ru> --- dlls/taskschd/task.c | 37 ++++++++++++++++++++++++++--- dlls/taskschd/tests/scheduler.c | 41 +++++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 3 deletions(-) diff --git a/dlls/taskschd/task.c b/dlls/taskschd/task.c index c22fc6be983..6dcec44e8dc 100644 --- a/dlls/taskschd/task.c +++ b/dlls/taskschd/task.c @@ -2401,6 +2401,7 @@ typedef struct { IPrincipal IPrincipal_iface; LONG ref; + BSTR user_id; } Principal; static inline Principal *impl_from_IPrincipal(IPrincipal *iface) @@ -2422,6 +2423,8 @@ static ULONG WINAPI Principal_Release(IPrincipal *iface) if (!ref) { TRACE("destroying %p\n", iface); + if (principal->user_id) + SysFreeString(principal->user_id); free(principal); } @@ -2501,13 +2504,40 @@ static HRESULT WINAPI Principal_put_DisplayName(IPrincipal *iface, BSTR name) static HRESULT WINAPI Principal_get_UserId(IPrincipal *iface, BSTR *user_id) { - FIXME("%p,%p: stub\n", iface, user_id); - return E_NOTIMPL; + Principal *principal = impl_from_IPrincipal(iface); + + TRACE("%p,%p\n", iface, user_id); + + if (!user_id) return E_POINTER; + + if (!principal->user_id) + *user_id = NULL; + else + { + *user_id = SysAllocString(principal->user_id); + if (!*user_id) return E_OUTOFMEMORY; + } + + return S_OK; } static HRESULT WINAPI Principal_put_UserId(IPrincipal *iface, BSTR user_id) { - FIXME("%p,%s: stub\n", iface, debugstr_w(user_id)); + Principal *principal = impl_from_IPrincipal(iface); + BSTR copy = NULL; + + TRACE("%p,%s\n", iface, debugstr_w(user_id)); + + if (user_id) + { + copy = SysAllocString(user_id); + if (!copy) return E_OUTOFMEMORY; + } + + if (principal->user_id) + SysFreeString(principal->user_id); + + principal->user_id = copy; return S_OK; } @@ -2579,6 +2609,7 @@ static HRESULT Principal_create(IPrincipal **obj) principal->IPrincipal_iface.lpVtbl = &Principal_vtbl; principal->ref = 1; + principal->user_id = NULL; *obj = &principal->IPrincipal_iface; diff --git a/dlls/taskschd/tests/scheduler.c b/dlls/taskschd/tests/scheduler.c index 888215526f2..705ba478471 100644 --- a/dlls/taskschd/tests/scheduler.c +++ b/dlls/taskschd/tests/scheduler.c @@ -1766,6 +1766,40 @@ static void test_action_collection(IActionCollection *actions_col) ok(hr == E_FAIL, "expected E_FAIL, got %#lx\n", hr); } +static void test_principal(IPrincipal *principal) +{ + static const BSTR userid = (BSTR)L"TestUser"; + TASK_LOGON_TYPE logon_type; + HRESULT hr; + BSTR bstr; + + hr = IPrincipal_get_UserId(principal, NULL); + ok(hr == E_POINTER, "expected E_POINTER, got %#lx\n", hr); + + bstr = (BSTR)0xdeadbeef; + hr = IPrincipal_get_UserId(principal, &bstr); + ok(hr == S_OK, "get_UserId failed: %08lx\n", hr); + ok(bstr == NULL, "expected NULL, got %s\n", wine_dbgstr_w(bstr)); + + hr = IPrincipal_put_UserId(principal, userid); + ok(hr == S_OK, "put_UserId failed: %08lx\n", hr); + + bstr = NULL; + hr = IPrincipal_get_UserId(principal, &bstr); + ok(hr == S_OK, "get_UserId failed: %08lx\n", hr); + ok(bstr != NULL, "UserId not set\n"); + ok(!lstrcmpW(bstr, userid), "expected %s, got %s\n", wine_dbgstr_w(userid), wine_dbgstr_w(bstr)); + SysFreeString(bstr); + + hr = IPrincipal_put_UserId(principal, NULL); + ok(hr == S_OK, "put_UserId failed: %08lx\n", hr); + + bstr = (BSTR)0xdeadbeef; + hr = IPrincipal_get_UserId(principal, &bstr); + ok(hr == S_OK, "get_UserId failed: %08lx\n", hr); + ok(bstr == NULL, "expected NULL, got %s\n", wine_dbgstr_w(bstr)); +} + static void test_TaskDefinition(void) { static WCHAR xml0[] = L""; @@ -1869,6 +1903,7 @@ static void test_TaskDefinition(void) VARIANT_TRUE, VARIANT_TRUE }; ITriggerCollection *trigger_col, *trigger_col2; IActionCollection *actions_col; + IPrincipal *principal; HRESULT hr; ITaskService *service; ITaskDefinition *taskdef; @@ -2095,6 +2130,12 @@ static void test_TaskDefinition(void) test_action_collection(actions_col); IActionCollection_Release(actions_col); + hr = ITaskDefinition_get_Principal(taskdef, &principal); + ok(hr == S_OK, "get_Principal failed: %08lx\n", hr); + ok(principal != NULL, "Principal = NULL\n"); + test_principal(principal); + IPrincipal_Release(principal); + IRegistrationInfo_Release(reginfo); ITaskDefinition_Release(taskdef); ITaskService_Release(service); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11065
From: Oleg Nikulin <owl2@etersoft.ru> --- dlls/taskschd/task.c | 23 +++++++++++++++++++---- dlls/taskschd/tests/scheduler.c | 27 +++++++++++++++++++++++++++ 2 files changed, 46 insertions(+), 4 deletions(-) diff --git a/dlls/taskschd/task.c b/dlls/taskschd/task.c index 6dcec44e8dc..46e0762f515 100644 --- a/dlls/taskschd/task.c +++ b/dlls/taskschd/task.c @@ -2402,6 +2402,7 @@ typedef struct IPrincipal IPrincipal_iface; LONG ref; BSTR user_id; + TASK_LOGON_TYPE logon_type; } Principal; static inline Principal *impl_from_IPrincipal(IPrincipal *iface) @@ -2543,14 +2544,27 @@ static HRESULT WINAPI Principal_put_UserId(IPrincipal *iface, BSTR user_id) static HRESULT WINAPI Principal_get_LogonType(IPrincipal *iface, TASK_LOGON_TYPE *logon_type) { - FIXME("%p,%p: stub\n", iface, logon_type); - return E_NOTIMPL; + Principal *principal = impl_from_IPrincipal(iface); + + TRACE("%p,%p\n", iface, logon_type); + + if (!logon_type) return E_POINTER; + + *logon_type = principal->logon_type; + return S_OK; } static HRESULT WINAPI Principal_put_LogonType(IPrincipal *iface, TASK_LOGON_TYPE logon_type) { - FIXME("%p,%u: stub\n", iface, logon_type); - return E_NOTIMPL; + Principal *principal = impl_from_IPrincipal(iface); + + TRACE("%p,%u\n", iface, logon_type); + + if (logon_type == TASK_LOGON_NONE) + return E_INVALIDARG; + + principal->logon_type = logon_type; + return S_OK; } static HRESULT WINAPI Principal_get_GroupId(IPrincipal *iface, BSTR *group_id) @@ -2610,6 +2624,7 @@ static HRESULT Principal_create(IPrincipal **obj) principal->IPrincipal_iface.lpVtbl = &Principal_vtbl; principal->ref = 1; principal->user_id = NULL; + principal->logon_type = TASK_LOGON_INTERACTIVE_TOKEN; *obj = &principal->IPrincipal_iface; diff --git a/dlls/taskschd/tests/scheduler.c b/dlls/taskschd/tests/scheduler.c index 705ba478471..27bb20c85c8 100644 --- a/dlls/taskschd/tests/scheduler.c +++ b/dlls/taskschd/tests/scheduler.c @@ -1798,6 +1798,33 @@ static void test_principal(IPrincipal *principal) hr = IPrincipal_get_UserId(principal, &bstr); ok(hr == S_OK, "get_UserId failed: %08lx\n", hr); ok(bstr == NULL, "expected NULL, got %s\n", wine_dbgstr_w(bstr)); + + hr = IPrincipal_get_LogonType(principal, NULL); + ok(hr == E_POINTER, "expected E_POINTER, got %#lx\n", hr); + + logon_type = 0xdeadbeef; + hr = IPrincipal_get_LogonType(principal, &logon_type); + ok(hr == S_OK, "get_LogonType failed: %08lx\n", hr); + ok(logon_type == TASK_LOGON_INTERACTIVE_TOKEN, "expected TASK_LOGON_INTERACTIVE_TOKEN, got %u\n", logon_type); + + hr = IPrincipal_put_LogonType(principal, TASK_LOGON_NONE); + ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %#lx\n", hr); + + hr = IPrincipal_put_LogonType(principal, TASK_LOGON_PASSWORD); + ok(hr == S_OK, "put_LogonType failed: %08lx\n", hr); + + logon_type = 0xdeadbeef; + hr = IPrincipal_get_LogonType(principal, &logon_type); + ok(hr == S_OK, "get_LogonType failed: %08lx\n", hr); + ok(logon_type == TASK_LOGON_PASSWORD, "expected TASK_LOGON_PASSWORD, got %u\n", logon_type); + + hr = IPrincipal_put_LogonType(principal, TASK_LOGON_INTERACTIVE_TOKEN); + ok(hr == S_OK, "put_LogonType failed: %08lx\n", hr); + + logon_type = 0xdeadbeef; + hr = IPrincipal_get_LogonType(principal, &logon_type); + ok(hr == S_OK, "get_LogonType failed: %08lx\n", hr); + ok(logon_type == TASK_LOGON_INTERACTIVE_TOKEN, "expected TASK_LOGON_INTERACTIVE_TOKEN, got %u\n", logon_type); } static void test_TaskDefinition(void) -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/11065
participants (2)
-
Oleg Nikulin -
Oleg Nikulin (@owl2)