xref: /reactos/dll/win32/mstask/task.c (revision c2c66aff)
1 /*
2  * Copyright (C) 2008 Google (Roy Shea)
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Lesser General Public
6  * License as published by the Free Software Foundation; either
7  * version 2.1 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with this library; if not, write to the Free Software
16  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
17  */
18 
19 #include "mstask_private.h"
20 
21 typedef struct
22 {
23     ITask ITask_iface;
24     IPersistFile IPersistFile_iface;
25     LONG ref;
26     LPWSTR taskName;
27     LPWSTR applicationName;
28     LPWSTR parameters;
29     LPWSTR comment;
30     DWORD maxRunTime;
31     LPWSTR accountName;
32 } TaskImpl;
33 
34 static inline TaskImpl *impl_from_ITask(ITask *iface)
35 {
36     return CONTAINING_RECORD(iface, TaskImpl, ITask_iface);
37 }
38 
39 static inline TaskImpl *impl_from_IPersistFile( IPersistFile *iface )
40 {
41     return CONTAINING_RECORD(iface, TaskImpl, IPersistFile_iface);
42 }
43 
44 static void TaskDestructor(TaskImpl *This)
45 {
46     TRACE("%p\n", This);
47     HeapFree(GetProcessHeap(), 0, This->accountName);
48     HeapFree(GetProcessHeap(), 0, This->comment);
49     HeapFree(GetProcessHeap(), 0, This->parameters);
50     HeapFree(GetProcessHeap(), 0, This->taskName);
51     HeapFree(GetProcessHeap(), 0, This);
52     InterlockedDecrement(&dll_ref);
53 }
54 
55 static HRESULT WINAPI MSTASK_ITask_QueryInterface(
56         ITask* iface,
57         REFIID riid,
58         void **ppvObject)
59 {
60     TaskImpl * This = impl_from_ITask(iface);
61 
62     TRACE("IID: %s\n", debugstr_guid(riid));
63     if (ppvObject == NULL)
64         return E_POINTER;
65 
66     if (IsEqualGUID(riid, &IID_IUnknown) ||
67             IsEqualGUID(riid, &IID_ITask))
68     {
69         *ppvObject = &This->ITask_iface;
70         ITask_AddRef(iface);
71         return S_OK;
72     }
73     else if (IsEqualGUID(riid, &IID_IPersistFile))
74     {
75         *ppvObject = &This->IPersistFile_iface;
76         ITask_AddRef(iface);
77         return S_OK;
78     }
79 
80     WARN("Unknown interface: %s\n", debugstr_guid(riid));
81     *ppvObject = NULL;
82     return E_NOINTERFACE;
83 }
84 
85 static ULONG WINAPI MSTASK_ITask_AddRef(
86         ITask* iface)
87 {
88     TaskImpl *This = impl_from_ITask(iface);
89     ULONG ref;
90     TRACE("\n");
91     ref = InterlockedIncrement(&This->ref);
92     return ref;
93 }
94 
95 static ULONG WINAPI MSTASK_ITask_Release(
96         ITask* iface)
97 {
98     TaskImpl * This = impl_from_ITask(iface);
99     ULONG ref;
100     TRACE("\n");
101     ref = InterlockedDecrement(&This->ref);
102     if (ref == 0)
103         TaskDestructor(This);
104     return ref;
105 }
106 
107 static HRESULT WINAPI MSTASK_ITask_CreateTrigger(
108         ITask* iface,
109         WORD *piNewTrigger,
110         ITaskTrigger **ppTrigger)
111 {
112     TRACE("(%p, %p, %p)\n", iface, piNewTrigger, ppTrigger);
113     return TaskTriggerConstructor((LPVOID *)ppTrigger);
114 }
115 
116 static HRESULT WINAPI MSTASK_ITask_DeleteTrigger(
117         ITask* iface,
118         WORD iTrigger)
119 {
120     FIXME("(%p, %d): stub\n", iface, iTrigger);
121     return E_NOTIMPL;
122 }
123 
124 static HRESULT WINAPI MSTASK_ITask_GetTriggerCount(
125         ITask* iface,
126         WORD *plCount)
127 {
128     FIXME("(%p, %p): stub\n", iface, plCount);
129     return E_NOTIMPL;
130 }
131 
132 static HRESULT WINAPI MSTASK_ITask_GetTrigger(
133         ITask* iface,
134         WORD iTrigger,
135         ITaskTrigger **ppTrigger)
136 {
137     FIXME("(%p, %d, %p): stub\n", iface, iTrigger, ppTrigger);
138     return E_NOTIMPL;
139 }
140 
141 static HRESULT WINAPI MSTASK_ITask_GetTriggerString(
142         ITask* iface,
143         WORD iTrigger,
144         LPWSTR *ppwszTrigger)
145 {
146     FIXME("(%p, %d, %p): stub\n", iface, iTrigger, ppwszTrigger);
147     return E_NOTIMPL;
148 }
149 
150 static HRESULT WINAPI MSTASK_ITask_GetRunTimes(
151         ITask* iface,
152         const LPSYSTEMTIME pstBegin,
153         const LPSYSTEMTIME pstEnd,
154         WORD *pCount,
155         LPSYSTEMTIME *rgstTaskTimes)
156 {
157     FIXME("(%p, %p, %p, %p, %p): stub\n", iface, pstBegin, pstEnd, pCount,
158             rgstTaskTimes);
159     return E_NOTIMPL;
160 }
161 
162 static HRESULT WINAPI MSTASK_ITask_GetNextRunTime(
163         ITask* iface,
164         SYSTEMTIME *pstNextRun)
165 {
166     FIXME("(%p, %p): stub\n", iface, pstNextRun);
167     return E_NOTIMPL;
168 }
169 
170 static HRESULT WINAPI MSTASK_ITask_SetIdleWait(
171         ITask* iface,
172         WORD wIdleMinutes,
173         WORD wDeadlineMinutes)
174 {
175     FIXME("(%p, %d, %d): stub\n", iface, wIdleMinutes, wDeadlineMinutes);
176     return E_NOTIMPL;
177 }
178 
179 static HRESULT WINAPI MSTASK_ITask_GetIdleWait(
180         ITask* iface,
181         WORD *pwIdleMinutes,
182         WORD *pwDeadlineMinutes)
183 {
184     FIXME("(%p, %p, %p): stub\n", iface, pwIdleMinutes, pwDeadlineMinutes);
185     return E_NOTIMPL;
186 }
187 
188 static HRESULT WINAPI MSTASK_ITask_Run(
189         ITask* iface)
190 {
191     FIXME("(%p): stub\n", iface);
192     return E_NOTIMPL;
193 }
194 
195 static HRESULT WINAPI MSTASK_ITask_Terminate(
196         ITask* iface)
197 {
198     FIXME("(%p): stub\n", iface);
199     return E_NOTIMPL;
200 }
201 
202 static HRESULT WINAPI MSTASK_ITask_EditWorkItem(
203         ITask* iface,
204         HWND hParent,
205         DWORD dwReserved)
206 {
207     FIXME("(%p, %p, %d): stub\n", iface, hParent, dwReserved);
208     return E_NOTIMPL;
209 }
210 
211 static HRESULT WINAPI MSTASK_ITask_GetMostRecentRunTime(
212         ITask* iface,
213         SYSTEMTIME *pstLastRun)
214 {
215     FIXME("(%p, %p): stub\n", iface, pstLastRun);
216     return E_NOTIMPL;
217 }
218 
219 static HRESULT WINAPI MSTASK_ITask_GetStatus(
220         ITask* iface,
221         HRESULT *phrStatus)
222 {
223     FIXME("(%p, %p): stub\n", iface, phrStatus);
224     return E_NOTIMPL;
225 }
226 
227 static HRESULT WINAPI MSTASK_ITask_GetExitCode(
228         ITask* iface,
229         DWORD *pdwExitCode)
230 {
231     FIXME("(%p, %p): stub\n", iface, pdwExitCode);
232     return E_NOTIMPL;
233 }
234 
235 static HRESULT WINAPI MSTASK_ITask_SetComment(
236         ITask* iface,
237         LPCWSTR pwszComment)
238 {
239     DWORD n;
240     TaskImpl *This = impl_from_ITask(iface);
241     LPWSTR tmp_comment;
242 
243     TRACE("(%p, %s)\n", iface, debugstr_w(pwszComment));
244 
245     /* Empty comment */
246     if (pwszComment[0] == 0)
247     {
248         HeapFree(GetProcessHeap(), 0, This->comment);
249         This->comment = NULL;
250         return S_OK;
251     }
252 
253     /* Set to pwszComment */
254     n = (lstrlenW(pwszComment) + 1);
255     tmp_comment = HeapAlloc(GetProcessHeap(), 0, n * sizeof(WCHAR));
256     if (!tmp_comment)
257         return E_OUTOFMEMORY;
258     lstrcpyW(tmp_comment, pwszComment);
259     HeapFree(GetProcessHeap(), 0, This->comment);
260     This->comment = tmp_comment;
261 
262     return S_OK;
263 }
264 
265 static HRESULT WINAPI MSTASK_ITask_GetComment(
266         ITask* iface,
267         LPWSTR *ppwszComment)
268 {
269     DWORD n;
270     TaskImpl *This = impl_from_ITask(iface);
271 
272     TRACE("(%p, %p)\n", iface, ppwszComment);
273 
274     n = This->comment ? lstrlenW(This->comment) + 1 : 1;
275     *ppwszComment = CoTaskMemAlloc(n * sizeof(WCHAR));
276     if (!*ppwszComment)
277         return E_OUTOFMEMORY;
278 
279     if (!This->comment)
280         *ppwszComment[0] = 0;
281     else
282         lstrcpyW(*ppwszComment, This->comment);
283 
284     return S_OK;
285 }
286 
287 static HRESULT WINAPI MSTASK_ITask_SetCreator(
288         ITask* iface,
289         LPCWSTR pwszCreator)
290 {
291     FIXME("(%p, %p): stub\n", iface, pwszCreator);
292     return E_NOTIMPL;
293 }
294 
295 static HRESULT WINAPI MSTASK_ITask_GetCreator(
296         ITask* iface,
297         LPWSTR *ppwszCreator)
298 {
299     FIXME("(%p, %p): stub\n", iface, ppwszCreator);
300     return E_NOTIMPL;
301 }
302 
303 static HRESULT WINAPI MSTASK_ITask_SetWorkItemData(
304         ITask* iface,
305         WORD cBytes,
306         BYTE rgbData[])
307 {
308     FIXME("(%p, %d, %p): stub\n", iface, cBytes, rgbData);
309     return E_NOTIMPL;
310 }
311 
312 static HRESULT WINAPI MSTASK_ITask_GetWorkItemData(
313         ITask* iface,
314         WORD *pcBytes,
315         BYTE **ppBytes)
316 {
317     FIXME("(%p, %p, %p): stub\n", iface, pcBytes, ppBytes);
318     return E_NOTIMPL;
319 }
320 
321 static HRESULT WINAPI MSTASK_ITask_SetErrorRetryCount(
322         ITask* iface,
323         WORD wRetryCount)
324 {
325     FIXME("(%p, %d): stub\n", iface, wRetryCount);
326     return E_NOTIMPL;
327 }
328 
329 static HRESULT WINAPI MSTASK_ITask_GetErrorRetryCount(
330         ITask* iface,
331         WORD *pwRetryCount)
332 {
333     FIXME("(%p, %p): stub\n", iface, pwRetryCount);
334     return E_NOTIMPL;
335 }
336 
337 static HRESULT WINAPI MSTASK_ITask_SetErrorRetryInterval(
338         ITask* iface,
339         WORD wRetryInterval)
340 {
341     FIXME("(%p, %d): stub\n", iface, wRetryInterval);
342     return E_NOTIMPL;
343 }
344 
345 static HRESULT WINAPI MSTASK_ITask_GetErrorRetryInterval(
346         ITask* iface,
347         WORD *pwRetryInterval)
348 {
349     FIXME("(%p, %p): stub\n", iface, pwRetryInterval);
350     return E_NOTIMPL;
351 }
352 
353 static HRESULT WINAPI MSTASK_ITask_SetFlags(
354         ITask* iface,
355         DWORD dwFlags)
356 {
357     FIXME("(%p, 0x%08x): stub\n", iface, dwFlags);
358     return E_NOTIMPL;
359 }
360 
361 static HRESULT WINAPI MSTASK_ITask_GetFlags(
362         ITask* iface,
363         DWORD *pdwFlags)
364 {
365     FIXME("(%p, %p): stub\n", iface, pdwFlags);
366     return E_NOTIMPL;
367 }
368 
369 static HRESULT WINAPI MSTASK_ITask_SetAccountInformation(
370         ITask* iface,
371         LPCWSTR pwszAccountName,
372         LPCWSTR pwszPassword)
373 {
374     DWORD n;
375     TaskImpl *This = impl_from_ITask(iface);
376     LPWSTR tmp_account_name;
377 
378     TRACE("(%p, %s, %s): partial stub\n", iface, debugstr_w(pwszAccountName),
379             debugstr_w(pwszPassword));
380 
381     if (pwszPassword)
382         FIXME("Partial stub ignores passwords\n");
383 
384     n = (lstrlenW(pwszAccountName) + 1);
385     tmp_account_name = HeapAlloc(GetProcessHeap(), 0, n * sizeof(WCHAR));
386     if (!tmp_account_name)
387         return E_OUTOFMEMORY;
388     lstrcpyW(tmp_account_name, pwszAccountName);
389     HeapFree(GetProcessHeap(), 0, This->accountName);
390     This->accountName = tmp_account_name;
391     return S_OK;
392 }
393 
394 static HRESULT WINAPI MSTASK_ITask_GetAccountInformation(
395         ITask* iface,
396         LPWSTR *ppwszAccountName)
397 {
398     DWORD n;
399     TaskImpl *This = impl_from_ITask(iface);
400 
401     TRACE("(%p, %p): partial stub\n", iface, ppwszAccountName);
402 
403     /* This implements the WinXP behavior when accountName has not yet
404      * set.  Win2K behaves differently, returning SCHED_E_CANNOT_OPEN_TASK */
405     if (!This->accountName)
406         return HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND);
407 
408     n = (lstrlenW(This->accountName) + 1);
409     *ppwszAccountName = CoTaskMemAlloc(n * sizeof(WCHAR));
410     if (!*ppwszAccountName)
411         return E_OUTOFMEMORY;
412     lstrcpyW(*ppwszAccountName, This->accountName);
413     return S_OK;
414 }
415 
416 static HRESULT WINAPI MSTASK_ITask_SetApplicationName(
417         ITask* iface,
418         LPCWSTR pwszApplicationName)
419 {
420     DWORD n;
421     TaskImpl *This = impl_from_ITask(iface);
422     LPWSTR tmp_name;
423 
424     TRACE("(%p, %s)\n", iface, debugstr_w(pwszApplicationName));
425 
426     /* Empty application name */
427     if (pwszApplicationName[0] == 0)
428     {
429         HeapFree(GetProcessHeap(), 0, This->applicationName);
430         This->applicationName = NULL;
431         return S_OK;
432     }
433 
434     /* Attempt to set pwszApplicationName to a path resolved application name */
435     n = SearchPathW(NULL, pwszApplicationName, NULL, 0, NULL, NULL);
436     if (n)
437     {
438         tmp_name = HeapAlloc(GetProcessHeap(), 0, n * sizeof(WCHAR));
439         if (!tmp_name)
440             return E_OUTOFMEMORY;
441         n = SearchPathW(NULL, pwszApplicationName, NULL, n, tmp_name, NULL);
442         if (n)
443         {
444             HeapFree(GetProcessHeap(), 0, This->applicationName);
445             This->applicationName = tmp_name;
446             return S_OK;
447         }
448         else
449             HeapFree(GetProcessHeap(), 0, tmp_name);
450     }
451 
452     /* If unable to path resolve name, simply set to pwszApplicationName */
453     n = (lstrlenW(pwszApplicationName) + 1);
454     tmp_name = HeapAlloc(GetProcessHeap(), 0, n * sizeof(WCHAR));
455     if (!tmp_name)
456         return E_OUTOFMEMORY;
457     lstrcpyW(tmp_name, pwszApplicationName);
458     HeapFree(GetProcessHeap(), 0, This->applicationName);
459     This->applicationName = tmp_name;
460     return S_OK;
461 }
462 
463 static HRESULT WINAPI MSTASK_ITask_GetApplicationName(
464         ITask* iface,
465         LPWSTR *ppwszApplicationName)
466 {
467     DWORD n;
468     TaskImpl *This = impl_from_ITask(iface);
469 
470     TRACE("(%p, %p)\n", iface, ppwszApplicationName);
471 
472     n = This->applicationName ? lstrlenW(This->applicationName) + 1 : 1;
473     *ppwszApplicationName = CoTaskMemAlloc(n * sizeof(WCHAR));
474     if (!*ppwszApplicationName)
475         return E_OUTOFMEMORY;
476 
477     if (!This->applicationName)
478         *ppwszApplicationName[0] = 0;
479     else
480         lstrcpyW(*ppwszApplicationName, This->applicationName);
481 
482     return S_OK;
483 }
484 
485 static HRESULT WINAPI MSTASK_ITask_SetParameters(
486         ITask* iface,
487         LPCWSTR pwszParameters)
488 {
489     DWORD n;
490     TaskImpl *This = impl_from_ITask(iface);
491     LPWSTR tmp_parameters;
492 
493     TRACE("(%p, %s)\n", iface, debugstr_w(pwszParameters));
494 
495     /* Empty parameter list */
496     if (pwszParameters[0] == 0)
497     {
498         HeapFree(GetProcessHeap(), 0, This->parameters);
499         This->parameters = NULL;
500         return S_OK;
501     }
502 
503     /* Set to pwszParameters */
504     n = (lstrlenW(pwszParameters) + 1);
505     tmp_parameters = HeapAlloc(GetProcessHeap(), 0, n * sizeof(WCHAR));
506     if (!tmp_parameters)
507         return E_OUTOFMEMORY;
508     lstrcpyW(tmp_parameters, pwszParameters);
509     HeapFree(GetProcessHeap(), 0, This->parameters);
510     This->parameters = tmp_parameters;
511     return S_OK;
512 }
513 
514 static HRESULT WINAPI MSTASK_ITask_GetParameters(
515         ITask* iface,
516         LPWSTR *ppwszParameters)
517 {
518     DWORD n;
519     TaskImpl *This = impl_from_ITask(iface);
520 
521     TRACE("(%p, %p)\n", iface, ppwszParameters);
522 
523     n = This->parameters ? lstrlenW(This->parameters) + 1 : 1;
524     *ppwszParameters = CoTaskMemAlloc(n * sizeof(WCHAR));
525     if (!*ppwszParameters)
526         return E_OUTOFMEMORY;
527 
528     if (!This->parameters)
529         *ppwszParameters[0] = 0;
530     else
531         lstrcpyW(*ppwszParameters, This->parameters);
532 
533     return S_OK;
534 }
535 
536 static HRESULT WINAPI MSTASK_ITask_SetWorkingDirectory(
537         ITask* iface,
538         LPCWSTR pwszWorkingDirectory)
539 {
540     FIXME("(%p, %s): stub\n", iface, debugstr_w(pwszWorkingDirectory));
541     return E_NOTIMPL;
542 }
543 
544 static HRESULT WINAPI MSTASK_ITask_GetWorkingDirectory(
545         ITask* iface,
546         LPWSTR *ppwszWorkingDirectory)
547 {
548     FIXME("(%p, %p): stub\n", iface, ppwszWorkingDirectory);
549     return E_NOTIMPL;
550 }
551 
552 static HRESULT WINAPI MSTASK_ITask_SetPriority(
553         ITask* iface,
554         DWORD dwPriority)
555 {
556     FIXME("(%p, 0x%08x): stub\n", iface, dwPriority);
557     return E_NOTIMPL;
558 }
559 
560 static HRESULT WINAPI MSTASK_ITask_GetPriority(
561         ITask* iface,
562         DWORD *pdwPriority)
563 {
564     FIXME("(%p, %p): stub\n", iface, pdwPriority);
565     return E_NOTIMPL;
566 }
567 
568 static HRESULT WINAPI MSTASK_ITask_SetTaskFlags(
569         ITask* iface,
570         DWORD dwFlags)
571 {
572     FIXME("(%p, 0x%08x): stub\n", iface, dwFlags);
573     return E_NOTIMPL;
574 }
575 
576 static HRESULT WINAPI MSTASK_ITask_GetTaskFlags(
577         ITask* iface,
578         DWORD *pdwFlags)
579 {
580     FIXME("(%p, %p): stub\n", iface, pdwFlags);
581     return E_NOTIMPL;
582 }
583 
584 static HRESULT WINAPI MSTASK_ITask_SetMaxRunTime(
585         ITask* iface,
586         DWORD dwMaxRunTime)
587 {
588     TaskImpl *This = impl_from_ITask(iface);
589 
590     TRACE("(%p, %d)\n", iface, dwMaxRunTime);
591 
592     This->maxRunTime = dwMaxRunTime;
593     return S_OK;
594 }
595 
596 static HRESULT WINAPI MSTASK_ITask_GetMaxRunTime(
597         ITask* iface,
598         DWORD *pdwMaxRunTime)
599 {
600     TaskImpl *This = impl_from_ITask(iface);
601 
602     TRACE("(%p, %p)\n", iface, pdwMaxRunTime);
603 
604     *pdwMaxRunTime = This->maxRunTime;
605     return S_OK;
606 }
607 
608 static HRESULT WINAPI MSTASK_IPersistFile_QueryInterface(
609         IPersistFile* iface,
610         REFIID riid,
611         void **ppvObject)
612 {
613     TaskImpl *This = impl_from_IPersistFile(iface);
614     TRACE("(%p, %s, %p)\n", iface, debugstr_guid(riid), ppvObject);
615     return ITask_QueryInterface(&This->ITask_iface, riid, ppvObject);
616 }
617 
618 static ULONG WINAPI MSTASK_IPersistFile_AddRef(
619         IPersistFile* iface)
620 {
621     TaskImpl *This = impl_from_IPersistFile(iface);
622     ULONG ref;
623     TRACE("\n");
624     ref = InterlockedIncrement(&This->ref);
625     return ref;
626 }
627 
628 static ULONG WINAPI MSTASK_IPersistFile_Release(
629         IPersistFile* iface)
630 {
631     TaskImpl *This = impl_from_IPersistFile(iface);
632     ULONG ref;
633     TRACE("\n");
634     ref = InterlockedDecrement(&This->ref);
635     if (ref == 0)
636         TaskDestructor(This);
637     return ref;
638 }
639 
640 static HRESULT WINAPI MSTASK_IPersistFile_GetClassID(
641         IPersistFile* iface,
642         CLSID *pClassID)
643 {
644     FIXME("(%p, %p): stub\n", iface, pClassID);
645     return E_NOTIMPL;
646 }
647 
648 static HRESULT WINAPI MSTASK_IPersistFile_IsDirty(
649         IPersistFile* iface)
650 {
651     FIXME("(%p): stub\n", iface);
652     return E_NOTIMPL;
653 }
654 
655 static HRESULT WINAPI MSTASK_IPersistFile_Load(
656         IPersistFile* iface,
657         LPCOLESTR pszFileName,
658         DWORD dwMode)
659 {
660     FIXME("(%p, %p, 0x%08x): stub\n", iface, pszFileName, dwMode);
661     return E_NOTIMPL;
662 }
663 
664 static HRESULT WINAPI MSTASK_IPersistFile_Save(
665         IPersistFile* iface,
666         LPCOLESTR pszFileName,
667         BOOL fRemember)
668 {
669     FIXME("(%p, %p, %d): stub\n", iface, pszFileName, fRemember);
670     WARN("Returning S_OK but not writing to disk: %s %d\n",
671             debugstr_w(pszFileName), fRemember);
672     return S_OK;
673 }
674 
675 static HRESULT WINAPI MSTASK_IPersistFile_SaveCompleted(
676         IPersistFile* iface,
677         LPCOLESTR pszFileName)
678 {
679     FIXME("(%p, %p): stub\n", iface, pszFileName);
680     return E_NOTIMPL;
681 }
682 
683 static HRESULT WINAPI MSTASK_IPersistFile_GetCurFile(
684         IPersistFile* iface,
685         LPOLESTR *ppszFileName)
686 {
687     FIXME("(%p, %p): stub\n", iface, ppszFileName);
688     return E_NOTIMPL;
689 }
690 
691 
692 static const ITaskVtbl MSTASK_ITaskVtbl =
693 {
694     MSTASK_ITask_QueryInterface,
695     MSTASK_ITask_AddRef,
696     MSTASK_ITask_Release,
697     MSTASK_ITask_CreateTrigger,
698     MSTASK_ITask_DeleteTrigger,
699     MSTASK_ITask_GetTriggerCount,
700     MSTASK_ITask_GetTrigger,
701     MSTASK_ITask_GetTriggerString,
702     MSTASK_ITask_GetRunTimes,
703     MSTASK_ITask_GetNextRunTime,
704     MSTASK_ITask_SetIdleWait,
705     MSTASK_ITask_GetIdleWait,
706     MSTASK_ITask_Run,
707     MSTASK_ITask_Terminate,
708     MSTASK_ITask_EditWorkItem,
709     MSTASK_ITask_GetMostRecentRunTime,
710     MSTASK_ITask_GetStatus,
711     MSTASK_ITask_GetExitCode,
712     MSTASK_ITask_SetComment,
713     MSTASK_ITask_GetComment,
714     MSTASK_ITask_SetCreator,
715     MSTASK_ITask_GetCreator,
716     MSTASK_ITask_SetWorkItemData,
717     MSTASK_ITask_GetWorkItemData,
718     MSTASK_ITask_SetErrorRetryCount,
719     MSTASK_ITask_GetErrorRetryCount,
720     MSTASK_ITask_SetErrorRetryInterval,
721     MSTASK_ITask_GetErrorRetryInterval,
722     MSTASK_ITask_SetFlags,
723     MSTASK_ITask_GetFlags,
724     MSTASK_ITask_SetAccountInformation,
725     MSTASK_ITask_GetAccountInformation,
726     MSTASK_ITask_SetApplicationName,
727     MSTASK_ITask_GetApplicationName,
728     MSTASK_ITask_SetParameters,
729     MSTASK_ITask_GetParameters,
730     MSTASK_ITask_SetWorkingDirectory,
731     MSTASK_ITask_GetWorkingDirectory,
732     MSTASK_ITask_SetPriority,
733     MSTASK_ITask_GetPriority,
734     MSTASK_ITask_SetTaskFlags,
735     MSTASK_ITask_GetTaskFlags,
736     MSTASK_ITask_SetMaxRunTime,
737     MSTASK_ITask_GetMaxRunTime
738 };
739 
740 static const IPersistFileVtbl MSTASK_IPersistFileVtbl =
741 {
742     MSTASK_IPersistFile_QueryInterface,
743     MSTASK_IPersistFile_AddRef,
744     MSTASK_IPersistFile_Release,
745     MSTASK_IPersistFile_GetClassID,
746     MSTASK_IPersistFile_IsDirty,
747     MSTASK_IPersistFile_Load,
748     MSTASK_IPersistFile_Save,
749     MSTASK_IPersistFile_SaveCompleted,
750     MSTASK_IPersistFile_GetCurFile
751 };
752 
753 HRESULT TaskConstructor(LPCWSTR pwszTaskName, LPVOID *ppObj)
754 {
755     TaskImpl *This;
756     int n;
757 
758     TRACE("(%s, %p)\n", debugstr_w(pwszTaskName), ppObj);
759 
760     This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
761     if (!This)
762         return E_OUTOFMEMORY;
763 
764     This->ITask_iface.lpVtbl = &MSTASK_ITaskVtbl;
765     This->IPersistFile_iface.lpVtbl = &MSTASK_IPersistFileVtbl;
766     This->ref = 1;
767     n = (lstrlenW(pwszTaskName) + 1) * sizeof(WCHAR);
768     This->taskName = HeapAlloc(GetProcessHeap(), 0, n);
769     if (!This->taskName)
770     {
771         HeapFree(GetProcessHeap(), 0, This);
772         return E_OUTOFMEMORY;
773     }
774     lstrcpyW(This->taskName, pwszTaskName);
775     This->applicationName = NULL;
776     This->parameters = NULL;
777     This->comment = NULL;
778     This->accountName = NULL;
779 
780     /* Default time is 3 days = 259200000 ms */
781     This->maxRunTime = 259200000;
782 
783     *ppObj = &This->ITask_iface;
784     InterlockedIncrement(&dll_ref);
785     return S_OK;
786 }
787