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