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
);
36 USHORT product_version
;
39 USHORT name_size_offset
;
40 USHORT trigger_offset
;
41 USHORT error_retry_count
;
42 USHORT error_retry_interval
;
50 SYSTEMTIME last_runtime
;
56 IPersistFile IPersistFile_iface
;
58 ITaskDefinition
*task
;
62 WORD idle_minutes
, deadline_minutes
;
63 DWORD priority
, maxRunTime
;
67 static inline TaskImpl
*impl_from_ITask(ITask
*iface
)
69 return CONTAINING_RECORD(iface
, TaskImpl
, ITask_iface
);
72 static inline TaskImpl
*impl_from_IPersistFile( IPersistFile
*iface
)
74 return CONTAINING_RECORD(iface
, TaskImpl
, IPersistFile_iface
);
77 static void TaskDestructor(TaskImpl
*This
)
81 IExecAction_Release(This
->action
);
82 ITaskDefinition_Release(This
->task
);
83 HeapFree(GetProcessHeap(), 0, This
->task_name
);
84 HeapFree(GetProcessHeap(), 0, This
->accountName
);
85 HeapFree(GetProcessHeap(), 0, This
);
86 InterlockedDecrement(&dll_ref
);
89 static HRESULT WINAPI
MSTASK_ITask_QueryInterface(
94 TaskImpl
* This
= impl_from_ITask(iface
);
96 TRACE("IID: %s\n", debugstr_guid(riid
));
97 if (ppvObject
== NULL
)
100 if (IsEqualGUID(riid
, &IID_IUnknown
) ||
101 IsEqualGUID(riid
, &IID_ITask
))
103 *ppvObject
= &This
->ITask_iface
;
107 else if (IsEqualGUID(riid
, &IID_IPersistFile
))
109 *ppvObject
= &This
->IPersistFile_iface
;
114 WARN("Unknown interface: %s\n", debugstr_guid(riid
));
116 return E_NOINTERFACE
;
119 static ULONG WINAPI
MSTASK_ITask_AddRef(
122 TaskImpl
*This
= impl_from_ITask(iface
);
125 ref
= InterlockedIncrement(&This
->ref
);
129 static ULONG WINAPI
MSTASK_ITask_Release(
132 TaskImpl
* This
= impl_from_ITask(iface
);
135 ref
= InterlockedDecrement(&This
->ref
);
137 TaskDestructor(This
);
141 static HRESULT WINAPI
MSTASK_ITask_CreateTrigger(
144 ITaskTrigger
**ppTrigger
)
146 TRACE("(%p, %p, %p)\n", iface
, piNewTrigger
, ppTrigger
);
147 return TaskTriggerConstructor((LPVOID
*)ppTrigger
);
150 static HRESULT WINAPI
MSTASK_ITask_DeleteTrigger(
154 FIXME("(%p, %d): stub\n", iface
, iTrigger
);
158 static HRESULT WINAPI
MSTASK_ITask_GetTriggerCount(
162 FIXME("(%p, %p): stub\n", iface
, plCount
);
166 static HRESULT WINAPI
MSTASK_ITask_GetTrigger(
169 ITaskTrigger
**ppTrigger
)
171 FIXME("(%p, %d, %p): stub\n", iface
, iTrigger
, ppTrigger
);
175 static HRESULT WINAPI
MSTASK_ITask_GetTriggerString(
178 LPWSTR
*ppwszTrigger
)
180 FIXME("(%p, %d, %p): stub\n", iface
, iTrigger
, ppwszTrigger
);
184 static HRESULT WINAPI
MSTASK_ITask_GetRunTimes(
186 const LPSYSTEMTIME pstBegin
,
187 const LPSYSTEMTIME pstEnd
,
189 LPSYSTEMTIME
*rgstTaskTimes
)
191 FIXME("(%p, %p, %p, %p, %p): stub\n", iface
, pstBegin
, pstEnd
, pCount
,
196 static HRESULT WINAPI
MSTASK_ITask_GetNextRunTime(
198 SYSTEMTIME
*pstNextRun
)
200 FIXME("(%p, %p): stub\n", iface
, pstNextRun
);
204 static HRESULT WINAPI
MSTASK_ITask_SetIdleWait(
207 WORD wDeadlineMinutes
)
209 FIXME("(%p, %d, %d): stub\n", iface
, wIdleMinutes
, wDeadlineMinutes
);
213 static HRESULT WINAPI
MSTASK_ITask_GetIdleWait(ITask
*iface
, WORD
*idle_minutes
, WORD
*deadline_minutes
)
215 TaskImpl
*This
= impl_from_ITask(iface
);
217 TRACE("(%p, %p, %p): stub\n", iface
, idle_minutes
, deadline_minutes
);
219 *idle_minutes
= This
->idle_minutes
;
220 *deadline_minutes
= This
->deadline_minutes
;
224 static HRESULT WINAPI
MSTASK_ITask_Run(
227 FIXME("(%p): stub\n", iface
);
231 static HRESULT WINAPI
MSTASK_ITask_Terminate(
234 FIXME("(%p): stub\n", iface
);
238 static HRESULT WINAPI
MSTASK_ITask_EditWorkItem(
243 FIXME("(%p, %p, %d): stub\n", iface
, hParent
, dwReserved
);
247 static HRESULT WINAPI
MSTASK_ITask_GetMostRecentRunTime(ITask
*iface
, SYSTEMTIME
*st
)
249 FIXME("(%p, %p): stub\n", iface
, st
);
251 memset(st
, 0, sizeof(*st
));
252 return SCHED_S_TASK_HAS_NOT_RUN
;
255 static HRESULT WINAPI
MSTASK_ITask_GetStatus(ITask
*iface
, HRESULT
*status
)
257 TaskImpl
*This
= impl_from_ITask(iface
);
259 TRACE("(%p, %p)\n", iface
, status
);
261 *status
= This
->status
;
265 static HRESULT WINAPI
MSTASK_ITask_GetExitCode(ITask
*iface
, DWORD
*exit_code
)
267 FIXME("(%p, %p): stub\n", iface
, exit_code
);
270 return SCHED_S_TASK_HAS_NOT_RUN
;
273 static HRESULT WINAPI
MSTASK_ITask_SetComment(ITask
*iface
, LPCWSTR comment
)
275 TaskImpl
*This
= impl_from_ITask(iface
);
276 IRegistrationInfo
*info
;
279 TRACE("(%p, %s)\n", iface
, debugstr_w(comment
));
281 if (!comment
|| !comment
[0])
284 hr
= ITaskDefinition_get_RegistrationInfo(This
->task
, &info
);
287 hr
= IRegistrationInfo_put_Description(info
, (BSTR
)comment
);
288 IRegistrationInfo_Release(info
);
293 static HRESULT WINAPI
MSTASK_ITask_GetComment(ITask
*iface
, LPWSTR
*comment
)
295 TaskImpl
*This
= impl_from_ITask(iface
);
296 IRegistrationInfo
*info
;
301 TRACE("(%p, %p)\n", iface
, comment
);
303 hr
= ITaskDefinition_get_RegistrationInfo(This
->task
, &info
);
304 if (hr
!= S_OK
) return hr
;
306 hr
= IRegistrationInfo_get_Description(info
, &description
);
309 len
= description
? lstrlenW(description
) + 1 : 1;
310 *comment
= CoTaskMemAlloc(len
* sizeof(WCHAR
));
316 lstrcpyW(*comment
, description
);
322 SysFreeString(description
);
325 IRegistrationInfo_Release(info
);
329 static HRESULT WINAPI
MSTASK_ITask_SetCreator(ITask
*iface
, LPCWSTR creator
)
331 TaskImpl
*This
= impl_from_ITask(iface
);
332 IRegistrationInfo
*info
;
335 TRACE("(%p, %s)\n", iface
, debugstr_w(creator
));
337 if (!creator
|| !creator
[0])
340 hr
= ITaskDefinition_get_RegistrationInfo(This
->task
, &info
);
343 hr
= IRegistrationInfo_put_Author(info
, (BSTR
)creator
);
344 IRegistrationInfo_Release(info
);
349 static HRESULT WINAPI
MSTASK_ITask_GetCreator(ITask
*iface
, LPWSTR
*creator
)
351 TaskImpl
*This
= impl_from_ITask(iface
);
352 IRegistrationInfo
*info
;
357 TRACE("(%p, %p)\n", iface
, creator
);
359 hr
= ITaskDefinition_get_RegistrationInfo(This
->task
, &info
);
360 if (hr
!= S_OK
) return hr
;
362 hr
= IRegistrationInfo_get_Author(info
, &author
);
365 len
= author
? lstrlenW(author
) + 1 : 1;
366 *creator
= CoTaskMemAlloc(len
* sizeof(WCHAR
));
372 lstrcpyW(*creator
, author
);
378 SysFreeString(author
);
381 IRegistrationInfo_Release(info
);
385 static HRESULT WINAPI
MSTASK_ITask_SetWorkItemData(
390 FIXME("(%p, %d, %p): stub\n", iface
, cBytes
, rgbData
);
394 static HRESULT WINAPI
MSTASK_ITask_GetWorkItemData(
399 FIXME("(%p, %p, %p): stub\n", iface
, pcBytes
, ppBytes
);
403 static HRESULT WINAPI
MSTASK_ITask_SetErrorRetryCount(
407 FIXME("(%p, %d): stub\n", iface
, wRetryCount
);
411 static HRESULT WINAPI
MSTASK_ITask_GetErrorRetryCount(ITask
*iface
, WORD
*count
)
413 TRACE("(%p, %p)\n", iface
, count
);
417 static HRESULT WINAPI
MSTASK_ITask_SetErrorRetryInterval(
421 FIXME("(%p, %d): stub\n", iface
, wRetryInterval
);
425 static HRESULT WINAPI
MSTASK_ITask_GetErrorRetryInterval(ITask
*iface
, WORD
*interval
)
427 TRACE("(%p, %p)\n", iface
, interval
);
431 static HRESULT WINAPI
MSTASK_ITask_SetFlags(
435 FIXME("(%p, 0x%08x): stub\n", iface
, dwFlags
);
439 static HRESULT WINAPI
MSTASK_ITask_GetFlags(ITask
*iface
, DWORD
*flags
)
441 FIXME("(%p, %p): stub\n", iface
, flags
);
446 static HRESULT WINAPI
MSTASK_ITask_SetAccountInformation(
448 LPCWSTR pwszAccountName
,
449 LPCWSTR pwszPassword
)
452 TaskImpl
*This
= impl_from_ITask(iface
);
453 LPWSTR tmp_account_name
;
455 TRACE("(%p, %s, %s): partial stub\n", iface
, debugstr_w(pwszAccountName
),
456 debugstr_w(pwszPassword
));
459 FIXME("Partial stub ignores passwords\n");
461 n
= (lstrlenW(pwszAccountName
) + 1);
462 tmp_account_name
= HeapAlloc(GetProcessHeap(), 0, n
* sizeof(WCHAR
));
463 if (!tmp_account_name
)
464 return E_OUTOFMEMORY
;
465 lstrcpyW(tmp_account_name
, pwszAccountName
);
466 HeapFree(GetProcessHeap(), 0, This
->accountName
);
467 This
->accountName
= tmp_account_name
;
471 static HRESULT WINAPI
MSTASK_ITask_GetAccountInformation(
473 LPWSTR
*ppwszAccountName
)
476 TaskImpl
*This
= impl_from_ITask(iface
);
478 TRACE("(%p, %p): partial stub\n", iface
, ppwszAccountName
);
480 /* This implements the WinXP behavior when accountName has not yet
481 * set. Win2K behaves differently, returning SCHED_E_CANNOT_OPEN_TASK */
482 if (!This
->accountName
)
483 return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND
);
485 n
= (lstrlenW(This
->accountName
) + 1);
486 *ppwszAccountName
= CoTaskMemAlloc(n
* sizeof(WCHAR
));
487 if (!*ppwszAccountName
)
488 return E_OUTOFMEMORY
;
489 lstrcpyW(*ppwszAccountName
, This
->accountName
);
493 static HRESULT WINAPI
MSTASK_ITask_SetApplicationName(ITask
*iface
, LPCWSTR appname
)
495 TaskImpl
*This
= impl_from_ITask(iface
);
498 TRACE("(%p, %s)\n", iface
, debugstr_w(appname
));
500 /* Empty application name */
501 if (!appname
|| !appname
[0])
502 return IExecAction_put_Path(This
->action
, NULL
);
504 /* Attempt to set pwszApplicationName to a path resolved application name */
505 len
= SearchPathW(NULL
, appname
, NULL
, 0, NULL
, NULL
);
511 tmp_name
= HeapAlloc(GetProcessHeap(), 0, len
* sizeof(WCHAR
));
513 return E_OUTOFMEMORY
;
514 len
= SearchPathW(NULL
, appname
, NULL
, len
, tmp_name
, NULL
);
516 hr
= IExecAction_put_Path(This
->action
, tmp_name
);
518 hr
= HRESULT_FROM_WIN32(GetLastError());
520 HeapFree(GetProcessHeap(), 0, tmp_name
);
524 /* If unable to path resolve name, simply set to appname */
525 return IExecAction_put_Path(This
->action
, (BSTR
)appname
);
528 static HRESULT WINAPI
MSTASK_ITask_GetApplicationName(ITask
*iface
, LPWSTR
*appname
)
530 TaskImpl
*This
= impl_from_ITask(iface
);
535 TRACE("(%p, %p)\n", iface
, appname
);
537 hr
= IExecAction_get_Path(This
->action
, &path
);
538 if (hr
!= S_OK
) return hr
;
540 len
= path
? lstrlenW(path
) + 1 : 1;
541 *appname
= CoTaskMemAlloc(len
* sizeof(WCHAR
));
547 lstrcpyW(*appname
, path
);
557 static HRESULT WINAPI
MSTASK_ITask_SetParameters(ITask
*iface
, LPCWSTR params
)
559 TaskImpl
*This
= impl_from_ITask(iface
);
561 TRACE("(%p, %s)\n", iface
, debugstr_w(params
));
563 /* Empty parameter list */
564 if (!params
|| !params
[0])
567 return IExecAction_put_Arguments(This
->action
, (BSTR
)params
);
570 static HRESULT WINAPI
MSTASK_ITask_GetParameters(ITask
*iface
, LPWSTR
*params
)
572 TaskImpl
*This
= impl_from_ITask(iface
);
577 TRACE("(%p, %p)\n", iface
, params
);
579 hr
= IExecAction_get_Arguments(This
->action
, &args
);
580 if (hr
!= S_OK
) return hr
;
582 len
= args
? lstrlenW(args
) + 1 : 1;
583 *params
= CoTaskMemAlloc(len
* sizeof(WCHAR
));
589 lstrcpyW(*params
, args
);
599 static HRESULT WINAPI
MSTASK_ITask_SetWorkingDirectory(ITask
* iface
, LPCWSTR workdir
)
601 TaskImpl
*This
= impl_from_ITask(iface
);
603 TRACE("(%p, %s)\n", iface
, debugstr_w(workdir
));
605 if (!workdir
|| !workdir
[0])
608 return IExecAction_put_WorkingDirectory(This
->action
, (BSTR
)workdir
);
611 static HRESULT WINAPI
MSTASK_ITask_GetWorkingDirectory(ITask
*iface
, LPWSTR
*workdir
)
613 TaskImpl
*This
= impl_from_ITask(iface
);
618 TRACE("(%p, %p)\n", iface
, workdir
);
620 hr
= IExecAction_get_WorkingDirectory(This
->action
, &dir
);
621 if (hr
!= S_OK
) return hr
;
623 len
= dir
? lstrlenW(dir
) + 1 : 1;
624 *workdir
= CoTaskMemAlloc(len
* sizeof(WCHAR
));
630 lstrcpyW(*workdir
, dir
);
640 static HRESULT WINAPI
MSTASK_ITask_SetPriority(
644 FIXME("(%p, 0x%08x): stub\n", iface
, dwPriority
);
648 static HRESULT WINAPI
MSTASK_ITask_GetPriority(ITask
*iface
, DWORD
*priority
)
650 TaskImpl
*This
= impl_from_ITask(iface
);
652 TRACE("(%p, %p)\n", iface
, priority
);
654 *priority
= This
->priority
;
658 static HRESULT WINAPI
MSTASK_ITask_SetTaskFlags(
662 FIXME("(%p, 0x%08x): stub\n", iface
, dwFlags
);
666 static HRESULT WINAPI
MSTASK_ITask_GetTaskFlags(ITask
*iface
, DWORD
*flags
)
668 FIXME("(%p, %p): stub\n", iface
, flags
);
673 static HRESULT WINAPI
MSTASK_ITask_SetMaxRunTime(
677 TaskImpl
*This
= impl_from_ITask(iface
);
679 TRACE("(%p, %d)\n", iface
, dwMaxRunTime
);
681 This
->maxRunTime
= dwMaxRunTime
;
685 static HRESULT WINAPI
MSTASK_ITask_GetMaxRunTime(
687 DWORD
*pdwMaxRunTime
)
689 TaskImpl
*This
= impl_from_ITask(iface
);
691 TRACE("(%p, %p)\n", iface
, pdwMaxRunTime
);
693 *pdwMaxRunTime
= This
->maxRunTime
;
697 static HRESULT WINAPI
MSTASK_IPersistFile_QueryInterface(
702 TaskImpl
*This
= impl_from_IPersistFile(iface
);
703 TRACE("(%p, %s, %p)\n", iface
, debugstr_guid(riid
), ppvObject
);
704 return ITask_QueryInterface(&This
->ITask_iface
, riid
, ppvObject
);
707 static ULONG WINAPI
MSTASK_IPersistFile_AddRef(
710 TaskImpl
*This
= impl_from_IPersistFile(iface
);
713 ref
= InterlockedIncrement(&This
->ref
);
717 static ULONG WINAPI
MSTASK_IPersistFile_Release(
720 TaskImpl
*This
= impl_from_IPersistFile(iface
);
723 ref
= InterlockedDecrement(&This
->ref
);
725 TaskDestructor(This
);
729 static HRESULT WINAPI
MSTASK_IPersistFile_GetClassID(IPersistFile
*iface
, CLSID
*clsid
)
731 TRACE("(%p, %p)\n", iface
, clsid
);
733 *clsid
= CLSID_CTask
;
737 static HRESULT WINAPI
MSTASK_IPersistFile_IsDirty(
740 FIXME("(%p): stub\n", iface
);
744 static HRESULT WINAPI
MSTASK_IPersistFile_Load(
746 LPCOLESTR pszFileName
,
749 FIXME("(%p, %p, 0x%08x): stub\n", iface
, pszFileName
, dwMode
);
753 static BOOL
write_signature(HANDLE hfile
)
757 USHORT SignatureVersion
;
758 USHORT ClientVersion
;
763 signature
.SignatureVersion
= 0x0001;
764 signature
.ClientVersion
= 0x0001;
765 memset(&signature
.md5
, 0, sizeof(signature
.md5
));
767 return WriteFile(hfile
, &signature
, sizeof(signature
), &size
, NULL
);
770 static BOOL
write_reserved_data(HANDLE hfile
)
776 } user
= { 8, { 0xff,0x0f,0x1d,0,0,0,0,0 } };
779 return WriteFile(hfile
, &user
, sizeof(user
), &size
, NULL
);
782 static BOOL
write_user_data(HANDLE hfile
, BYTE
*data
, WORD data_size
)
786 if (!WriteFile(hfile
, &data_size
, sizeof(data_size
), &size
, NULL
))
789 if (!data_size
) return TRUE
;
791 return WriteFile(hfile
, data
, data_size
, &size
, NULL
);
794 static HRESULT
write_triggers(ITask
*task
, HANDLE hfile
)
800 hr
= ITask_GetTriggerCount(task
, &count
);
801 if (hr
!= S_OK
) return hr
;
803 if (!WriteFile(hfile
, &count
, sizeof(count
), &size
, NULL
))
804 return HRESULT_FROM_WIN32(GetLastError());
806 for (i
= 0; i
< count
; i
++)
808 ITaskTrigger
*trigger
;
809 TASK_TRIGGER task_trigger
;
811 hr
= ITask_GetTrigger(task
, i
, &trigger
);
812 if (hr
!= S_OK
) return hr
;
814 hr
= ITaskTrigger_GetTrigger(trigger
, &task_trigger
);
815 ITaskTrigger_Release(trigger
);
816 if (hr
!= S_OK
) return hr
;
818 if (!WriteFile(hfile
, &task_trigger
, sizeof(task_trigger
), &size
, NULL
))
819 return HRESULT_FROM_WIN32(GetLastError());
825 static BOOL
write_unicode_string(HANDLE hfile
, const WCHAR
*str
)
830 count
= str
? (lstrlenW(str
) + 1) : 0;
831 if (!WriteFile(hfile
, &count
, sizeof(count
), &size
, NULL
))
834 if (!str
) return TRUE
;
836 count
*= sizeof(WCHAR
);
837 return WriteFile(hfile
, str
, count
, &size
, NULL
);
840 static HRESULT WINAPI
MSTASK_IPersistFile_Save(IPersistFile
*iface
, LPCOLESTR name
, BOOL remember
)
842 static const WCHAR tasksW
[] = { '\\','T','a','s','k','s','\\',0 };
843 static const WCHAR jobW
[] = { '.','j','o','b',0 };
844 static WCHAR authorW
[] = { 'W','i','n','e',0 };
845 static WCHAR commentW
[] = { 'C','r','e','a','t','e','d',' ','b','y',' ','W','i','n','e',0 };
847 WORD word
, user_data_size
= 0;
849 DWORD size
, ver
, disposition
;
850 TaskImpl
*This
= impl_from_IPersistFile(iface
);
851 ITask
*task
= &This
->ITask_iface
;
852 LPWSTR appname
= NULL
, params
= NULL
, workdir
= NULL
, creator
= NULL
, comment
= NULL
;
853 BYTE
*user_data
= NULL
;
854 WCHAR task_name
[MAX_PATH
];
857 TRACE("(%p, %s, %d)\n", iface
, debugstr_w(name
), remember
);
859 disposition
= name
? CREATE_NEW
: OPEN_ALWAYS
;
863 name
= This
->task_name
;
866 else if (strchrW(name
, '.'))
869 GetWindowsDirectoryW(task_name
, MAX_PATH
);
870 lstrcatW(task_name
, tasksW
);
871 lstrcatW(task_name
, name
);
872 lstrcatW(task_name
, jobW
);
874 ITask_GetComment(task
, &comment
);
875 if (!comment
) comment
= commentW
;
876 ITask_GetCreator(task
, &creator
);
877 if (!creator
) creator
= authorW
;
878 ITask_GetApplicationName(task
, &appname
);
879 ITask_GetParameters(task
, ¶ms
);
880 ITask_GetWorkingDirectory(task
, &workdir
);
881 ITask_GetWorkItemData(task
, &user_data_size
, &user_data
);
884 fixed
.product_version
= MAKEWORD(ver
>> 8, ver
);
885 fixed
.file_version
= 0x0001;
886 CoCreateGuid(&fixed
.uuid
);
887 fixed
.name_size_offset
= sizeof(fixed
) + sizeof(USHORT
); /* FIXDLEN_DATA + Instance Count */
888 fixed
.trigger_offset
= sizeof(fixed
) + sizeof(USHORT
); /* FIXDLEN_DATA + Instance Count */
889 fixed
.trigger_offset
+= sizeof(USHORT
); /* Application Name */
891 fixed
.trigger_offset
+= (lstrlenW(appname
) + 1) * sizeof(WCHAR
);
892 fixed
.trigger_offset
+= sizeof(USHORT
); /* Parameters */
894 fixed
.trigger_offset
+= (lstrlenW(params
) + 1) * sizeof(WCHAR
);
895 fixed
.trigger_offset
+= sizeof(USHORT
); /* Working Directory */
897 fixed
.trigger_offset
+= (lstrlenW(workdir
) + 1) * sizeof(WCHAR
);
898 fixed
.trigger_offset
+= sizeof(USHORT
); /* Author */
900 fixed
.trigger_offset
+= (lstrlenW(creator
) + 1) * sizeof(WCHAR
);
901 fixed
.trigger_offset
+= sizeof(USHORT
); /* Comment */
903 fixed
.trigger_offset
+= (lstrlenW(comment
) + 1) * sizeof(WCHAR
);
904 fixed
.trigger_offset
+= sizeof(USHORT
) + user_data_size
; /* User Data */
905 fixed
.trigger_offset
+= 10; /* Reserved Data */
907 fixed
.error_retry_count
= 0;
908 fixed
.error_retry_interval
= 0;
909 fixed
.idle_wait
= This
->idle_minutes
;
910 fixed
.idle_deadline
= This
->deadline_minutes
;
911 fixed
.priority
= This
->priority
;
912 fixed
.maximum_runtime
= This
->maxRunTime
;
914 fixed
.status
= SCHED_S_TASK_HAS_NOT_RUN
;
916 memset(&fixed
.last_runtime
, 0, sizeof(fixed
.last_runtime
));
918 hfile
= CreateFileW(task_name
, GENERIC_WRITE
, 0, NULL
, disposition
, 0, 0);
919 if (hfile
== INVALID_HANDLE_VALUE
)
920 return HRESULT_FROM_WIN32(GetLastError());
922 if (!WriteFile(hfile
, &fixed
, sizeof(fixed
), &size
, NULL
))
924 hr
= HRESULT_FROM_WIN32(GetLastError());
930 if (!WriteFile(hfile
, &word
, sizeof(word
), &size
, NULL
))
932 hr
= HRESULT_FROM_WIN32(GetLastError());
935 /* Application Name */
936 if (!write_unicode_string(hfile
, appname
))
938 hr
= HRESULT_FROM_WIN32(GetLastError());
942 if (!write_unicode_string(hfile
, params
))
944 hr
= HRESULT_FROM_WIN32(GetLastError());
947 /* Working Directory */
948 if (!write_unicode_string(hfile
, workdir
))
950 hr
= HRESULT_FROM_WIN32(GetLastError());
954 if (!write_unicode_string(hfile
, creator
))
956 hr
= HRESULT_FROM_WIN32(GetLastError());
960 if (!write_unicode_string(hfile
, comment
))
962 hr
= HRESULT_FROM_WIN32(GetLastError());
967 if (!write_user_data(hfile
, user_data
, user_data_size
))
969 hr
= HRESULT_FROM_WIN32(GetLastError());
974 if (!write_reserved_data(hfile
))
976 hr
= HRESULT_FROM_WIN32(GetLastError());
981 if (!write_triggers(hfile
, task
))
983 hr
= HRESULT_FROM_WIN32(GetLastError());
988 if (!write_signature(hfile
))
990 hr
= HRESULT_FROM_WIN32(GetLastError());
997 CoTaskMemFree(appname
);
998 CoTaskMemFree(params
);
999 CoTaskMemFree(workdir
);
1000 if (creator
!= authorW
)
1001 CoTaskMemFree(creator
);
1002 if (comment
!= commentW
)
1003 CoTaskMemFree(comment
);
1004 CoTaskMemFree(user_data
);
1011 HeapFree(GetProcessHeap(), 0, This
->task_name
);
1012 This
->task_name
= heap_strdupW(name
);
1017 static HRESULT WINAPI
MSTASK_IPersistFile_SaveCompleted(
1018 IPersistFile
* iface
,
1019 LPCOLESTR pszFileName
)
1021 FIXME("(%p, %p): stub\n", iface
, pszFileName
);
1025 static HRESULT WINAPI
MSTASK_IPersistFile_GetCurFile(
1026 IPersistFile
* iface
,
1027 LPOLESTR
*ppszFileName
)
1029 FIXME("(%p, %p): stub\n", iface
, ppszFileName
);
1033 static const ITaskVtbl MSTASK_ITaskVtbl
=
1035 MSTASK_ITask_QueryInterface
,
1036 MSTASK_ITask_AddRef
,
1037 MSTASK_ITask_Release
,
1038 MSTASK_ITask_CreateTrigger
,
1039 MSTASK_ITask_DeleteTrigger
,
1040 MSTASK_ITask_GetTriggerCount
,
1041 MSTASK_ITask_GetTrigger
,
1042 MSTASK_ITask_GetTriggerString
,
1043 MSTASK_ITask_GetRunTimes
,
1044 MSTASK_ITask_GetNextRunTime
,
1045 MSTASK_ITask_SetIdleWait
,
1046 MSTASK_ITask_GetIdleWait
,
1048 MSTASK_ITask_Terminate
,
1049 MSTASK_ITask_EditWorkItem
,
1050 MSTASK_ITask_GetMostRecentRunTime
,
1051 MSTASK_ITask_GetStatus
,
1052 MSTASK_ITask_GetExitCode
,
1053 MSTASK_ITask_SetComment
,
1054 MSTASK_ITask_GetComment
,
1055 MSTASK_ITask_SetCreator
,
1056 MSTASK_ITask_GetCreator
,
1057 MSTASK_ITask_SetWorkItemData
,
1058 MSTASK_ITask_GetWorkItemData
,
1059 MSTASK_ITask_SetErrorRetryCount
,
1060 MSTASK_ITask_GetErrorRetryCount
,
1061 MSTASK_ITask_SetErrorRetryInterval
,
1062 MSTASK_ITask_GetErrorRetryInterval
,
1063 MSTASK_ITask_SetFlags
,
1064 MSTASK_ITask_GetFlags
,
1065 MSTASK_ITask_SetAccountInformation
,
1066 MSTASK_ITask_GetAccountInformation
,
1067 MSTASK_ITask_SetApplicationName
,
1068 MSTASK_ITask_GetApplicationName
,
1069 MSTASK_ITask_SetParameters
,
1070 MSTASK_ITask_GetParameters
,
1071 MSTASK_ITask_SetWorkingDirectory
,
1072 MSTASK_ITask_GetWorkingDirectory
,
1073 MSTASK_ITask_SetPriority
,
1074 MSTASK_ITask_GetPriority
,
1075 MSTASK_ITask_SetTaskFlags
,
1076 MSTASK_ITask_GetTaskFlags
,
1077 MSTASK_ITask_SetMaxRunTime
,
1078 MSTASK_ITask_GetMaxRunTime
1081 static const IPersistFileVtbl MSTASK_IPersistFileVtbl
=
1083 MSTASK_IPersistFile_QueryInterface
,
1084 MSTASK_IPersistFile_AddRef
,
1085 MSTASK_IPersistFile_Release
,
1086 MSTASK_IPersistFile_GetClassID
,
1087 MSTASK_IPersistFile_IsDirty
,
1088 MSTASK_IPersistFile_Load
,
1089 MSTASK_IPersistFile_Save
,
1090 MSTASK_IPersistFile_SaveCompleted
,
1091 MSTASK_IPersistFile_GetCurFile
1094 HRESULT
TaskConstructor(ITaskService
*service
, const WCHAR
*task_name
, ITask
**task
)
1097 ITaskDefinition
*taskdef
;
1098 IActionCollection
*actions
;
1101 TRACE("(%s, %p)\n", debugstr_w(task_name
), task
);
1103 hr
= ITaskService_NewTask(service
, 0, &taskdef
);
1104 if (hr
!= S_OK
) return hr
;
1106 This
= HeapAlloc(GetProcessHeap(), 0, sizeof(*This
));
1109 ITaskDefinition_Release(taskdef
);
1110 return E_OUTOFMEMORY
;
1113 This
->ITask_iface
.lpVtbl
= &MSTASK_ITaskVtbl
;
1114 This
->IPersistFile_iface
.lpVtbl
= &MSTASK_IPersistFileVtbl
;
1116 This
->task
= taskdef
;
1117 This
->task_name
= heap_strdupW(task_name
);
1118 This
->status
= SCHED_S_TASK_NOT_SCHEDULED
;
1119 This
->idle_minutes
= 10;
1120 This
->deadline_minutes
= 60;
1121 This
->priority
= NORMAL_PRIORITY_CLASS
;
1122 This
->accountName
= NULL
;
1124 /* Default time is 3 days = 259200000 ms */
1125 This
->maxRunTime
= 259200000;
1127 hr
= ITaskDefinition_get_Actions(This
->task
, &actions
);
1130 hr
= IActionCollection_Create(actions
, TASK_ACTION_EXEC
, (IAction
**)&This
->action
);
1131 IActionCollection_Release(actions
);
1134 *task
= &This
->ITask_iface
;
1135 InterlockedIncrement(&dll_ref
);
1140 ITaskDefinition_Release(This
->task
);
1141 ITask_Release(&This
->ITask_iface
);