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
;
46 static inline TaskImpl
*impl_from_ITask(ITask
*iface
)
48 return CONTAINING_RECORD(iface
, TaskImpl
, ITask_iface
);
51 static inline TaskImpl
*impl_from_IPersistFile( IPersistFile
*iface
)
53 return CONTAINING_RECORD(iface
, TaskImpl
, IPersistFile_iface
);
56 static void TaskDestructor(TaskImpl
*This
)
60 IExecAction_Release(This
->action
);
61 ITaskDefinition_Release(This
->task
);
62 HeapFree(GetProcessHeap(), 0, This
->task_name
);
63 HeapFree(GetProcessHeap(), 0, This
->accountName
);
64 HeapFree(GetProcessHeap(), 0, This
);
65 InterlockedDecrement(&dll_ref
);
68 static HRESULT WINAPI
MSTASK_ITask_QueryInterface(
73 TaskImpl
* This
= impl_from_ITask(iface
);
75 TRACE("IID: %s\n", debugstr_guid(riid
));
76 if (ppvObject
== NULL
)
79 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
80 IsEqualGUID(riid
, &IID_ITask
))
82 *ppvObject
= &This
->ITask_iface
;
86 else if (IsEqualGUID(riid
, &IID_IPersistFile
))
88 *ppvObject
= &This
->IPersistFile_iface
;
93 WARN("Unknown interface: %s\n", debugstr_guid(riid
));
98 static ULONG WINAPI
MSTASK_ITask_AddRef(
101 TaskImpl
*This
= impl_from_ITask(iface
);
104 ref
= InterlockedIncrement(&This
->ref
);
108 static ULONG WINAPI
MSTASK_ITask_Release(
111 TaskImpl
* This
= impl_from_ITask(iface
);
114 ref
= InterlockedDecrement(&This
->ref
);
116 TaskDestructor(This
);
120 static HRESULT WINAPI
MSTASK_ITask_CreateTrigger(
123 ITaskTrigger
**ppTrigger
)
125 TRACE("(%p, %p, %p)\n", iface
, piNewTrigger
, ppTrigger
);
126 return TaskTriggerConstructor((LPVOID
*)ppTrigger
);
129 static HRESULT WINAPI
MSTASK_ITask_DeleteTrigger(
133 FIXME("(%p, %d): stub\n", iface
, iTrigger
);
137 static HRESULT WINAPI
MSTASK_ITask_GetTriggerCount(
141 FIXME("(%p, %p): stub\n", iface
, plCount
);
145 static HRESULT WINAPI
MSTASK_ITask_GetTrigger(
148 ITaskTrigger
**ppTrigger
)
150 FIXME("(%p, %d, %p): stub\n", iface
, iTrigger
, ppTrigger
);
154 static HRESULT WINAPI
MSTASK_ITask_GetTriggerString(
157 LPWSTR
*ppwszTrigger
)
159 FIXME("(%p, %d, %p): stub\n", iface
, iTrigger
, ppwszTrigger
);
163 static HRESULT WINAPI
MSTASK_ITask_GetRunTimes(
165 const LPSYSTEMTIME pstBegin
,
166 const LPSYSTEMTIME pstEnd
,
168 LPSYSTEMTIME
*rgstTaskTimes
)
170 FIXME("(%p, %p, %p, %p, %p): stub\n", iface
, pstBegin
, pstEnd
, pCount
,
175 static HRESULT WINAPI
MSTASK_ITask_GetNextRunTime(
177 SYSTEMTIME
*pstNextRun
)
179 FIXME("(%p, %p): stub\n", iface
, pstNextRun
);
183 static HRESULT WINAPI
MSTASK_ITask_SetIdleWait(
186 WORD wDeadlineMinutes
)
188 FIXME("(%p, %d, %d): stub\n", iface
, wIdleMinutes
, wDeadlineMinutes
);
192 static HRESULT WINAPI
MSTASK_ITask_GetIdleWait(
195 WORD
*pwDeadlineMinutes
)
197 FIXME("(%p, %p, %p): stub\n", iface
, pwIdleMinutes
, pwDeadlineMinutes
);
201 static HRESULT WINAPI
MSTASK_ITask_Run(
204 FIXME("(%p): stub\n", iface
);
208 static HRESULT WINAPI
MSTASK_ITask_Terminate(
211 FIXME("(%p): stub\n", iface
);
215 static HRESULT WINAPI
MSTASK_ITask_EditWorkItem(
220 FIXME("(%p, %p, %d): stub\n", iface
, hParent
, dwReserved
);
224 static HRESULT WINAPI
MSTASK_ITask_GetMostRecentRunTime(
226 SYSTEMTIME
*pstLastRun
)
228 FIXME("(%p, %p): stub\n", iface
, pstLastRun
);
232 static HRESULT WINAPI
MSTASK_ITask_GetStatus(
236 FIXME("(%p, %p): stub\n", iface
, phrStatus
);
240 static HRESULT WINAPI
MSTASK_ITask_GetExitCode(
244 FIXME("(%p, %p): stub\n", iface
, pdwExitCode
);
248 static HRESULT WINAPI
MSTASK_ITask_SetComment(ITask
*iface
, LPCWSTR comment
)
250 TaskImpl
*This
= impl_from_ITask(iface
);
251 IRegistrationInfo
*info
;
254 TRACE("(%p, %s)\n", iface
, debugstr_w(comment
));
256 if (!comment
|| !comment
[0])
259 hr
= ITaskDefinition_get_RegistrationInfo(This
->task
, &info
);
262 hr
= IRegistrationInfo_put_Description(info
, (BSTR
)comment
);
263 IRegistrationInfo_Release(info
);
268 static HRESULT WINAPI
MSTASK_ITask_GetComment(ITask
*iface
, LPWSTR
*comment
)
270 TaskImpl
*This
= impl_from_ITask(iface
);
271 IRegistrationInfo
*info
;
276 TRACE("(%p, %p)\n", iface
, comment
);
278 hr
= ITaskDefinition_get_RegistrationInfo(This
->task
, &info
);
279 if (hr
!= S_OK
) return hr
;
281 hr
= IRegistrationInfo_get_Description(info
, &description
);
284 len
= description
? lstrlenW(description
) + 1 : 1;
285 *comment
= CoTaskMemAlloc(len
* sizeof(WCHAR
));
291 lstrcpyW(*comment
, description
);
297 SysFreeString(description
);
300 IRegistrationInfo_Release(info
);
304 static HRESULT WINAPI
MSTASK_ITask_SetCreator(ITask
*iface
, LPCWSTR creator
)
306 TaskImpl
*This
= impl_from_ITask(iface
);
307 IRegistrationInfo
*info
;
310 TRACE("(%p, %s)\n", iface
, debugstr_w(creator
));
312 if (!creator
|| !creator
[0])
315 hr
= ITaskDefinition_get_RegistrationInfo(This
->task
, &info
);
318 hr
= IRegistrationInfo_put_Author(info
, (BSTR
)creator
);
319 IRegistrationInfo_Release(info
);
324 static HRESULT WINAPI
MSTASK_ITask_GetCreator(ITask
*iface
, LPWSTR
*creator
)
326 TaskImpl
*This
= impl_from_ITask(iface
);
327 IRegistrationInfo
*info
;
332 TRACE("(%p, %p)\n", iface
, creator
);
334 hr
= ITaskDefinition_get_RegistrationInfo(This
->task
, &info
);
335 if (hr
!= S_OK
) return hr
;
337 hr
= IRegistrationInfo_get_Author(info
, &author
);
340 len
= author
? lstrlenW(author
) + 1 : 1;
341 *creator
= CoTaskMemAlloc(len
* sizeof(WCHAR
));
347 lstrcpyW(*creator
, author
);
353 SysFreeString(author
);
356 IRegistrationInfo_Release(info
);
360 static HRESULT WINAPI
MSTASK_ITask_SetWorkItemData(
365 FIXME("(%p, %d, %p): stub\n", iface
, cBytes
, rgbData
);
369 static HRESULT WINAPI
MSTASK_ITask_GetWorkItemData(
374 FIXME("(%p, %p, %p): stub\n", iface
, pcBytes
, ppBytes
);
378 static HRESULT WINAPI
MSTASK_ITask_SetErrorRetryCount(
382 FIXME("(%p, %d): stub\n", iface
, wRetryCount
);
386 static HRESULT WINAPI
MSTASK_ITask_GetErrorRetryCount(
390 FIXME("(%p, %p): stub\n", iface
, pwRetryCount
);
394 static HRESULT WINAPI
MSTASK_ITask_SetErrorRetryInterval(
398 FIXME("(%p, %d): stub\n", iface
, wRetryInterval
);
402 static HRESULT WINAPI
MSTASK_ITask_GetErrorRetryInterval(
404 WORD
*pwRetryInterval
)
406 FIXME("(%p, %p): stub\n", iface
, pwRetryInterval
);
410 static HRESULT WINAPI
MSTASK_ITask_SetFlags(
414 FIXME("(%p, 0x%08x): stub\n", iface
, dwFlags
);
418 static HRESULT WINAPI
MSTASK_ITask_GetFlags(ITask
*iface
, DWORD
*flags
)
420 FIXME("(%p, %p): stub\n", iface
, flags
);
425 static HRESULT WINAPI
MSTASK_ITask_SetAccountInformation(
427 LPCWSTR pwszAccountName
,
428 LPCWSTR pwszPassword
)
431 TaskImpl
*This
= impl_from_ITask(iface
);
432 LPWSTR tmp_account_name
;
434 TRACE("(%p, %s, %s): partial stub\n", iface
, debugstr_w(pwszAccountName
),
435 debugstr_w(pwszPassword
));
438 FIXME("Partial stub ignores passwords\n");
440 n
= (lstrlenW(pwszAccountName
) + 1);
441 tmp_account_name
= HeapAlloc(GetProcessHeap(), 0, n
* sizeof(WCHAR
));
442 if (!tmp_account_name
)
443 return E_OUTOFMEMORY
;
444 lstrcpyW(tmp_account_name
, pwszAccountName
);
445 HeapFree(GetProcessHeap(), 0, This
->accountName
);
446 This
->accountName
= tmp_account_name
;
450 static HRESULT WINAPI
MSTASK_ITask_GetAccountInformation(
452 LPWSTR
*ppwszAccountName
)
455 TaskImpl
*This
= impl_from_ITask(iface
);
457 TRACE("(%p, %p): partial stub\n", iface
, ppwszAccountName
);
459 /* This implements the WinXP behavior when accountName has not yet
460 * set. Win2K behaves differently, returning SCHED_E_CANNOT_OPEN_TASK */
461 if (!This
->accountName
)
462 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
);
464 n
= (lstrlenW(This
->accountName
) + 1);
465 *ppwszAccountName
= CoTaskMemAlloc(n
* sizeof(WCHAR
));
466 if (!*ppwszAccountName
)
467 return E_OUTOFMEMORY
;
468 lstrcpyW(*ppwszAccountName
, This
->accountName
);
472 static HRESULT WINAPI
MSTASK_ITask_SetApplicationName(ITask
*iface
, LPCWSTR appname
)
474 TaskImpl
*This
= impl_from_ITask(iface
);
477 TRACE("(%p, %s)\n", iface
, debugstr_w(appname
));
479 /* Empty application name */
480 if (!appname
|| !appname
[0])
481 return IExecAction_put_Path(This
->action
, NULL
);
483 /* Attempt to set pwszApplicationName to a path resolved application name */
484 len
= SearchPathW(NULL
, appname
, NULL
, 0, NULL
, NULL
);
490 tmp_name
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
492 return E_OUTOFMEMORY
;
493 len
= SearchPathW(NULL
, appname
, NULL
, len
, tmp_name
, NULL
);
495 hr
= IExecAction_put_Path(This
->action
, tmp_name
);
497 hr
= HRESULT_FROM_WIN32(GetLastError());
499 HeapFree(GetProcessHeap(), 0, tmp_name
);
503 /* If unable to path resolve name, simply set to appname */
504 return IExecAction_put_Path(This
->action
, (BSTR
)appname
);
507 static HRESULT WINAPI
MSTASK_ITask_GetApplicationName(ITask
*iface
, LPWSTR
*appname
)
509 TaskImpl
*This
= impl_from_ITask(iface
);
514 TRACE("(%p, %p)\n", iface
, appname
);
516 hr
= IExecAction_get_Path(This
->action
, &path
);
517 if (hr
!= S_OK
) return hr
;
519 len
= path
? lstrlenW(path
) + 1 : 1;
520 *appname
= CoTaskMemAlloc(len
* sizeof(WCHAR
));
526 lstrcpyW(*appname
, path
);
536 static HRESULT WINAPI
MSTASK_ITask_SetParameters(ITask
*iface
, LPCWSTR params
)
538 TaskImpl
*This
= impl_from_ITask(iface
);
540 TRACE("(%p, %s)\n", iface
, debugstr_w(params
));
542 /* Empty parameter list */
543 if (!params
|| !params
[0])
546 return IExecAction_put_Arguments(This
->action
, (BSTR
)params
);
549 static HRESULT WINAPI
MSTASK_ITask_GetParameters(ITask
*iface
, LPWSTR
*params
)
551 TaskImpl
*This
= impl_from_ITask(iface
);
556 TRACE("(%p, %p)\n", iface
, params
);
558 hr
= IExecAction_get_Arguments(This
->action
, &args
);
559 if (hr
!= S_OK
) return hr
;
561 len
= args
? lstrlenW(args
) + 1 : 1;
562 *params
= CoTaskMemAlloc(len
* sizeof(WCHAR
));
568 lstrcpyW(*params
, args
);
578 static HRESULT WINAPI
MSTASK_ITask_SetWorkingDirectory(ITask
* iface
, LPCWSTR workdir
)
580 TaskImpl
*This
= impl_from_ITask(iface
);
582 TRACE("(%p, %s)\n", iface
, debugstr_w(workdir
));
584 if (!workdir
|| !workdir
[0])
587 return IExecAction_put_WorkingDirectory(This
->action
, (BSTR
)workdir
);
590 static HRESULT WINAPI
MSTASK_ITask_GetWorkingDirectory(ITask
*iface
, LPWSTR
*workdir
)
592 TaskImpl
*This
= impl_from_ITask(iface
);
597 TRACE("(%p, %p)\n", iface
, workdir
);
599 hr
= IExecAction_get_WorkingDirectory(This
->action
, &dir
);
600 if (hr
!= S_OK
) return hr
;
602 len
= dir
? lstrlenW(dir
) + 1 : 1;
603 *workdir
= CoTaskMemAlloc(len
* sizeof(WCHAR
));
609 lstrcpyW(*workdir
, dir
);
619 static HRESULT WINAPI
MSTASK_ITask_SetPriority(
623 FIXME("(%p, 0x%08x): stub\n", iface
, dwPriority
);
627 static HRESULT WINAPI
MSTASK_ITask_GetPriority(
631 FIXME("(%p, %p): stub\n", iface
, pdwPriority
);
635 static HRESULT WINAPI
MSTASK_ITask_SetTaskFlags(
639 FIXME("(%p, 0x%08x): stub\n", iface
, dwFlags
);
643 static HRESULT WINAPI
MSTASK_ITask_GetTaskFlags(ITask
*iface
, DWORD
*flags
)
645 FIXME("(%p, %p): stub\n", iface
, flags
);
650 static HRESULT WINAPI
MSTASK_ITask_SetMaxRunTime(
654 TaskImpl
*This
= impl_from_ITask(iface
);
656 TRACE("(%p, %d)\n", iface
, dwMaxRunTime
);
658 This
->maxRunTime
= dwMaxRunTime
;
662 static HRESULT WINAPI
MSTASK_ITask_GetMaxRunTime(
664 DWORD
*pdwMaxRunTime
)
666 TaskImpl
*This
= impl_from_ITask(iface
);
668 TRACE("(%p, %p)\n", iface
, pdwMaxRunTime
);
670 *pdwMaxRunTime
= This
->maxRunTime
;
674 static HRESULT WINAPI
MSTASK_IPersistFile_QueryInterface(
679 TaskImpl
*This
= impl_from_IPersistFile(iface
);
680 TRACE("(%p, %s, %p)\n", iface
, debugstr_guid(riid
), ppvObject
);
681 return ITask_QueryInterface(&This
->ITask_iface
, riid
, ppvObject
);
684 static ULONG WINAPI
MSTASK_IPersistFile_AddRef(
687 TaskImpl
*This
= impl_from_IPersistFile(iface
);
690 ref
= InterlockedIncrement(&This
->ref
);
694 static ULONG WINAPI
MSTASK_IPersistFile_Release(
697 TaskImpl
*This
= impl_from_IPersistFile(iface
);
700 ref
= InterlockedDecrement(&This
->ref
);
702 TaskDestructor(This
);
706 static HRESULT WINAPI
MSTASK_IPersistFile_GetClassID(
710 FIXME("(%p, %p): stub\n", iface
, pClassID
);
714 static HRESULT WINAPI
MSTASK_IPersistFile_IsDirty(
717 FIXME("(%p): stub\n", iface
);
721 static HRESULT WINAPI
MSTASK_IPersistFile_Load(
723 LPCOLESTR pszFileName
,
726 FIXME("(%p, %p, 0x%08x): stub\n", iface
, pszFileName
, dwMode
);
730 static HRESULT WINAPI
MSTASK_IPersistFile_Save(
732 LPCOLESTR pszFileName
,
735 FIXME("(%p, %p, %d): stub\n", iface
, pszFileName
, fRemember
);
736 WARN("Returning S_OK but not writing to disk: %s %d\n",
737 debugstr_w(pszFileName
), fRemember
);
741 static HRESULT WINAPI
MSTASK_IPersistFile_SaveCompleted(
743 LPCOLESTR pszFileName
)
745 FIXME("(%p, %p): stub\n", iface
, pszFileName
);
749 static HRESULT WINAPI
MSTASK_IPersistFile_GetCurFile(
751 LPOLESTR
*ppszFileName
)
753 FIXME("(%p, %p): stub\n", iface
, ppszFileName
);
758 static const ITaskVtbl MSTASK_ITaskVtbl
=
760 MSTASK_ITask_QueryInterface
,
762 MSTASK_ITask_Release
,
763 MSTASK_ITask_CreateTrigger
,
764 MSTASK_ITask_DeleteTrigger
,
765 MSTASK_ITask_GetTriggerCount
,
766 MSTASK_ITask_GetTrigger
,
767 MSTASK_ITask_GetTriggerString
,
768 MSTASK_ITask_GetRunTimes
,
769 MSTASK_ITask_GetNextRunTime
,
770 MSTASK_ITask_SetIdleWait
,
771 MSTASK_ITask_GetIdleWait
,
773 MSTASK_ITask_Terminate
,
774 MSTASK_ITask_EditWorkItem
,
775 MSTASK_ITask_GetMostRecentRunTime
,
776 MSTASK_ITask_GetStatus
,
777 MSTASK_ITask_GetExitCode
,
778 MSTASK_ITask_SetComment
,
779 MSTASK_ITask_GetComment
,
780 MSTASK_ITask_SetCreator
,
781 MSTASK_ITask_GetCreator
,
782 MSTASK_ITask_SetWorkItemData
,
783 MSTASK_ITask_GetWorkItemData
,
784 MSTASK_ITask_SetErrorRetryCount
,
785 MSTASK_ITask_GetErrorRetryCount
,
786 MSTASK_ITask_SetErrorRetryInterval
,
787 MSTASK_ITask_GetErrorRetryInterval
,
788 MSTASK_ITask_SetFlags
,
789 MSTASK_ITask_GetFlags
,
790 MSTASK_ITask_SetAccountInformation
,
791 MSTASK_ITask_GetAccountInformation
,
792 MSTASK_ITask_SetApplicationName
,
793 MSTASK_ITask_GetApplicationName
,
794 MSTASK_ITask_SetParameters
,
795 MSTASK_ITask_GetParameters
,
796 MSTASK_ITask_SetWorkingDirectory
,
797 MSTASK_ITask_GetWorkingDirectory
,
798 MSTASK_ITask_SetPriority
,
799 MSTASK_ITask_GetPriority
,
800 MSTASK_ITask_SetTaskFlags
,
801 MSTASK_ITask_GetTaskFlags
,
802 MSTASK_ITask_SetMaxRunTime
,
803 MSTASK_ITask_GetMaxRunTime
806 static const IPersistFileVtbl MSTASK_IPersistFileVtbl
=
808 MSTASK_IPersistFile_QueryInterface
,
809 MSTASK_IPersistFile_AddRef
,
810 MSTASK_IPersistFile_Release
,
811 MSTASK_IPersistFile_GetClassID
,
812 MSTASK_IPersistFile_IsDirty
,
813 MSTASK_IPersistFile_Load
,
814 MSTASK_IPersistFile_Save
,
815 MSTASK_IPersistFile_SaveCompleted
,
816 MSTASK_IPersistFile_GetCurFile
819 HRESULT
TaskConstructor(ITaskService
*service
, const WCHAR
*task_name
, ITask
**task
)
822 ITaskDefinition
*taskdef
;
823 IActionCollection
*actions
;
826 TRACE("(%s, %p)\n", debugstr_w(task_name
), task
);
828 hr
= ITaskService_NewTask(service
, 0, &taskdef
);
829 if (hr
!= S_OK
) return hr
;
831 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
834 ITaskDefinition_Release(taskdef
);
835 return E_OUTOFMEMORY
;
838 This
->ITask_iface
.lpVtbl
= &MSTASK_ITaskVtbl
;
839 This
->IPersistFile_iface
.lpVtbl
= &MSTASK_IPersistFileVtbl
;
841 This
->task
= taskdef
;
842 This
->task_name
= heap_strdupW(task_name
);
843 This
->accountName
= NULL
;
845 /* Default time is 3 days = 259200000 ms */
846 This
->maxRunTime
= 259200000;
848 hr
= ITaskDefinition_get_Actions(This
->task
, &actions
);
851 hr
= IActionCollection_Create(actions
, TASK_ACTION_EXEC
, (IAction
**)&This
->action
);
852 IActionCollection_Release(actions
);
855 *task
= &This
->ITask_iface
;
856 InterlockedIncrement(&dll_ref
);
861 ITaskDefinition_Release(This
->task
);
862 ITask_Release(&This
->ITask_iface
);