2 * Copyright (C) 2008 Google (Roy Shea)
3 * Copyright (C) 2018 Dmitry Timoshkov
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
29 #include "mstask_private.h"
30 #include "wine/debug.h"
32 WINE_DEFAULT_DEBUG_CHANNEL(mstask
);
37 IPersistFile IPersistFile_iface
;
39 ITaskDefinition
*task
;
48 static inline TaskImpl
*impl_from_ITask(ITask
*iface
)
50 return CONTAINING_RECORD(iface
, TaskImpl
, ITask_iface
);
53 static inline TaskImpl
*impl_from_IPersistFile( IPersistFile
*iface
)
55 return CONTAINING_RECORD(iface
, TaskImpl
, IPersistFile_iface
);
58 static void TaskDestructor(TaskImpl
*This
)
62 IExecAction_Release(This
->action
);
63 ITaskDefinition_Release(This
->task
);
64 HeapFree(GetProcessHeap(), 0, This
->task_name
);
65 HeapFree(GetProcessHeap(), 0, This
->accountName
);
66 HeapFree(GetProcessHeap(), 0, This
->comment
);
67 HeapFree(GetProcessHeap(), 0, This
->parameters
);
68 HeapFree(GetProcessHeap(), 0, This
);
69 InterlockedDecrement(&dll_ref
);
72 static HRESULT WINAPI
MSTASK_ITask_QueryInterface(
77 TaskImpl
* This
= impl_from_ITask(iface
);
79 TRACE("IID: %s\n", debugstr_guid(riid
));
80 if (ppvObject
== NULL
)
83 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
84 IsEqualGUID(riid
, &IID_ITask
))
86 *ppvObject
= &This
->ITask_iface
;
90 else if (IsEqualGUID(riid
, &IID_IPersistFile
))
92 *ppvObject
= &This
->IPersistFile_iface
;
97 WARN("Unknown interface: %s\n", debugstr_guid(riid
));
102 static ULONG WINAPI
MSTASK_ITask_AddRef(
105 TaskImpl
*This
= impl_from_ITask(iface
);
108 ref
= InterlockedIncrement(&This
->ref
);
112 static ULONG WINAPI
MSTASK_ITask_Release(
115 TaskImpl
* This
= impl_from_ITask(iface
);
118 ref
= InterlockedDecrement(&This
->ref
);
120 TaskDestructor(This
);
124 static HRESULT WINAPI
MSTASK_ITask_CreateTrigger(
127 ITaskTrigger
**ppTrigger
)
129 TRACE("(%p, %p, %p)\n", iface
, piNewTrigger
, ppTrigger
);
130 return TaskTriggerConstructor((LPVOID
*)ppTrigger
);
133 static HRESULT WINAPI
MSTASK_ITask_DeleteTrigger(
137 FIXME("(%p, %d): stub\n", iface
, iTrigger
);
141 static HRESULT WINAPI
MSTASK_ITask_GetTriggerCount(
145 FIXME("(%p, %p): stub\n", iface
, plCount
);
149 static HRESULT WINAPI
MSTASK_ITask_GetTrigger(
152 ITaskTrigger
**ppTrigger
)
154 FIXME("(%p, %d, %p): stub\n", iface
, iTrigger
, ppTrigger
);
158 static HRESULT WINAPI
MSTASK_ITask_GetTriggerString(
161 LPWSTR
*ppwszTrigger
)
163 FIXME("(%p, %d, %p): stub\n", iface
, iTrigger
, ppwszTrigger
);
167 static HRESULT WINAPI
MSTASK_ITask_GetRunTimes(
169 const LPSYSTEMTIME pstBegin
,
170 const LPSYSTEMTIME pstEnd
,
172 LPSYSTEMTIME
*rgstTaskTimes
)
174 FIXME("(%p, %p, %p, %p, %p): stub\n", iface
, pstBegin
, pstEnd
, pCount
,
179 static HRESULT WINAPI
MSTASK_ITask_GetNextRunTime(
181 SYSTEMTIME
*pstNextRun
)
183 FIXME("(%p, %p): stub\n", iface
, pstNextRun
);
187 static HRESULT WINAPI
MSTASK_ITask_SetIdleWait(
190 WORD wDeadlineMinutes
)
192 FIXME("(%p, %d, %d): stub\n", iface
, wIdleMinutes
, wDeadlineMinutes
);
196 static HRESULT WINAPI
MSTASK_ITask_GetIdleWait(
199 WORD
*pwDeadlineMinutes
)
201 FIXME("(%p, %p, %p): stub\n", iface
, pwIdleMinutes
, pwDeadlineMinutes
);
205 static HRESULT WINAPI
MSTASK_ITask_Run(
208 FIXME("(%p): stub\n", iface
);
212 static HRESULT WINAPI
MSTASK_ITask_Terminate(
215 FIXME("(%p): stub\n", iface
);
219 static HRESULT WINAPI
MSTASK_ITask_EditWorkItem(
224 FIXME("(%p, %p, %d): stub\n", iface
, hParent
, dwReserved
);
228 static HRESULT WINAPI
MSTASK_ITask_GetMostRecentRunTime(
230 SYSTEMTIME
*pstLastRun
)
232 FIXME("(%p, %p): stub\n", iface
, pstLastRun
);
236 static HRESULT WINAPI
MSTASK_ITask_GetStatus(
240 FIXME("(%p, %p): stub\n", iface
, phrStatus
);
244 static HRESULT WINAPI
MSTASK_ITask_GetExitCode(
248 FIXME("(%p, %p): stub\n", iface
, pdwExitCode
);
252 static HRESULT WINAPI
MSTASK_ITask_SetComment(
257 TaskImpl
*This
= impl_from_ITask(iface
);
260 TRACE("(%p, %s)\n", iface
, debugstr_w(pwszComment
));
263 if (pwszComment
[0] == 0)
265 HeapFree(GetProcessHeap(), 0, This
->comment
);
266 This
->comment
= NULL
;
270 /* Set to pwszComment */
271 n
= (lstrlenW(pwszComment
) + 1);
272 tmp_comment
= HeapAlloc(GetProcessHeap(), 0, n
* sizeof(WCHAR
));
274 return E_OUTOFMEMORY
;
275 lstrcpyW(tmp_comment
, pwszComment
);
276 HeapFree(GetProcessHeap(), 0, This
->comment
);
277 This
->comment
= tmp_comment
;
282 static HRESULT WINAPI
MSTASK_ITask_GetComment(
284 LPWSTR
*ppwszComment
)
287 TaskImpl
*This
= impl_from_ITask(iface
);
289 TRACE("(%p, %p)\n", iface
, ppwszComment
);
291 n
= This
->comment
? lstrlenW(This
->comment
) + 1 : 1;
292 *ppwszComment
= CoTaskMemAlloc(n
* sizeof(WCHAR
));
294 return E_OUTOFMEMORY
;
297 *ppwszComment
[0] = 0;
299 lstrcpyW(*ppwszComment
, This
->comment
);
304 static HRESULT WINAPI
MSTASK_ITask_SetCreator(
308 FIXME("(%p, %p): stub\n", iface
, pwszCreator
);
312 static HRESULT WINAPI
MSTASK_ITask_GetCreator(
314 LPWSTR
*ppwszCreator
)
316 FIXME("(%p, %p): stub\n", iface
, ppwszCreator
);
320 static HRESULT WINAPI
MSTASK_ITask_SetWorkItemData(
325 FIXME("(%p, %d, %p): stub\n", iface
, cBytes
, rgbData
);
329 static HRESULT WINAPI
MSTASK_ITask_GetWorkItemData(
334 FIXME("(%p, %p, %p): stub\n", iface
, pcBytes
, ppBytes
);
338 static HRESULT WINAPI
MSTASK_ITask_SetErrorRetryCount(
342 FIXME("(%p, %d): stub\n", iface
, wRetryCount
);
346 static HRESULT WINAPI
MSTASK_ITask_GetErrorRetryCount(
350 FIXME("(%p, %p): stub\n", iface
, pwRetryCount
);
354 static HRESULT WINAPI
MSTASK_ITask_SetErrorRetryInterval(
358 FIXME("(%p, %d): stub\n", iface
, wRetryInterval
);
362 static HRESULT WINAPI
MSTASK_ITask_GetErrorRetryInterval(
364 WORD
*pwRetryInterval
)
366 FIXME("(%p, %p): stub\n", iface
, pwRetryInterval
);
370 static HRESULT WINAPI
MSTASK_ITask_SetFlags(
374 FIXME("(%p, 0x%08x): stub\n", iface
, dwFlags
);
378 static HRESULT WINAPI
MSTASK_ITask_GetFlags(ITask
*iface
, DWORD
*flags
)
380 FIXME("(%p, %p): stub\n", iface
, flags
);
385 static HRESULT WINAPI
MSTASK_ITask_SetAccountInformation(
387 LPCWSTR pwszAccountName
,
388 LPCWSTR pwszPassword
)
391 TaskImpl
*This
= impl_from_ITask(iface
);
392 LPWSTR tmp_account_name
;
394 TRACE("(%p, %s, %s): partial stub\n", iface
, debugstr_w(pwszAccountName
),
395 debugstr_w(pwszPassword
));
398 FIXME("Partial stub ignores passwords\n");
400 n
= (lstrlenW(pwszAccountName
) + 1);
401 tmp_account_name
= HeapAlloc(GetProcessHeap(), 0, n
* sizeof(WCHAR
));
402 if (!tmp_account_name
)
403 return E_OUTOFMEMORY
;
404 lstrcpyW(tmp_account_name
, pwszAccountName
);
405 HeapFree(GetProcessHeap(), 0, This
->accountName
);
406 This
->accountName
= tmp_account_name
;
410 static HRESULT WINAPI
MSTASK_ITask_GetAccountInformation(
412 LPWSTR
*ppwszAccountName
)
415 TaskImpl
*This
= impl_from_ITask(iface
);
417 TRACE("(%p, %p): partial stub\n", iface
, ppwszAccountName
);
419 /* This implements the WinXP behavior when accountName has not yet
420 * set. Win2K behaves differently, returning SCHED_E_CANNOT_OPEN_TASK */
421 if (!This
->accountName
)
422 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
);
424 n
= (lstrlenW(This
->accountName
) + 1);
425 *ppwszAccountName
= CoTaskMemAlloc(n
* sizeof(WCHAR
));
426 if (!*ppwszAccountName
)
427 return E_OUTOFMEMORY
;
428 lstrcpyW(*ppwszAccountName
, This
->accountName
);
432 static HRESULT WINAPI
MSTASK_ITask_SetApplicationName(ITask
*iface
, LPCWSTR appname
)
434 TaskImpl
*This
= impl_from_ITask(iface
);
437 TRACE("(%p, %s)\n", iface
, debugstr_w(appname
));
439 /* Empty application name */
440 if (!appname
|| !appname
[0])
441 return IExecAction_put_Path(This
->action
, NULL
);
443 /* Attempt to set pwszApplicationName to a path resolved application name */
444 len
= SearchPathW(NULL
, appname
, NULL
, 0, NULL
, NULL
);
450 tmp_name
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
452 return E_OUTOFMEMORY
;
453 len
= SearchPathW(NULL
, appname
, NULL
, len
, tmp_name
, NULL
);
455 hr
= IExecAction_put_Path(This
->action
, tmp_name
);
457 hr
= HRESULT_FROM_WIN32(GetLastError());
459 HeapFree(GetProcessHeap(), 0, tmp_name
);
463 /* If unable to path resolve name, simply set to appname */
464 return IExecAction_put_Path(This
->action
, (BSTR
)appname
);
467 static HRESULT WINAPI
MSTASK_ITask_GetApplicationName(ITask
*iface
, LPWSTR
*appname
)
469 TaskImpl
*This
= impl_from_ITask(iface
);
474 TRACE("(%p, %p)\n", iface
, appname
);
476 hr
= IExecAction_get_Path(This
->action
, &path
);
477 if (hr
!= S_OK
) return hr
;
479 len
= path
? lstrlenW(path
) + 1 : 1;
480 *appname
= CoTaskMemAlloc(len
* sizeof(WCHAR
));
486 lstrcpyW(*appname
, path
);
496 static HRESULT WINAPI
MSTASK_ITask_SetParameters(
498 LPCWSTR pwszParameters
)
501 TaskImpl
*This
= impl_from_ITask(iface
);
502 LPWSTR tmp_parameters
;
504 TRACE("(%p, %s)\n", iface
, debugstr_w(pwszParameters
));
506 /* Empty parameter list */
507 if (pwszParameters
[0] == 0)
509 HeapFree(GetProcessHeap(), 0, This
->parameters
);
510 This
->parameters
= NULL
;
514 /* Set to pwszParameters */
515 n
= (lstrlenW(pwszParameters
) + 1);
516 tmp_parameters
= HeapAlloc(GetProcessHeap(), 0, n
* sizeof(WCHAR
));
518 return E_OUTOFMEMORY
;
519 lstrcpyW(tmp_parameters
, pwszParameters
);
520 HeapFree(GetProcessHeap(), 0, This
->parameters
);
521 This
->parameters
= tmp_parameters
;
525 static HRESULT WINAPI
MSTASK_ITask_GetParameters(
527 LPWSTR
*ppwszParameters
)
530 TaskImpl
*This
= impl_from_ITask(iface
);
532 TRACE("(%p, %p)\n", iface
, ppwszParameters
);
534 n
= This
->parameters
? lstrlenW(This
->parameters
) + 1 : 1;
535 *ppwszParameters
= CoTaskMemAlloc(n
* sizeof(WCHAR
));
536 if (!*ppwszParameters
)
537 return E_OUTOFMEMORY
;
539 if (!This
->parameters
)
540 *ppwszParameters
[0] = 0;
542 lstrcpyW(*ppwszParameters
, This
->parameters
);
547 static HRESULT WINAPI
MSTASK_ITask_SetWorkingDirectory(
549 LPCWSTR pwszWorkingDirectory
)
551 FIXME("(%p, %s): stub\n", iface
, debugstr_w(pwszWorkingDirectory
));
555 static HRESULT WINAPI
MSTASK_ITask_GetWorkingDirectory(
557 LPWSTR
*ppwszWorkingDirectory
)
559 FIXME("(%p, %p): stub\n", iface
, ppwszWorkingDirectory
);
563 static HRESULT WINAPI
MSTASK_ITask_SetPriority(
567 FIXME("(%p, 0x%08x): stub\n", iface
, dwPriority
);
571 static HRESULT WINAPI
MSTASK_ITask_GetPriority(
575 FIXME("(%p, %p): stub\n", iface
, pdwPriority
);
579 static HRESULT WINAPI
MSTASK_ITask_SetTaskFlags(
583 FIXME("(%p, 0x%08x): stub\n", iface
, dwFlags
);
587 static HRESULT WINAPI
MSTASK_ITask_GetTaskFlags(ITask
*iface
, DWORD
*flags
)
589 FIXME("(%p, %p): stub\n", iface
, flags
);
594 static HRESULT WINAPI
MSTASK_ITask_SetMaxRunTime(
598 TaskImpl
*This
= impl_from_ITask(iface
);
600 TRACE("(%p, %d)\n", iface
, dwMaxRunTime
);
602 This
->maxRunTime
= dwMaxRunTime
;
606 static HRESULT WINAPI
MSTASK_ITask_GetMaxRunTime(
608 DWORD
*pdwMaxRunTime
)
610 TaskImpl
*This
= impl_from_ITask(iface
);
612 TRACE("(%p, %p)\n", iface
, pdwMaxRunTime
);
614 *pdwMaxRunTime
= This
->maxRunTime
;
618 static HRESULT WINAPI
MSTASK_IPersistFile_QueryInterface(
623 TaskImpl
*This
= impl_from_IPersistFile(iface
);
624 TRACE("(%p, %s, %p)\n", iface
, debugstr_guid(riid
), ppvObject
);
625 return ITask_QueryInterface(&This
->ITask_iface
, riid
, ppvObject
);
628 static ULONG WINAPI
MSTASK_IPersistFile_AddRef(
631 TaskImpl
*This
= impl_from_IPersistFile(iface
);
634 ref
= InterlockedIncrement(&This
->ref
);
638 static ULONG WINAPI
MSTASK_IPersistFile_Release(
641 TaskImpl
*This
= impl_from_IPersistFile(iface
);
644 ref
= InterlockedDecrement(&This
->ref
);
646 TaskDestructor(This
);
650 static HRESULT WINAPI
MSTASK_IPersistFile_GetClassID(
654 FIXME("(%p, %p): stub\n", iface
, pClassID
);
658 static HRESULT WINAPI
MSTASK_IPersistFile_IsDirty(
661 FIXME("(%p): stub\n", iface
);
665 static HRESULT WINAPI
MSTASK_IPersistFile_Load(
667 LPCOLESTR pszFileName
,
670 FIXME("(%p, %p, 0x%08x): stub\n", iface
, pszFileName
, dwMode
);
674 static HRESULT WINAPI
MSTASK_IPersistFile_Save(
676 LPCOLESTR pszFileName
,
679 FIXME("(%p, %p, %d): stub\n", iface
, pszFileName
, fRemember
);
680 WARN("Returning S_OK but not writing to disk: %s %d\n",
681 debugstr_w(pszFileName
), fRemember
);
685 static HRESULT WINAPI
MSTASK_IPersistFile_SaveCompleted(
687 LPCOLESTR pszFileName
)
689 FIXME("(%p, %p): stub\n", iface
, pszFileName
);
693 static HRESULT WINAPI
MSTASK_IPersistFile_GetCurFile(
695 LPOLESTR
*ppszFileName
)
697 FIXME("(%p, %p): stub\n", iface
, ppszFileName
);
702 static const ITaskVtbl MSTASK_ITaskVtbl
=
704 MSTASK_ITask_QueryInterface
,
706 MSTASK_ITask_Release
,
707 MSTASK_ITask_CreateTrigger
,
708 MSTASK_ITask_DeleteTrigger
,
709 MSTASK_ITask_GetTriggerCount
,
710 MSTASK_ITask_GetTrigger
,
711 MSTASK_ITask_GetTriggerString
,
712 MSTASK_ITask_GetRunTimes
,
713 MSTASK_ITask_GetNextRunTime
,
714 MSTASK_ITask_SetIdleWait
,
715 MSTASK_ITask_GetIdleWait
,
717 MSTASK_ITask_Terminate
,
718 MSTASK_ITask_EditWorkItem
,
719 MSTASK_ITask_GetMostRecentRunTime
,
720 MSTASK_ITask_GetStatus
,
721 MSTASK_ITask_GetExitCode
,
722 MSTASK_ITask_SetComment
,
723 MSTASK_ITask_GetComment
,
724 MSTASK_ITask_SetCreator
,
725 MSTASK_ITask_GetCreator
,
726 MSTASK_ITask_SetWorkItemData
,
727 MSTASK_ITask_GetWorkItemData
,
728 MSTASK_ITask_SetErrorRetryCount
,
729 MSTASK_ITask_GetErrorRetryCount
,
730 MSTASK_ITask_SetErrorRetryInterval
,
731 MSTASK_ITask_GetErrorRetryInterval
,
732 MSTASK_ITask_SetFlags
,
733 MSTASK_ITask_GetFlags
,
734 MSTASK_ITask_SetAccountInformation
,
735 MSTASK_ITask_GetAccountInformation
,
736 MSTASK_ITask_SetApplicationName
,
737 MSTASK_ITask_GetApplicationName
,
738 MSTASK_ITask_SetParameters
,
739 MSTASK_ITask_GetParameters
,
740 MSTASK_ITask_SetWorkingDirectory
,
741 MSTASK_ITask_GetWorkingDirectory
,
742 MSTASK_ITask_SetPriority
,
743 MSTASK_ITask_GetPriority
,
744 MSTASK_ITask_SetTaskFlags
,
745 MSTASK_ITask_GetTaskFlags
,
746 MSTASK_ITask_SetMaxRunTime
,
747 MSTASK_ITask_GetMaxRunTime
750 static const IPersistFileVtbl MSTASK_IPersistFileVtbl
=
752 MSTASK_IPersistFile_QueryInterface
,
753 MSTASK_IPersistFile_AddRef
,
754 MSTASK_IPersistFile_Release
,
755 MSTASK_IPersistFile_GetClassID
,
756 MSTASK_IPersistFile_IsDirty
,
757 MSTASK_IPersistFile_Load
,
758 MSTASK_IPersistFile_Save
,
759 MSTASK_IPersistFile_SaveCompleted
,
760 MSTASK_IPersistFile_GetCurFile
763 HRESULT
TaskConstructor(ITaskService
*service
, const WCHAR
*task_name
, ITask
**task
)
766 ITaskDefinition
*taskdef
;
767 IActionCollection
*actions
;
770 TRACE("(%s, %p)\n", debugstr_w(task_name
), task
);
772 hr
= ITaskService_NewTask(service
, 0, &taskdef
);
773 if (hr
!= S_OK
) return hr
;
775 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
778 ITaskDefinition_Release(taskdef
);
779 return E_OUTOFMEMORY
;
782 This
->ITask_iface
.lpVtbl
= &MSTASK_ITaskVtbl
;
783 This
->IPersistFile_iface
.lpVtbl
= &MSTASK_IPersistFileVtbl
;
785 This
->task
= taskdef
;
786 This
->task_name
= heap_strdupW(task_name
);
787 This
->parameters
= NULL
;
788 This
->comment
= NULL
;
789 This
->accountName
= NULL
;
791 /* Default time is 3 days = 259200000 ms */
792 This
->maxRunTime
= 259200000;
794 hr
= ITaskDefinition_get_Actions(This
->task
, &actions
);
797 hr
= IActionCollection_Create(actions
, TASK_ACTION_EXEC
, (IAction
**)&This
->action
);
798 IActionCollection_Release(actions
);
801 *task
= &This
->ITask_iface
;
802 InterlockedIncrement(&dll_ref
);
807 ITaskDefinition_Release(This
->task
);
808 ITask_Release(&This
->ITask_iface
);