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