widl: Use the output buffer functions to write typelibs.
[wine] / dlls / mstask / task_trigger.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 <stdarg.h>
20 #include "winternl.h"
21 #include "mstask_private.h"
22 #include "wine/debug.h"
23
24 WINE_DEFAULT_DEBUG_CHANNEL(mstask);
25
26 static HRESULT WINAPI MSTASK_ITaskTrigger_QueryInterface(
27         ITaskTrigger* iface,
28         REFIID riid,
29         void **ppvObject)
30 {
31     TaskTriggerImpl *This = (TaskTriggerImpl *)iface;
32
33     TRACE("IID: %s\n", debugstr_guid(riid));
34     if (ppvObject == NULL)
35         return E_POINTER;
36
37     if (IsEqualGUID(riid, &IID_IUnknown) ||
38             IsEqualGUID(riid, &IID_ITaskTrigger))
39     {
40         *ppvObject = &This->lpVtbl;
41         ITaskTrigger_AddRef(iface);
42         return S_OK;
43     }
44
45     WARN("Unknown interface: %s\n", debugstr_guid(riid));
46     *ppvObject = NULL;
47     return E_NOINTERFACE;
48 }
49
50 static ULONG WINAPI MSTASK_ITaskTrigger_AddRef(
51         ITaskTrigger* iface)
52 {
53     TaskTriggerImpl *This = (TaskTriggerImpl *)iface;
54     ULONG ref;
55     TRACE("\n");
56     ref = InterlockedIncrement(&This->ref);
57     return ref;
58 }
59
60 static ULONG WINAPI MSTASK_ITaskTrigger_Release(
61         ITaskTrigger* iface)
62 {
63     TaskTriggerImpl *This = (TaskTriggerImpl *)iface;
64     ULONG ref;
65     TRACE("\n");
66     ref = InterlockedDecrement(&This->ref);
67     if (ref == 0)
68     {
69         HeapFree(GetProcessHeap(), 0, This);
70         InterlockedDecrement(&dll_ref);
71     }
72     return ref;
73 }
74
75 static HRESULT WINAPI MSTASK_ITaskTrigger_SetTrigger(
76         ITaskTrigger* iface,
77         const PTASK_TRIGGER pTrigger)
78 {
79     TaskTriggerImpl * This = (TaskTriggerImpl *)iface;
80     TIME_FIELDS field_time;
81     LARGE_INTEGER sys_time;
82     TASK_TRIGGER tmp_trigger_cond;
83
84     TRACE("(%p, %p)\n", iface, pTrigger);
85
86     /* Verify valid structure size */
87     if (pTrigger->cbTriggerSize != sizeof(*pTrigger))
88         return E_INVALIDARG;
89     tmp_trigger_cond.cbTriggerSize = pTrigger->cbTriggerSize;
90
91     /* Reserved field must be zero */
92     tmp_trigger_cond.Reserved1 = 0;
93
94     /* Verify and set valid start date and time */
95     memset(&field_time, 0, sizeof(field_time));
96     field_time.Year = pTrigger->wBeginYear;
97     field_time.Month = pTrigger->wBeginMonth;
98     field_time.Day = pTrigger->wBeginDay;
99     field_time.Hour = pTrigger->wStartHour;
100     field_time.Minute = pTrigger->wStartMinute;
101     if (!RtlTimeFieldsToTime(&field_time, &sys_time))
102         return E_INVALIDARG;
103     tmp_trigger_cond.wBeginYear = pTrigger->wBeginYear;
104     tmp_trigger_cond.wBeginMonth = pTrigger->wBeginMonth;
105     tmp_trigger_cond.wBeginDay = pTrigger->wBeginDay;
106     tmp_trigger_cond.wStartHour = pTrigger->wStartHour;
107     tmp_trigger_cond.wStartMinute = pTrigger->wStartMinute;
108
109     /* Verify valid end date if TASK_TRIGGER_FLAG_HAS_END_DATE flag is set */
110     if (pTrigger->rgFlags & TASK_TRIGGER_FLAG_HAS_END_DATE)
111     {
112         memset(&field_time, 0, sizeof(field_time));
113         field_time.Year = pTrigger->wEndYear;
114         field_time.Month = pTrigger->wEndMonth;
115         field_time.Day = pTrigger->wEndDay;
116         if (!RtlTimeFieldsToTime(&field_time, &sys_time))
117             return E_INVALIDARG;
118     }
119
120     /* Set valid end date independent of TASK_TRIGGER_FLAG_HAS_END_DATE flag */
121     tmp_trigger_cond.wEndYear = pTrigger->wEndYear;
122     tmp_trigger_cond.wEndMonth = pTrigger->wEndMonth;
123     tmp_trigger_cond.wEndDay = pTrigger->wEndDay;
124
125     /* Verify duration and interval pair */
126     if (pTrigger->MinutesDuration <= pTrigger->MinutesInterval &&
127             pTrigger->MinutesInterval > 0)
128         return E_INVALIDARG;
129     if (pTrigger->MinutesDuration > 0 && pTrigger->MinutesInterval == 0)
130         return E_INVALIDARG;
131     tmp_trigger_cond.MinutesDuration = pTrigger->MinutesDuration;
132     tmp_trigger_cond.MinutesInterval = pTrigger->MinutesInterval;
133
134     /* Copy over flags */
135     tmp_trigger_cond.rgFlags = pTrigger->rgFlags;
136
137     /* Set TriggerType dependent fields of Type union */
138     tmp_trigger_cond.TriggerType = pTrigger->TriggerType;
139     switch (pTrigger->TriggerType)
140     {
141         case TASK_TIME_TRIGGER_DAILY:
142             tmp_trigger_cond.Type.Daily.DaysInterval =
143                     pTrigger->Type.Daily.DaysInterval;
144             break;
145         case TASK_TIME_TRIGGER_WEEKLY:
146             tmp_trigger_cond.Type.Weekly.WeeksInterval =
147                     pTrigger->Type.Weekly.WeeksInterval;
148             tmp_trigger_cond.Type.Weekly.rgfDaysOfTheWeek =
149                     pTrigger->Type.Weekly.rgfDaysOfTheWeek;
150             break;
151         case TASK_TIME_TRIGGER_MONTHLYDATE:
152             tmp_trigger_cond.Type.MonthlyDate.rgfDays =
153                     pTrigger->Type.MonthlyDate.rgfDays;
154             tmp_trigger_cond.Type.MonthlyDate.rgfMonths =
155                     pTrigger->Type.MonthlyDate.rgfMonths;
156             break;
157         case TASK_TIME_TRIGGER_MONTHLYDOW:
158             tmp_trigger_cond.Type.MonthlyDOW.wWhichWeek =
159                     pTrigger->Type.MonthlyDOW.wWhichWeek;
160             tmp_trigger_cond.Type.MonthlyDOW.rgfDaysOfTheWeek =
161                     pTrigger->Type.MonthlyDOW.rgfDaysOfTheWeek;
162             tmp_trigger_cond.Type.MonthlyDOW.rgfMonths =
163                     pTrigger->Type.MonthlyDOW.rgfMonths;
164             break;
165         case TASK_TIME_TRIGGER_ONCE:
166         case TASK_EVENT_TRIGGER_ON_IDLE:
167         case TASK_EVENT_TRIGGER_AT_SYSTEMSTART:
168         case TASK_EVENT_TRIGGER_AT_LOGON:
169         default:
170             tmp_trigger_cond.Type = This->triggerCond.Type;
171             break;
172     }
173
174     /* Reserved field must be zero */
175     tmp_trigger_cond.Reserved2 = 0;
176
177     /* wRandomMinutesInterval not currently used and is initialized to zero */
178     tmp_trigger_cond.wRandomMinutesInterval = 0;
179
180     /* Update object copy of triggerCond */
181     This->triggerCond = tmp_trigger_cond;
182
183     return S_OK;
184 }
185
186 static HRESULT WINAPI MSTASK_ITaskTrigger_GetTrigger(
187         ITaskTrigger* iface,
188         PTASK_TRIGGER pTrigger)
189 {
190     TaskTriggerImpl * This = (TaskTriggerImpl *)iface;
191
192     TRACE("(%p, %p)\n", iface, pTrigger);
193
194     /* Native implementation doesn't verify equivalent cbTriggerSize fields */
195
196     /* Copy relevant fields of the structure */
197     pTrigger->cbTriggerSize = This->triggerCond.cbTriggerSize;
198     pTrigger->Reserved1 = 0;
199     pTrigger->wBeginYear = This->triggerCond.wBeginYear;
200     pTrigger->wBeginMonth = This->triggerCond.wBeginMonth;
201     pTrigger->wBeginDay = This->triggerCond.wBeginDay;
202     pTrigger->wEndYear = This->triggerCond.wEndYear;
203     pTrigger->wEndMonth = This->triggerCond.wEndMonth;
204     pTrigger->wEndDay = This->triggerCond.wEndDay;
205     pTrigger->wStartHour = This->triggerCond.wStartHour;
206     pTrigger->wStartMinute = This->triggerCond.wStartMinute;
207     pTrigger->MinutesDuration = This->triggerCond.MinutesDuration;
208     pTrigger->MinutesInterval = This->triggerCond.MinutesInterval;
209     pTrigger->rgFlags = This->triggerCond.rgFlags;
210     pTrigger->TriggerType = This->triggerCond.TriggerType;
211     switch (This->triggerCond.TriggerType)
212     {
213         case TASK_TIME_TRIGGER_DAILY:
214             pTrigger->Type.Daily.DaysInterval =
215                     This->triggerCond.Type.Daily.DaysInterval;
216             break;
217         case TASK_TIME_TRIGGER_WEEKLY:
218             pTrigger->Type.Weekly.WeeksInterval =
219                     This->triggerCond.Type.Weekly.WeeksInterval;
220             pTrigger->Type.Weekly.rgfDaysOfTheWeek =
221                     This->triggerCond.Type.Weekly.rgfDaysOfTheWeek;
222             break;
223         case TASK_TIME_TRIGGER_MONTHLYDATE:
224             pTrigger->Type.MonthlyDate.rgfDays =
225                     This->triggerCond.Type.MonthlyDate.rgfDays;
226             pTrigger->Type.MonthlyDate.rgfMonths =
227                     This->triggerCond.Type.MonthlyDate.rgfMonths;
228             break;
229         case TASK_TIME_TRIGGER_MONTHLYDOW:
230             pTrigger->Type.MonthlyDOW.wWhichWeek =
231                     This->triggerCond.Type.MonthlyDOW.wWhichWeek;
232             pTrigger->Type.MonthlyDOW.rgfDaysOfTheWeek =
233                     This->triggerCond.Type.MonthlyDOW.rgfDaysOfTheWeek;
234             pTrigger->Type.MonthlyDOW.rgfMonths =
235                     This->triggerCond.Type.MonthlyDOW.rgfMonths;
236             break;
237         case TASK_TIME_TRIGGER_ONCE:
238         case TASK_EVENT_TRIGGER_ON_IDLE:
239         case TASK_EVENT_TRIGGER_AT_SYSTEMSTART:
240         case TASK_EVENT_TRIGGER_AT_LOGON:
241         default:
242             break;
243     }
244     pTrigger->Reserved2 = 0;
245     pTrigger->wRandomMinutesInterval = 0;
246     return S_OK;
247 }
248
249 static HRESULT WINAPI MSTASK_ITaskTrigger_GetTriggerString(
250         ITaskTrigger* iface,
251         LPWSTR *ppwszTrigger)
252 {
253     FIXME("Not implemented\n");
254     return E_NOTIMPL;
255 }
256
257 static const ITaskTriggerVtbl MSTASK_ITaskTriggerVtbl =
258 {
259     MSTASK_ITaskTrigger_QueryInterface,
260     MSTASK_ITaskTrigger_AddRef,
261     MSTASK_ITaskTrigger_Release,
262     MSTASK_ITaskTrigger_SetTrigger,
263     MSTASK_ITaskTrigger_GetTrigger,
264     MSTASK_ITaskTrigger_GetTriggerString
265 };
266
267 HRESULT TaskTriggerConstructor(LPVOID *ppObj)
268 {
269     TaskTriggerImpl *This;
270     SYSTEMTIME time;
271     TRACE("(%p)\n", ppObj);
272
273     This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This));
274     if (!This)
275         return E_OUTOFMEMORY;
276
277     This->lpVtbl = &MSTASK_ITaskTriggerVtbl;
278     This->ref = 1;
279
280     /* Most fields of triggerCond default to zero.  Initialize other
281      * fields to default values. */
282     memset(&This->triggerCond, 0, sizeof(TASK_TRIGGER));
283     GetLocalTime(&time);
284     This->triggerCond.cbTriggerSize = sizeof(This->triggerCond);
285     This->triggerCond.wBeginYear = time.wYear;
286     This->triggerCond.wBeginMonth = time.wMonth;
287     This->triggerCond.wBeginDay = time.wDay;
288     This->triggerCond.wStartHour = time.wHour;
289     This->triggerCond.wStartMinute = time.wMinute;
290     This->triggerCond.rgFlags = TASK_TRIGGER_FLAG_DISABLED;
291     This->triggerCond.TriggerType = TASK_TIME_TRIGGER_DAILY,
292     This->triggerCond.Type.Daily.DaysInterval = 1;
293
294     *ppObj = &This->lpVtbl;
295     InterlockedIncrement(&dll_ref);
296     return S_OK;
297 }