[PATCH 0/2] MR10345: taskschd: Add implemention for ILogonTrigger.
I have ported an application called "Fenbi Live Course", which is an teaching-oriented application. But when installed on wine, it crashed. I found that the application use the com class ILogononTrigger which is not implemented by wine. It is used like this: hr = pTriggerCollection->Create( TASK_TRIGGER_LOGON, &pTrigger ); I just complete the code it needs. I can't put the installer program in the attachment because the file is too big. I put the download url here if you need it. [](https://www.fenbi.com/page/download). -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10345
From: Kun Yang <yangkun@uniontech.com> This is tests for ILogonTrigger class created by ITriggerCollection. Signed-off-by: Kun Yang <yangkun@uniontech.com> --- dlls/taskschd/tests/scheduler.c | 104 ++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) diff --git a/dlls/taskschd/tests/scheduler.c b/dlls/taskschd/tests/scheduler.c index 7715ef0845d..b2d2309ee1a 100644 --- a/dlls/taskschd/tests/scheduler.c +++ b/dlls/taskschd/tests/scheduler.c @@ -1426,6 +1426,103 @@ static void test_registration_trigger(ITrigger *trigger) IRegistrationTrigger_Release(reg_trigger); } +static void test_logon_trigger(ITrigger *trigger) +{ + ILogonTrigger *log_trigger; + HRESULT hr; + TASK_TRIGGER_TYPE2 type; + BSTR id, exc_time_limit, start_boundary, end_boundary, delay, user_id; + VARIANT_BOOL enabled; + static WCHAR id_str[] = L"Trigger_id_test"; + static WCHAR exc_time_limit_str[] = L"Time_limit_test"; + static WCHAR start_boundary_str[] = L"2023-01-01T00:00:00"; + static WCHAR end_boundary_str[] = L"2026-01-01T01:00:00"; + static WCHAR delay_str[] = L"10H"; + static WCHAR user_id_str[] = L"User_id_test"; + + hr = ITrigger_QueryInterface(trigger, &IID_ILogonTrigger, (void**)&log_trigger); + ok(hr == S_OK, "Could not get IRegistrationTrigger iface: %08lx\n", hr); + + hr = ILogonTrigger_get_Type(log_trigger, &type); + ok(hr == S_OK, "get_Type failed: %08lx\n", hr); + ok(type == TASK_TRIGGER_LOGON, "got %u\n", type); + + hr = ILogonTrigger_get_Id(log_trigger, &id); + ok(hr == S_OK, "get_Id failed: %08lx\n", hr); + ok(id == NULL, "test ok!\n"); + + hr = ILogonTrigger_put_Id(log_trigger, id_str); + ok(hr == S_OK, "put_Id failed: %08lx\n", hr); + hr = ILogonTrigger_get_Id(log_trigger, &id); + ok(hr == S_OK, "get_Id failed: %08lx\n", hr); + ok(!lstrcmpW(id, id_str), "got %s\n", wine_dbgstr_w(id)); + + hr = ILogonTrigger_get_ExecutionTimeLimit(log_trigger, &exc_time_limit); + ok(hr == S_OK, "get_ExecutionTimeLimit failed: %08lx\n", hr); + ok(exc_time_limit == NULL, "test ok!\n"); + + hr = ILogonTrigger_put_ExecutionTimeLimit(log_trigger, exc_time_limit_str); + ok(hr == S_OK, "put_ExecutionTimeLimit failed: %08lx\n", hr); + hr = ILogonTrigger_get_ExecutionTimeLimit(log_trigger, &exc_time_limit); + ok(hr == S_OK, "get_ExecutionTimeLimit failed: %08lx\n", hr); + ok(!lstrcmpW(exc_time_limit, exc_time_limit_str), "got %s\n", wine_dbgstr_w(exc_time_limit)); + + hr = ILogonTrigger_get_StartBoundary(log_trigger, &start_boundary); + ok(hr == S_OK, "get_StartBoundary failed: %08lx\n", hr); + ok(start_boundary == NULL, "test ok!\n"); + + hr = ILogonTrigger_put_StartBoundary(log_trigger, start_boundary_str); + ok(hr == S_OK, "put_StartBoundary failed: %08lx\n", hr); + hr = ILogonTrigger_get_StartBoundary(log_trigger, &start_boundary); + ok(hr == S_OK, "get_StartBoundary failed: %08lx\n", hr); + ok(!lstrcmpW(start_boundary, start_boundary_str), "got %s\n", wine_dbgstr_w(start_boundary)); + + hr = ILogonTrigger_get_EndBoundary(log_trigger, &end_boundary); + ok(hr == S_OK, "get_EndBoundary failed: %08lx\n", hr); + ok(end_boundary == NULL, "test ok!\n"); + + hr = ILogonTrigger_put_EndBoundary(log_trigger, end_boundary_str); + ok(hr == S_OK, "put_EndBoundary failed: %08lx\n", hr); + hr = ILogonTrigger_get_EndBoundary(log_trigger, &end_boundary); + ok(hr == S_OK, "get_EndBoundary failed: %08lx\n", hr); + ok(!lstrcmpW(end_boundary, end_boundary_str), "got %s\n", wine_dbgstr_w(end_boundary)); + + enabled = VARIANT_FALSE; + hr = ILogonTrigger_get_Enabled(log_trigger, &enabled); + ok(hr == S_OK, "get_Enabled failed: %08lx\n", hr); + ok(enabled == VARIANT_TRUE, "got %d\n", enabled); + + hr = ILogonTrigger_put_Enabled(log_trigger, VARIANT_FALSE); + ok(hr == S_OK, "put_Enabled failed: %08lx\n", hr); + + enabled = VARIANT_TRUE; + hr = ILogonTrigger_get_Enabled(log_trigger, &enabled); + ok(hr == S_OK, "get_Enabled failed: %08lx\n", hr); + ok(enabled == VARIANT_FALSE, "got %d\n", enabled); + + hr = ILogonTrigger_get_Delay(log_trigger, &delay); + ok(hr == S_OK, "get_Delay failed: %08lx\n", hr); + ok(delay == NULL, "test ok!\n"); + + hr = ILogonTrigger_put_Delay(log_trigger, delay_str); + ok(hr == S_OK, "put_Delay failed: %08lx\n", hr); + hr = ILogonTrigger_get_Delay(log_trigger, &delay); + ok(hr == S_OK, "get_EndBoundary failed: %08lx\n", hr); + ok(!lstrcmpW(delay, delay_str), "got %s\n", wine_dbgstr_w(delay)); + + hr = ILogonTrigger_get_UserId(log_trigger, &user_id); + ok(hr == S_OK, "get_UserId failed: %08lx\n", hr); + ok(user_id == NULL, "test ok!\n"); + + hr = ILogonTrigger_put_UserId(log_trigger, user_id_str); + ok(hr == S_OK, "put_UserId failed: %08lx\n", hr); + hr = ILogonTrigger_get_UserId(log_trigger, &user_id); + ok(hr == S_OK, "get_UserId failed: %08lx\n", hr); + ok(!lstrcmpW(user_id, user_id_str), "got %s\n", wine_dbgstr_w(user_id)); + + ILogonTrigger_Release(log_trigger); +} + static void create_action(ITaskDefinition *taskdef) { static WCHAR task1_exe[] = L"task1.exe"; @@ -1850,6 +1947,13 @@ static void test_TaskDefinition(void) ok(trigger != NULL, "trigger = NULL\n"); test_registration_trigger(trigger); ITrigger_Release(trigger); + + hr = ITriggerCollection_Create(trigger_col, TASK_TRIGGER_LOGON, &trigger); + todo_wine + ok(hr == S_OK, "Create failed: %08lx\n", hr); + ok(trigger != NULL, "trigger = NULL\n"); + test_logon_trigger(trigger); + ITrigger_Release(trigger); ITriggerCollection_Release(trigger_col); hr = ITaskDefinition_get_Triggers(taskdef, &trigger_col2); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10345
From: Kun Yang <yangkun@uniontech.com> Signed-off-by: Kun Yang <yangkun@uniontech.com> --- dlls/taskschd/task.c | 368 ++++++++++++++++++++++++++++++++ dlls/taskschd/tests/scheduler.c | 1 - 2 files changed, 368 insertions(+), 1 deletion(-) diff --git a/dlls/taskschd/task.c b/dlls/taskschd/task.c index 2ade926bf90..7525a52566d 100644 --- a/dlls/taskschd/task.c +++ b/dlls/taskschd/task.c @@ -819,6 +819,372 @@ static HRESULT RegistrationTrigger_create(ITrigger **trigger) return S_OK; } +typedef struct { + ILogonTrigger ILogonTrigger_iface; + BOOL enabled; + LONG ref; + WCHAR *user_id; + WCHAR *id; + WCHAR *execution_time_limit; + WCHAR *start_boundary; + WCHAR *end_boundary; + WCHAR *delay; +} LogonTrigger; + +static inline LogonTrigger *impl_from_ILogonTrigger(ILogonTrigger *iface) +{ + return CONTAINING_RECORD(iface, LogonTrigger, ILogonTrigger_iface); +} + +static HRESULT WINAPI LogonTrigger_QueryInterface(ILogonTrigger *iface, REFIID riid, void **ppv) +{ + LogonTrigger *This = impl_from_ILogonTrigger(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_ILogonTrigger, riid)) + { + *ppv = &This->ILogonTrigger_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 LogonTrigger_AddRef(ILogonTrigger *iface) +{ + LogonTrigger *This = impl_from_ILogonTrigger(iface); + LONG ref = InterlockedIncrement(&This->ref); + TRACE("(%p) ref=%ld\n", This, ref); + + return ref; +} + +static ULONG WINAPI LogonTrigger_Release(ILogonTrigger *iface) +{ + LogonTrigger *This = impl_from_ILogonTrigger(iface); + LONG ref = InterlockedDecrement(&This->ref); + + TRACE("(%p) ref=%ld\n", This, ref); + + if(!ref) + { + TRACE("destroying %p\n", iface); + free(This->user_id); + free(This->id); + free(This->execution_time_limit); + free(This->start_boundary); + free(This->end_boundary); + free(This->delay); + free(This); + } + + return ref; +} + +static HRESULT WINAPI LogonTrigger_GetTypeInfoCount(ILogonTrigger *iface, UINT *count) +{ + LogonTrigger *This = impl_from_ILogonTrigger(iface); + FIXME("(%p)->(%p)\n", This, count); + return E_NOTIMPL; +} + +static HRESULT WINAPI LogonTrigger_GetTypeInfo(ILogonTrigger *iface, UINT index, LCID lcid, ITypeInfo **info) +{ + LogonTrigger *This = impl_from_ILogonTrigger(iface); + FIXME("(%p)->(%u %lu %p)\n", This, index, lcid, info); + return E_NOTIMPL; +} + +static HRESULT WINAPI LogonTrigger_GetIDsOfNames(ILogonTrigger *iface, REFIID riid, LPOLESTR *names, + UINT count, LCID lcid, DISPID *dispid) +{ + LogonTrigger *This = impl_from_ILogonTrigger(iface); + FIXME("(%p)->(%s %p %u %lu %p)\n", This, debugstr_guid(riid), names, count, lcid, dispid); + return E_NOTIMPL; +} + +static HRESULT WINAPI LogonTrigger_Invoke(ILogonTrigger *iface, DISPID dispid, REFIID riid, LCID lcid, WORD flags, + DISPPARAMS *params, VARIANT *result, EXCEPINFO *excepinfo, UINT *argerr) +{ + LogonTrigger *This = impl_from_ILogonTrigger(iface); + FIXME("(%p)->(%ld %s %lx %x %p %p %p %p)\n", This, dispid, debugstr_guid(riid), lcid, flags, + params, result, excepinfo, argerr); + return E_NOTIMPL; +} + +static HRESULT WINAPI LogonTrigger_get_Type(ILogonTrigger *iface, TASK_TRIGGER_TYPE2 *type) +{ + LogonTrigger *This = impl_from_ILogonTrigger(iface); + + TRACE("(%p)->(%p)\n", This, type); + + if (!type) return E_POINTER; + + *type = TASK_TRIGGER_LOGON; + return S_OK; +} + +static HRESULT WINAPI LogonTrigger_get_Id(ILogonTrigger *iface, BSTR *id) +{ + LogonTrigger *This = impl_from_ILogonTrigger(iface); + + TRACE("(%p)->(%p)\n", This, id); + + if (!id) return E_POINTER; + + if (!This->id) *id = NULL; + else if (!(*id = SysAllocString(This->id))) return E_OUTOFMEMORY; + + return S_OK; +} + +static HRESULT WINAPI LogonTrigger_put_Id(ILogonTrigger *iface, BSTR id) +{ + LogonTrigger *This = impl_from_ILogonTrigger(iface); + WCHAR *str = NULL; + + TRACE("(%p)->(%s)\n", This, debugstr_w(id)); + + if (id && !(str = wcsdup(id))) return E_OUTOFMEMORY; + free(This->id); + This->id = str; + return S_OK; +} + +static HRESULT WINAPI LogonTrigger_get_Repetition(ILogonTrigger *iface, IRepetitionPattern **repeat) +{ + LogonTrigger *This = impl_from_ILogonTrigger(iface); + + TRACE("(%p)->(%p)\n", This, repeat); + + if (!repeat) return E_POINTER; + + return RepetitionPattern_create(repeat); +} + +static HRESULT WINAPI LogonTrigger_put_Repetition(ILogonTrigger *iface, IRepetitionPattern *repeat) +{ + LogonTrigger *This = impl_from_ILogonTrigger(iface); + FIXME("(%p)->(%p)\n", This, repeat); + return E_NOTIMPL; +} + +static HRESULT WINAPI LogonTrigger_get_ExecutionTimeLimit(ILogonTrigger *iface, BSTR *limit) +{ + LogonTrigger *This = impl_from_ILogonTrigger(iface); + + TRACE("(%p)->(%p)\n", This, limit); + + if (!limit) return E_POINTER; + + if (!This->execution_time_limit) *limit = NULL; + else if (!(*limit = SysAllocString(This->execution_time_limit))) return E_OUTOFMEMORY; + + return S_OK; +} + +static HRESULT WINAPI LogonTrigger_put_ExecutionTimeLimit(ILogonTrigger *iface, BSTR limit) +{ + LogonTrigger *This = impl_from_ILogonTrigger(iface); + WCHAR *str = NULL; + + TRACE("(%p)->(%s)\n", This, debugstr_w(limit)); + + if (limit && !(str = wcsdup(limit))) return E_OUTOFMEMORY; + free(This->execution_time_limit); + This->execution_time_limit = str; + return S_OK; +} + +static HRESULT WINAPI LogonTrigger_get_StartBoundary(ILogonTrigger *iface, BSTR *start) +{ + LogonTrigger *This = impl_from_ILogonTrigger(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 LogonTrigger_put_StartBoundary(ILogonTrigger *iface, BSTR start) +{ + LogonTrigger *This = impl_from_ILogonTrigger(iface); + WCHAR *str = NULL; + + TRACE("(%p)->(%s)\n", This, debugstr_w(start)); + + if (start && !(str = wcsdup(start))) return E_OUTOFMEMORY; + free(This->start_boundary); + This->start_boundary = str; + return S_OK; +} + +static HRESULT WINAPI LogonTrigger_get_EndBoundary(ILogonTrigger *iface, BSTR *end) +{ + LogonTrigger *This = impl_from_ILogonTrigger(iface); + + TRACE("(%p)->(%p)\n", This, end); + + if (!end) return E_POINTER; + + if (!This->end_boundary) *end = NULL; + else if (!(*end = SysAllocString(This->end_boundary))) return E_OUTOFMEMORY; + + return S_OK; +} + +static HRESULT WINAPI LogonTrigger_put_EndBoundary(ILogonTrigger *iface, BSTR end) +{ + LogonTrigger *This = impl_from_ILogonTrigger(iface); + WCHAR *str = NULL; + + TRACE("(%p)->(%s)\n", This, debugstr_w(end)); + + if (end && !(str = wcsdup(end))) return E_OUTOFMEMORY; + free(This->end_boundary); + This->end_boundary = str; + return S_OK; +} + +static HRESULT WINAPI LogonTrigger_get_Enabled(ILogonTrigger *iface, VARIANT_BOOL *enabled) +{ + LogonTrigger *This = impl_from_ILogonTrigger(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 LogonTrigger_put_Enabled(ILogonTrigger *iface, VARIANT_BOOL enabled) +{ + LogonTrigger *This = impl_from_ILogonTrigger(iface); + + TRACE("(%p)->(%x)\n", This, enabled); + + This->enabled = !!enabled; + return S_OK; +} + +static HRESULT WINAPI LogonTrigger_get_Delay(ILogonTrigger *iface, BSTR *pDelay) +{ + LogonTrigger *This = impl_from_ILogonTrigger(iface); + + TRACE("(%p)->(%p)\n", This, pDelay); + + if (!pDelay) return E_POINTER; + + if (!This->delay) *pDelay = NULL; + else if (!(*pDelay = SysAllocString(This->delay))) return E_OUTOFMEMORY; + + return S_OK; +} + +static HRESULT WINAPI LogonTrigger_put_Delay(ILogonTrigger *iface, BSTR delay) +{ + LogonTrigger *This = impl_from_ILogonTrigger(iface); + WCHAR *str = NULL; + + TRACE("(%p)->(%s)\n", This, debugstr_w(delay)); + + if (delay && !(str = wcsdup(delay))) return E_OUTOFMEMORY; + free(This->delay); + This->delay = str; + return S_OK; +} + +static HRESULT WINAPI LogonTrigger_get_UserId(ILogonTrigger *iface, BSTR *pUser) +{ + LogonTrigger *This = impl_from_ILogonTrigger(iface); + + TRACE("(%p)->(%p)\n", This, pUser); + + if (!pUser) return E_POINTER; + + if (!This->user_id) *pUser = NULL; + else if (!(*pUser = SysAllocString(This->user_id))) return E_OUTOFMEMORY; + + return S_OK; +} + +static HRESULT WINAPI LogonTrigger_put_UserId(ILogonTrigger *iface, BSTR user) +{ + LogonTrigger *This = impl_from_ILogonTrigger(iface); + WCHAR *str = NULL; + + TRACE("(%p)->(%s)\n", This, debugstr_w(user)); + + if (user && !(str = wcsdup(user))) return E_OUTOFMEMORY; + free(This->user_id); + This->user_id = str; + return S_OK; +} + +static const ILogonTriggerVtbl LogonTrigger_vtbl = { + LogonTrigger_QueryInterface, + LogonTrigger_AddRef, + LogonTrigger_Release, + LogonTrigger_GetTypeInfoCount, + LogonTrigger_GetTypeInfo, + LogonTrigger_GetIDsOfNames, + LogonTrigger_Invoke, + LogonTrigger_get_Type, + LogonTrigger_get_Id, + LogonTrigger_put_Id, + LogonTrigger_get_Repetition, + LogonTrigger_put_Repetition, + LogonTrigger_get_ExecutionTimeLimit, + LogonTrigger_put_ExecutionTimeLimit, + LogonTrigger_get_StartBoundary, + LogonTrigger_put_StartBoundary, + LogonTrigger_get_EndBoundary, + LogonTrigger_put_EndBoundary, + LogonTrigger_get_Enabled, + LogonTrigger_put_Enabled, + LogonTrigger_get_Delay, + LogonTrigger_put_Delay, + LogonTrigger_get_UserId, + LogonTrigger_put_UserId +}; + +static HRESULT LogonTrigger_create(ITrigger **trigger) +{ + LogonTrigger *logon_trigger; + + logon_trigger = malloc(sizeof(*logon_trigger)); + if (!logon_trigger) + return E_OUTOFMEMORY; + + logon_trigger->ILogonTrigger_iface.lpVtbl = &LogonTrigger_vtbl; + logon_trigger->ref = 1; + logon_trigger->enabled = TRUE; + logon_trigger->user_id = NULL; + logon_trigger->id = NULL; + logon_trigger->execution_time_limit = NULL; + logon_trigger->start_boundary = NULL; + logon_trigger->end_boundary = NULL; + logon_trigger->delay = NULL; + + *trigger = (ITrigger*)&logon_trigger->ILogonTrigger_iface; + return S_OK; +} + typedef struct { ITriggerCollection ITriggerCollection_iface; @@ -936,6 +1302,8 @@ static HRESULT WINAPI TriggerCollection_Create(ITriggerCollection *iface, TASK_T return DailyTrigger_create(trigger); case TASK_TRIGGER_REGISTRATION: return RegistrationTrigger_create(trigger); + case TASK_TRIGGER_LOGON: + return LogonTrigger_create(trigger); default: FIXME("Unimplemented type %d\n", type); return E_NOTIMPL; diff --git a/dlls/taskschd/tests/scheduler.c b/dlls/taskschd/tests/scheduler.c index b2d2309ee1a..025522f322c 100644 --- a/dlls/taskschd/tests/scheduler.c +++ b/dlls/taskschd/tests/scheduler.c @@ -1949,7 +1949,6 @@ static void test_TaskDefinition(void) ITrigger_Release(trigger); hr = ITriggerCollection_Create(trigger_col, TASK_TRIGGER_LOGON, &trigger); - todo_wine ok(hr == S_OK, "Create failed: %08lx\n", hr); ok(trigger != NULL, "trigger = NULL\n"); test_logon_trigger(trigger); -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/10345
the application download url is https://www.fenbi.com/page/download. -- https://gitlab.winehq.org/wine/wine/-/merge_requests/10345#note_132341
participants (2)
-
Kun Yang -
Kun Yang (@yangkun)